Trong hướng dẫn trước, bạn đã học cách thêm Bluetooth vào ứng dụng Particle Xenon. Bằng cách đó, bạn có thể điều khiển đèn LED RGB trên bo mạch từ một ứng dụng thử nghiệm như nRF Connect hoặc Light Blue Explorer.
Trong bài đăng này, chúng ta sẽ tiến thêm một bước nữa. Chúng tôi sẽ phát triển một ứng dụng Swift để điều khiển đèn LED Particle Mesh RGB. Nếu mọi việc suôn sẻ, bạn sẽ có một ứng dụng hoạt động trong khoảng 20 phút!
Hãy bắt đầu.
Bạn không có thời gian ngay bây giờ để đọc toàn bộ bài viết?
Tải xuống phiên bản PDF tại đây.
Thiết lập
- Cài đặt Xcode. Bạn có thể tải xuống từ App store tại đây.
- Bạn cũng sẽ cần đăng nhập Apple. Tôi sử dụng email iCloud của mình. Bạn có thể tạo tài khoản mới trong Xcode nếu chưa có.
- Cài đặt mã ví dụ RGB trên bảng Mesh hạt.
Tạo dự án
Sau khi mọi thứ đã được cài đặt, hãy bắt đầu những thứ thú vị!
Mở Xcode và đi tới Tệp → Dự án mới.
Chọn Ứng dụng xem một lần.
Sau đó, cập nhật Tên dự án theo ý thích của bạn. Tôi cũng đã thay đổi số nhận dạng tổ chức của mình thành com.jaredwolff
. Sửa đổi nó khi bạn thấy phù hợp!
Chọn một vị trí để lưu nó.
Tiếp theo, tìm Info.plist của bạn.
Cập nhật info.plist
bằng cách thêm Privacy - Bluetooth Peripheral Usage Description
Mô tả tôi đã sử dụng cuối cùng là App uses Bluetooth to connect to the Particle Xenon RGB Example
Điều này cho phép bạn sử dụng Bluetooth trong ứng dụng của mình nếu bạn muốn phát hành nó.
Bây giờ, hãy làm mọi thứ hoạt động ở mức tối thiểu!
Chức năng tối thiểu
Tiếp theo, chúng ta sẽ có một ứng dụng ít chức năng để kết nối và khám phá dịch vụ. Hầu hết các hành động sẽ xảy ra trong ViewController.swift
.
Cho phép nhập lần đầu tiên CoreBluetooth
import CoreBluetooth
Điều này cho phép chúng tôi kiểm soát chức năng Bluetooth Low Energy trong iOS. Sau đó, hãy thêm cả CBPeripheralDelegate
và CBCentralManagerDelegate
tới ViewController
lớp học.
class ViewController: UIViewController, CBPeripheralDelegate, CBCentralManagerDelegate {
Bây giờ chúng ta hãy tạo các biến riêng cục bộ để lưu trữ trình quản lý trung tâm và thiết bị ngoại vi thực tế. Chúng tôi sẽ thiết lập chúng thêm trong giây lát.
// Properties
private var centralManager: CBCentralManager!
private var peripheral: CBPeripheral!
Trong viewDidLoad
của bạn , hãy bắt đầu centralManager
centralManager = CBCentralManager(delegate: self, queue: nil)
Cài đặt delegate: self
là quan trọng. Nếu không, trạng thái trung tâm không bao giờ thay đổi khi khởi động.
Trước khi đi sâu hơn, hãy tạo một tệp riêng biệt và gọi nó là ParticlePeripheral.swift
. Nó có thể được đặt ở bất cứ đâu nhưng tôi đã đặt nó trong một 'nhóm' riêng biệt được gọi là Mô hình cho sau này.
Bên trong, chúng tôi sẽ tạo một số biến công khai chứa UUID cho Particle Board của chúng tôi. Họ sẽ trông quen thuộc!
import UIKit
import CoreBluetooth
class ParticlePeripheral: NSObject {
/// MARK: - Particle LED services and charcteristics Identifiers
public static let particleLEDServiceUUID = CBUUID.init(string: "b4250400-fb4b-4746-b2b0-93f0e61122c6")
public static let redLEDCharacteristicUUID = CBUUID.init(string: "b4250401-fb4b-4746-b2b0-93f0e61122c6")
public static let greenLEDCharacteristicUUID = CBUUID.init(string: "b4250402-fb4b-4746-b2b0-93f0e61122c6")
public static let blueLEDCharacteristicUUID = CBUUID.init(string: "b4250403-fb4b-4746-b2b0-93f0e61122c6")
}
Quay lại ViewController.swift
hãy ghép các bit Bluetooth lại với nhau.
Bluetooth bit
Mọi thứ cần làm với Bluetooth đều dựa trên sự kiện. Chúng tôi sẽ xác định một số chức năng xử lý các sự kiện này. Đây là những điều quan trọng:
centralManagerDidUpdateState
cập nhật khi Thiết bị ngoại vi Bluetooth được bật hoặc tắt. Nó sẽ kích hoạt khi một ứng dụng khởi động lần đầu tiên để bạn biết trạng thái của Bluetooth. Chúng tôi cũng bắt đầu quét tại đây.
centralManager
didDiscover
sự kiện xảy ra khi bạn nhận được kết quả quét. Chúng tôi sẽ sử dụng điều này để bắt đầu kết nối.
centralManager
didConnect
sự kiện sẽ kích hoạt sau khi thiết bị được kết nối. Chúng tôi sẽ bắt đầu khám phá thiết bị tại đây. Lưu ý: Khám phá thiết bị là cách chúng tôi xác định những dịch vụ và đặc điểm có sẵn. Đây là một cách tốt để xác nhận loại thiết bị mà chúng tôi đang kết nối.
peripheral
didDiscoverServices
sự kiện đầu tiên sau khi tất cả các dịch vụ đã được khám phá. Lưu ý rằng chúng tôi đã chuyển từ centralManager
thành peripheral
bây giờ chúng tôi đã kết nối. Chúng ta sẽ bắt đầu khám phá đặc trưng ở đây. Chúng tôi sẽ sử dụng UUID dịch vụ RGB làm mục tiêu.
peripheral
didDiscoverCharacteristicsFor
sự kiện sẽ cung cấp tất cả các đặc điểm bằng cách sử dụng UUID dịch vụ được cung cấp. Đây là bước cuối cùng trong chuỗi thực hiện khám phá toàn bộ thiết bị. Nó có nhiều lông nhưng chỉ phải thực hiện một lần trong giai đoạn kết nối!
Xác định tất cả các chức năng của Bluetooth.
Bây giờ chúng ta biết những gì các sự kiện hàm được kích hoạt. Chúng tôi sẽ xác định chúng theo thứ tự logic mà chúng xảy ra trong một chu kỳ kết nối.
Đầu tiên, chúng tôi sẽ xác định centralManagerDidUpdateState
để bắt đầu quét thiết bị bằng Dịch vụ LED RGB dạng hạt của chúng tôi. Nếu Bluetooth không được bật, nó sẽ không hoạt động.
// If we're powered on, start scanning
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])
}
}
Xác định centralManager
didDiscover
là bước tiếp theo của chúng tôi trong quá trình này. Chúng tôi biết rằng chúng tôi đã tìm thấy một thiết bị nếu sự kiện này đã xảy ra.
// Handles the result of the scan
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
// We've found it so stop scan
self.centralManager.stopScan()
// Copy the peripheral instance
self.peripheral = peripheral
self.peripheral.delegate = self
// Connect!
self.centralManager.connect(self.peripheral, options: nil)
}
Vì vậy, chúng tôi ngừng quét bằng self.centralManager.stopScan()
. Chúng tôi đặt peripheral
vì vậy nó vẫn tồn tại thông qua ứng dụng. Sau đó, chúng tôi kết nối với thiết bị đó bằng self.centralManager.connect
Sau khi kết nối, chúng tôi cần kiểm tra lại xem chúng tôi có đang làm việc với đúng thiết bị hay không.
// The handler if we do connect succesfully
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 thiết bị ngoại vi, chúng ta sẽ biết nó là thiết bị mà chúng ta đã tìm thấy trước đó. Chúng tôi sẽ bắt đầu khám phá dịch vụ bằng cách sử dụng peripheral.discoverService
. Chúng ta có thể sử dụng ParticlePeripheral.particleLEDServiceUUID
như một tham số. Bằng cách đó, chúng tôi không nhận bất kỳ dịch vụ nào mà chúng tôi không quan tâm.
Khi chúng tôi hoàn thành các dịch vụ khám phá, chúng tôi sẽ nhận được didDiscoverServices
biến cố. Chúng tôi lặp lại tất cả các dịch vụ "có sẵn". (Mặc dù sẽ chỉ có một!)
// Handles discovery event
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")
//Now kick off discovery of characteristics
peripheral.discoverCharacteristics([ParticlePeripheral.redLEDCharacteristicUUID,
ParticlePeripheral.greenLEDCharacteristicUUID,
ParticlePeripheral.blueLEDCharacteristicUUID], for: service)
return
}
}
}
}
Đến thời điểm này, đây là lần thứ ba chúng tôi kiểm tra để đảm bảo rằng chúng tôi có dịch vụ chính xác. Điều này trở nên tiện dụng hơn sau này khi có nhiều đặc điểm và nhiều dịch vụ.
Chúng tôi gọi peripheral.discoverCharacteristics
với một loạt các UUID cho các đặc điểm mà chúng tôi đang tìm kiếm. Chúng là tất cả các UUID mà chúng tôi đã xác định trong ParticlePeripheral.swift
.
Cuối cùng, chúng tôi xử lý didDiscoverCharacteriscsFor
biến cố. Chúng tôi lặp lại tất cả các đặc điểm có sẵn. Khi chúng tôi lặp lại, chúng tôi so sánh với những cái chúng tôi đang tìm kiếm.
// Handling discovery of characteristics
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");
}
}
}
}
Tại thời điểm này, chúng tôi đã sẵn sàng khám phá toàn bộ thiết bị của thiết bị Lưới hạt của chúng tôi. Trong phần tiếp theo, chúng tôi sẽ kiểm tra những gì chúng tôi có để đảm bảo mọi thứ đang hoạt động tốt.
Kiểm tra ví dụ nhỏ nhất của chúng tôi
Trước khi chúng ta bắt đầu, nếu bạn gặp sự cố, tôi đã đưa ra một số bước khắc phục sự cố trong phần chú thích.
Để kiểm tra, bạn sẽ phải có iPhone có Bluetooth Low Energy. Hầu hết các iPhone hiện đại đều có nó. Tôi tin rằng chiếc iPhone cuối cùng không có nó là iPhone 4 hoặc 3G. (vì vậy bạn có thể tốt)
Đầu tiên, hãy cắm nó vào máy tính của bạn.
Lên đầu bằng nút phát và dừng. Chọn thiết bị mục tiêu của bạn. Trong trường hợp của tôi, tôi đã chọn điện thoại của mình (iPhone của Jared ). Bạn cũng có thể sử dụng iPad.
Sau đó, bạn có thể nhấn Command + R hoặc nhấn vào nút Phát đó để tải ứng dụng vào điện thoại của bạn.
Đảm bảo rằng bạn đã mở tab nhật ký của mình. Bật nó bằng cách nhấp vào nút ngăn dưới cùng ở góc trên cùng bên phải.
Đảm bảo rằng bạn đã thiết lập thiết bị lưới và chạy mã ví dụ. Bạn có thể vào bài viết này để lấy nó. Hãy nhớ rằng bảng Particle Mesh của bạn cần phải chạy thiết bị OS 1.3.0 trở lên để Bluetooth hoạt động!
Khi cả phần sụn và ứng dụng được tải, hãy kiểm tra đầu ra nhật ký.
Nó sẽ trông giống như thế này:
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ều này có nghĩa là Điện thoại của bạn đã kết nối, đã tìm thấy dịch vụ LED! Các đặc điểm cũng được phát hiện rất quan trọng ở đây. Nếu không có những thứ đó, chúng tôi sẽ không thể gửi dữ liệu đến thiết bị lưới.
Bước tiếp theo là tạo một số thanh trượt để chúng tôi có thể cập nhật các giá trị RGB một cách nhanh chóng.
Trượt sang trái. Trượt sang phải.
Tiếp theo, chúng tôi sẽ thêm một số phần tử vào Main.storyboard
của chúng tôi . Mở Main.storyboard
và nhấp vào Chế độ xem bên dưới Bộ điều khiển Chế độ xem.
Sau đó, nhấp vào Thư viện cái nút. (Có vẻ như nghệ thuật cũ của Apple đã sử dụng cho nút trang chủ)
Bạn sẽ nhận được một cửa sổ bật lên với tất cả các lựa chọn mà bạn có thể chèn vào ứng dụng của mình.
Kéo ba Nhãn và sao chép ba Thanh trượt theo quan điểm của bạn.
Bạn có thể nhấp đúp vào các nhãn và đổi tên chúng khi bạn tiếp tục.
Nếu bạn nhấp và giữ, một số công cụ căn chỉnh tiện dụng sẽ bật lên. Họ thậm chí sẽ đặt vào trung tâm!
Bạn cũng có thể chọn tất cả và di chuyển chúng cùng nhau. Chúng tôi sẽ căn chỉnh chúng theo chiều dọc và chiều ngang.
Để chúng ở giữa, hãy xóa thuộc tính tự động kích hoạt. Nhấp vào biểu tượng Thước kẻ ở trên cùng bên phải. Sau đó, nhấp vào từng thanh màu đỏ . Điều này sẽ đảm bảo rằng các nhãn và thanh trượt của bạn vẫn ở trên màn hình!
Tiếp theo, hãy nhấp vào Hiển thị trình chỉnh sửa Trợ lý cái nút. (Trông giống như một biểu đồ Venn)
Lưu ý: đảm bảo rằng ViewController.swift đang mở trong Trợ lý biên tập viên của bạn.
Sau đó, bên dưới /properties
phần Control khi nhấp và kéo Thanh trượt màu đỏ vào mã của bạn.
Lặp lại với tất cả những cái khác. Hãy chắc chắn rằng bạn đặt tên cho họ một cái gì đó khác nhau. Mã của bạn sẽ trông như thế này khi bạn hoàn tất:
// 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 chúng tôi truy cập giá trị của các thanh trượt.
Tiếp theo, hãy đính kèm Giá trị đã thay đổi sự kiện cho mỗi thanh trượt. Nhấp chuột phải trên Thanh trượt màu đỏ trong chế độ xem thư mục.
Nó sẽ cung cấp cho bạn một số tùy chọn cho các sự kiện. Nhấp và kéo Giá trị đã thay đổi sự kiện đối với mã của bạn. Hãy chắc chắn rằng bạn đặt tên cho nó một cái gì đó có ý nghĩa. Tôi đã sử dụng RedSliderChanged cho Thanh trượt màu đỏ.
Lặp lại hai lần nữa. Mã của bạn sẽ trông như thế này ở 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 thanh trượt đến và Đã bật bỏ chọn . Bằng cách đó bạn không thể di chuyển chúng. Chúng tôi sẽ kích hoạt chúng sau này trong mã.
Ngoài ra, đây là thời điểm tuyệt vời để thay đổi giá trị tối đa thành 255 . Đồng thời đặt giá trị mặc định từ 0,5 đến 0
Quay lại đầu tệp. Hãy tạo một số biến cục bộ cho mỗi đặc điểm. Chúng tôi sẽ sử dụng những thứ này để có thể viết các biến thanh trượt vào bảng Particle Mesh.
// Characteristics
private var redChar: CBCharacteristic?
private var greenChar: CBCharacteristic?
private var blueChar: CBCharacteristic?
Bây giờ, hãy gắn kết mọi thứ lại với nhau!
Trong didDiscoverCharacteristicsFor
chức năng gọi lại. Hãy gán các đặc điểm đó. Ví dụ
if characteristic.uuid == ParticlePeripheral.redLEDCharacteristicUUID {
print("Red LED characteristic found")
redChar = characteristic
Khi chúng tôi tìm thấy từng đặc điểm, chúng tôi cũng có thể bật từng thanh trượt ở cùng một vị trí.
// Unmask red slider
redSlider.isEnabled = true
Cuối cùng thì didDiscoverCharacteristicsFor
của bạn sẽ giống như sau:
// Handling discovery of characteristics
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ờ, hãy cập nhật RedSliderChanged
GreenSliderChanged
và BlueSliderChanged
chức năng. Những gì chúng tôi muốn làm ở đây là cập nhật đặc tính được liên kết với Changed
hàm số. Tôi đã tạo một hàm riêng có tên là writeLEDValueToChar
. Chúng tôi sẽ chuyển đặc tính và dữ liệu.
private func writeLEDValueToChar( withCharacteristic characteristic: CBCharacteristic, withValue value: Data) {
// Check if it has the write property
if characteristic.properties.contains(.writeWithoutResponse) && peripheral != nil {
peripheral.writeValue(value, for: characteristic, type: .withoutResponse)
}
}
Bây giờ, hãy thêm cuộc gọi tới writeLEDValueToChar
cho mỗi Changed
chức năng. Bạn sẽ phải chuyển giá trị thành Uint8
. (Thiết bị Particle Mesh yêu cầu một 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 điều này cho GreenSliderChanged
và BlueSliderChanged
. Đảm bảo rằng bạn đã thay đổi red
thành green
và blue
cho mỗi!
Cuối cùng, để giữ mọi thứ sạch sẽ, tôi cũng đã thêm một chức năng xử lý các trường hợp ngắt kết nối Bluetooth.
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
Bên trong, chúng ta nên đặt lại trạng thái của các thanh trượt về 0 và vô hiệu hóa chúng.
if peripheral == self.peripheral {
print("Disconnected")
redSlider.isEnabled = false
greenSlider.isEnabled = false
blueSlider.isEnabled = false
redSlider.value = 0
greenSlider.value = 0
blueSlider.value = 0
Bạn nên đặt lại self.peripheral
để không theo cách đó, chúng tôi sẽ không bao giờ cố gắng ghi vào thiết bị ảo.
self.peripheral = nil
Cuối cùng, vì chúng tôi đã ngắt kết nối, hãy bắt đầu quét lại!
// Start scanning again
print("Central scanning for", ParticlePeripheral.particleLEDServiceUUID);
centralManager.scanForPeripherals(withServices: [ParticlePeripheral.particleLEDServiceUUID],
options: [CBCentralManagerScanOptionAllowDuplicatesKey : true])
}
Được rồi! Chúng tôi sắp sẵn sàng để kiểm tra. Hãy chuyển sang bước tiếp theo (và cuối cùng).
Kiểm tra các thanh trượt.
Công việc khó khăn đã hoàn thành. Bây giờ là lúc để chơi!
Cách dễ nhất để kiểm tra mọi thứ là nhấp vào nút Phát ở trên cùng bên trái hoặc Command + R phim tăt. Xcode sẽ tải ứng dụng vào điện thoại của bạn. Bạn sẽ thấy một màn hình trắng được tiếp tục bởi một màn hình có các thanh trượt của bạn!
Các thanh trượt sẽ chuyển sang màu xám cho đến khi được kết nối với bảng Lưới hạt của bạn. Bạn có thể kiểm tra đầu ra nhật ký của mình nếu kết nối đã được thiết lập.
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
(Nhìn quen quen? Chúng tôi đã kết nối!)
Nếu bạn làm theo mọi thứ một cách hoàn hảo, bạn sẽ có thể di chuyển các thanh trượt. Tốt hơn, đèn LED RGB trên bảng Particle Mesh sẽ thay đổi màu sắc.
Kết luận
Trong bài viết này, bạn đã học cách kết nối bảng Particle Mesh với thiết bị iOS qua Bluetooth. Chúng tôi đã học cách kết nối với từng đặc điểm có sẵn. Ngoài ra, trên hết, hãy tạo một giao diện sạch sẽ để thực hiện tất cả.
Như bạn có thể tưởng tượng, bạn có thể đi xuống lỗ thỏ bằng Bluetooth trên iOS. Còn nhiều điều nữa trong hướng dẫn sắp tới của tôi: Hướng dẫn cơ bản về lưới hạt. Những người đăng ký trong danh sách của tôi có quyền truy cập vào nội dung trước khi ra mắt và được giảm giá khi nó ra mắt! Nhấp vào đây để đăng ký.
Mã
Mã nguồn đầy đủ có sẵn trên Github. Nếu bạn thấy nó hữu ích, hãy nhấn vào nút dấu sao. ⭐️