Computer >> Hướng Dẫn Máy Tính >  >> Điện Thoại Thông Minh >> iPhone

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Trong hướng dẫn trước, bạn đã học cách thêm Bluetooth vào ứng dụng Particle Xenon. Cách đó cho phép điều khiển LED RGB onboard từ app test như nRF Connect hoặc Light Blue Explorer.

Trong bài này, chúng ta tiến xa hơn. Chúng ta sẽ phát triển ứng dụng Swift để điều khiển LED RGB Particle Mesh. Nếu mọi thứ suôn sẻ, bạn sẽ có app hoạt động trong khoảng 20 phút!

Hãy bắt đầu.

Không có thời gian đọc bài viết đầy đủ ngay?

Tải phiên bản PDF tại đây.

Thiết lập

  • Cài Xcode. Tải từ App Store tại đây.
  • Cũng cần tài khoản Apple. Tôi dùng email iCloud. Bạn có thể tạo tài khoản mới trong Xcode nếu chưa có.
  • Cài mã ví dụ RGB lên board Particle Mesh.

Tạo dự án

Sau khi cài xong, đến phần vui!

Mở Xcode vào File → New Project.

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Chọn Single View App.

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Cập nhật Project Name theo ý thích. Tôi cũng đổi organization identifier thành com.jaredwolff. Sửa theo ý bạn!

Chọn vị trí lưu.

Tiếp theo tìm Info.plist.

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Cập nhật info.plist bằng cách thêm Privacy - Bluetooth Peripheral Usage Description

Mô tả tôi dùng: App uses Bluetooth to connect to the Particle Xenon RGB Example

Điều này cho phép dùng Bluetooth trong app nếu muốn phát hành.

Bây giờ, hãy làm mọi thứ hoạt động tối thiểu!

Tối thiểu hoạt động

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Tiếp theo, tạo app tối thiểu để kết nối và khám phá dịch vụ (services discovery). Hầu hết hành động xảy ra trong ViewController.swift.

Trước hết import CoreBluetooth

import CoreBluetooth

Điều này cho phép điều khiển chức năng Bluetooth Low Energy trong iOS. Sau đó thêm cả CBPeripheralDelegate và CBCentralManagerDelegate vào class ViewController.

class ViewController: UIViewController, CBPeripheralDelegate, CBCentralManagerDelegate {

Tạo biến private cục bộ lưu central manager và peripheral thực tế. Sẽ thiết lập thêm sau.

// Properties
private var centralManager: CBCentralManager!
private var peripheral: CBPeripheral!

Trong hàm viewDidLoad, khởi tạo centralManager

centralManager = CBCentralManager(delegate: self, queue: nil)

Thiết lập delegate: self quan trọng. Nếu không, trạng thái central không bao giờ thay đổi khi khởi động.

Trước khi tiến xa, tạo file riêng tên ParticlePeripheral.swift. Có thể đặt đâu nhưng tôi để trong 'group' riêng tên Models cho sau.

Bên trong tạo biến public chứa UUID cho Particle Board. Chúng trông quen thuộc!

import UIKit
import CoreBluetooth

class ParticlePeripheral: NSObject {
    /// MARK: - Particle LED services và characteristics Identifiers
    public static let particleLEDServiceUUID = CBUUID(string: "b4250400-fb4b-4746-b2b0-93f0e61122c6")
    public static let redLEDCharacteristicUUID = CBUUID(string: "b4250401-fb4b-4746-b2b0-93f0e61122c6")
    public static let greenLEDCharacteristicUUID = CBUUID(string: "b4250402-fb4b-4746-b2b0-93f0e61122c6")
    public static let blueLEDCharacteristicUUID = CBUUID(string: "b4250403-fb4b-4746-b2b0-93f0e61122c6")
}

Quay lại ViewController.swift ghép các phần Bluetooth.

Các phần Bluetooth

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Mọi thứ về Bluetooth dựa trên sự kiện (event based). Chúng ta sẽ định nghĩa một số hàm xử lý sự kiện. Những hàm quan trọng:

  • centralManagerDidUpdateState cập nhật khi Bluetooth Peripheral bật/tắt. Sẽ kích hoạt khi app khởi động để biết trạng thái Bluetooth. Chúng ta cũng bắt đầu quét (scan) ở đây.
  • Sự kiện centralManager didDiscover xảy ra khi nhận kết quả quét. Dùng để bắt đầu kết nối.
  • Sự kiện centralManager didConnect kích hoạt khi thiết bị kết nối. Bắt đầu khám phá thiết bị (device discovery) ở đây. Lưu ý: Device discovery là cách xác định service và characteristic nào khả dụng. Cách tốt xác nhận loại thiết bị kết nối.
  • Sự kiện peripheral didDiscoverServices kích hoạt khi tất cả service được khám phá. Chú ý chuyển từ centralManager sang peripheral vì đã kết nối. Bắt đầu khám phá characteristic ở đây. Sẽ dùng RGB service UUID làm target.
  • Sự kiện peripheral didDiscoverCharacteristicsFor cung cấp tất cả characteristic dùng service UUID cung cấp. Đây là bước cuối trong chuỗi device discovery đầy đủ. Hơi rối nhưng chỉ làm một lần khi kết nối!

Định nghĩa tất cả hàm Bluetooth.

Bây giờ biết các sự kiện hàm được kích hoạt. Định nghĩa theo thứ tự logic xảy ra trong chu kỳ kết nối.

Đầu tiên, định nghĩa centralManagerDidUpdateState để bắt đầu quét thiết bị với Particle RGB LED Service. Nếu Bluetooth không bật, không làm gì.

// Nếu bật nguồn, bắt đầu quét
func centralManagerDidUpdateState(_ central: CBCentralManager) {
    print("Central state update")
    if central.state != .poweredOn {
        print("Central is not powered on")
    } else {
        print("Central scanning for", ParticlePeripheral.particleLEDServiceUUID)
        centralManager.scanForPeripherals(withServices: [ParticlePeripheral.particleLEDServiceUUID], options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
    }
}

Định nghĩa centralManager didDiscover là bước tiếp theo. Chúng ta biết đã tìm thấy thiết bị nếu sự kiện này xảy ra.

// Xử lý kết quả quét
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) {
    // Tìm thấy nên dừng quét
    self.centralManager.stopScan()
    // Copy instance peripheral
    self.peripheral = peripheral
    self.peripheral.delegate = self
    // Kết nối!
    self.centralManager.connect(self.peripheral, options: nil)
}

Vậy, dừng quét bằng self.centralManager.stopScan(). Set peripheral để tồn tại qua app. Sau đó kết nối thiết bị bằng self.centralManager.connect

Khi đã kết nối, cần kiểm tra lại xem có đúng thiết bị không.

// Handler khi kết nối thành công
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
    if peripheral == self.peripheral {
        print("Connected to your Particle Board")
        peripheral.discoverServices([ParticlePeripheral.particleLEDServiceUUID])
    }
}

Bằng cách so sánh hai peripheral, biết đó là thiết bị tìm thấy trước. Khởi động services discovery dùng peripheral.discoverService. Có thể dùng ParticlePeripheral.particleLEDServiceUUID làm tham số. Như vậy không nhặt các service không quan tâm.

Khi kết thúc khám phá service, nhận sự kiện didDiscoverServices. Duyệt qua tất cả service "có sẵn". (Mặc dù chỉ có một!)

// Xử lý sự kiện khám phá
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
    if let services = peripheral.services {
        for service in services {
            if service.uuid == ParticlePeripheral.particleLEDServiceUUID {
                print("LED service found")
                // Bây giờ khởi động khám phá characteristic
                peripheral.discoverCharacteristics([ParticlePeripheral.redLEDCharacteristicUUID, ParticlePeripheral.greenLEDCharacteristicUUID, ParticlePeripheral.blueLEDCharacteristicUUID], for: service)
                return
            }
        }
    }
}

Lúc này là lần thứ ba kiểm tra đảm bảo service đúng. Điều này hữu ích sau khi có nhiều characteristic và service.

Gọi peripheral.discoverCharacteristics với mảng UUID characteristic tìm kiếm. Chúng là tất cả UUID định nghĩa trong ParticlePeripheral.swift.

Cuối cùng, xử lý sự kiện didDiscoverCharacteristicsFor. Duyệt qua tất cả characteristic có sẵn. Khi duyệt so sánh với những thứ tìm kiếm.

// Xử lý khám phá characteristic
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
    if let characteristics = service.characteristics {
        for characteristic in characteristics {
            if characteristic.uuid == ParticlePeripheral.redLEDCharacteristicUUID {
                print("Red LED characteristic found")
            } else if characteristic.uuid == ParticlePeripheral.greenLEDCharacteristicUUID {
                print("Green LED characteristic found")
            } else if characteristic.uuid == ParticlePeripheral.blueLEDCharacteristicUUID {
                print("Blue LED characteristic found")
            }
        }
    }
}

Đến đây đã sẵn sàng device discovery đầy đủ cho Particle Mesh. Phần sau test xem có hoạt động không.

Test ví dụ tối thiểu

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Trước khi bắt đầu, nếu gặp khó khăn, tôi để bước troubleshooting ở footnote.

Để test, cần iPhone có Bluetooth Low Energy. Hầu hết iPhone hiện đại đều có. iPhone cuối không có theo tôi nhớ là iPhone 4 hoặc 3Gs. (vì vậy bạn chắc chắn ổn)

Đầu tiên, cắm vào máy tính.

Đi đến trên cùng nút play/stop. Chọn target device. Trường hợp tôi chọn điện thoại (Jared's iPhone). Cũng có thể dùng iPad.

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Sau đó nhấn Command + R hoặc nút Play để nạp app vào điện thoại.

Đảm bảo tab log mở. Bật bằng nút bottom pane góc trên phải.

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Đảm bảo có mesh device chạy mã ví dụ. Có thể vào bài trước để lấy. Nhớ board Particle Mesh cần chạy device OS 1.3.0 trở lên để Bluetooth hoạt động!

Khi cả firmware và app đã nạp, kiểm tra log output.

Nên trông như sau:

View loaded
Central state update
Central scanning for B4250400-FB4B-4746-B2B0-93F0E61122C6
Connected to your Particle Board
LED service found
Red LED characteristic found
Green LED characteristic found
Blue LED characteristic found

Điện thoại đã kết nối, tìm thấy LED service! Các characteristic cũng được khám phá quan trọng. Không có chúng thì không gửi dữ liệu đến mesh device.

Bước tiếp theo tạo slider để cập nhật giá trị RGB trên bay.

Slide trái, slide phải.

Tiếp theo thêm element vào Main.storyboard. Mở Main.storyboard click vào View dưới View Controller.

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Click nút Library. (Trông như nút home cũ của Apple)

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Popup hiện ra với tất cả lựa chọn chèn vào app.

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Kéo thả ba Labels và ba Sliders vào view.

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Double click label đổi tên.

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Click và giữ, công cụ căn chỉnh hiện ra. Chúng thậm chí snap vào giữa!

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Có thể chọn tất cả di chuyển cùng lúc. Căn chỉnh dọc và ngang.

Để chúng giữ giữa, bỏ thuộc tính autoresizing. Click icon Ruler góc trên phải. Click từng thanh đỏ. Điều này đảm bảo label và slider ở trên màn hình!

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Click nút Show Assistant Editor. (Trông như biểu đồ Venn)

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Lưu ý: đảm bảo ViewController.swift mở trong Assistant Editor.

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Dưới phần /properties, Control-click và kéo Red Slider vào code.

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Lặp lại cho các slider còn lại. Đảm bảo đặt tên khác nhau. Code trông như sau khi xong:

// Properties
private var centralManager: CBCentralManager!
private var peripheral: CBPeripheral!
// Sliders
@IBOutlet weak var redSlider: UISlider!
@IBOutlet weak var greenSlider: UISlider!
@IBOutlet weak var blueSlider: UISlider!

Điều này cho phép truy cập giá trị slider.

Tiếp theo, gắn sự kiện Value Changed cho mỗi slider. Right click vào Red Slider trong folder view.

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Sẽ có tùy chọn sự kiện. Kéo thả Value Changed vào code. Đặt tên có ý nghĩa. Tôi dùng RedSliderChanged cho Red Slider.

Lặp lại hai lần nữa. Code cuối bước này:

@IBAction func RedSliderChanged(_ sender: Any) { }
@IBAction func GreenSliderChanged(_ sender: Any) { }
@IBAction func BlueSliderChanged(_ sender: Any) { }

Tôi cũng chọn từng slider và bỏ tick Enabled. Vậy bạn không kéo được. Sẽ bật sau trong code.

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Cũng là lúc tốt đổi giá trị tối đa thành 255. Đặt giá trị mặc định từ 0.5 thành 0.

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Quay lại đầu file. Tạo biến cục bộ cho mỗi characteristic. Dùng để ghi giá trị slider lên Particle Mesh board.

// Characteristics
private var redChar: CBCharacteristic?
private var greenChar: CBCharacteristic?
private var blueChar: CBCharacteristic?

Bây giờ gắn mọi thứ!

Trong callback didDiscoverCharacteristicsFor. Gán characteristic đó. Ví dụ

if characteristic.uuid == ParticlePeripheral.redLEDCharacteristicUUID {
    print("Red LED characteristic found")
    redChar = characteristic
}

Khi tìm thấy mỗi characteristic, cũng bật slider tại chỗ đó.

// Bật red slider
redSlider.isEnabled = true

Cuối cùng didDiscoverCharacteristicsFor trông như:

// Xử lý khám phá characteristic
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
    if let characteristics = service.characteristics {
        for characteristic in characteristics {
            if characteristic.uuid == ParticlePeripheral.redLEDCharacteristicUUID {
                print("Red LED characteristic found")
                redChar = characteristic
                redSlider.isEnabled = true
            } else if characteristic.uuid == ParticlePeripheral.greenLEDCharacteristicUUID {
                print("Green LED characteristic found")
                greenChar = characteristic
                greenSlider.isEnabled = true
            } else if characteristic.uuid == ParticlePeripheral.blueLEDCharacteristicUUID {
                print("Blue LED characteristic found")
                blueChar = characteristic
                blueSlider.isEnabled = true
            }
        }
    }
}

Bây giờ cập nhật hàm RedSliderChanged GreenSliderChanged và BlueSliderChanged. Mục đích cập nhật characteristic liên quan với hàm Changed. Tôi tạo hàm riêng writeLEDValueToChar. Truyền characteristic và data.

private func writeLEDValueToChar(withCharacteristic characteristic: CBCharacteristic, withValue value: Data) {
    // Kiểm tra có property write không
    if characteristic.properties.contains(.writeWithoutResponse) && peripheral != nil {
        peripheral.writeValue(value, for: characteristic, type: .withoutResponse)
    }
}

Thêm gọi writeLEDValueToChar vào từng hàm Changed. Phép cast giá trị thành UInt8. (Particle Mesh device kỳ vọng số 8-bit không dấu.)

@IBAction func RedSliderChanged(_ sender: Any) {
    print("red:", redSlider.value)
    let slider: UInt8 = UInt8(redSlider.value)
    writeLEDValueToChar(withCharacteristic: redChar!, withValue: Data([slider]))
}

Lặp lại cho GreenSliderChanged và BlueSliderChanged. Đảm bảo đổi red thành green và blue cho từng cái!

Cuối cùng, để code gọn, thêm hàm xử lý ngắt kết nối Bluetooth.

func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {

Bên trong, reset slider về 0 và disable.

if peripheral == self.peripheral {
    print("Disconnected")
    redSlider.isEnabled = false
    greenSlider.isEnabled = false
    blueSlider.isEnabled = false
    redSlider.value = 0
    greenSlider.value = 0
    blueSlider.value = 0
}

Ý hay reset self.peripheral về nil để không bao giờ ghi vào thiết bị ma.

self.peripheral = nil

Cuối cùng, vì đã ngắt kết nối, quét lại!

// Bắt đầu quét lại
print("Central scanning for", ParticlePeripheral.particleLEDServiceUUID)
centralManager.scanForPeripherals(withServices: [ParticlePeripheral.particleLEDServiceUUID], options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
}

Xong! Gần như sẵn sàng test. Sang bước cuối.

Test các slider.

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Việc khó đã xong. Giờ đến lúc chơi!

Cách dễ nhất test là click nút Play góc trên trái hoặc phím tắt Command + R. Xcode nạp app vào điện thoại. Bạn thấy màn hình trắng rồi màn hình có slider!

Slider nên xám cho đến khi kết nối Particle Mesh board. Kiểm tra log output xem đã kết nối chưa.

View loaded
Central state update
Central scanning for B4250400-FB4B-4746-B2B0-93F0E61122C6
Connected to your Particle Board
LED service found
Red LED characteristic found
Green LED characteristic found
Blue LED characteristic found

(Quen thuộc? Đã kết nối!)

Nếu làm đúng mọi thứ, bạn có thể kéo slider. Tốt hơn, LED RGB trên Particle Mesh board đổi màu.

Xây dựng ứng dụng Swift Bluetooth điều khiển LED RGB Particle Mesh trong 20 phút

Kết luận

Trong bài này bạn học cách kết nối Particle Mesh board và thiết bị iOS qua Bluetooth. Học cách kết nối từng characteristic. Thêm vào đó, tạo giao diện sạch để làm tất cả.

Như bạn tưởng tượng, có thể đào sâu Bluetooth trên iOS. Còn nhiều hơn trong hướng dẫn sắp tới: The Ultimate Guide to Particle Mesh. Subscriber danh sách tôi truy cập nội dung pre-launch và giảm giá khi ra mắt! Click đây để đăng ký.

Mã nguồn

Mã nguồn đầy đủ trên Github. Nếu hữu ích, bấm nút star. ⭐️