在 swift 中监听事件舞会蓝牙外围设备
listening for an event prom bluetooth peripheral in swift
我有一个适用于低功耗蓝牙的 Dash 按钮。我可以扫描并找到它,连接到它并发现它的服务。
现在我想听听它的按钮是否被按下,或者 not.but 看来我的零件有一些严重的问题。我是 Swift 的新人,所以如果你能帮我解决这个问题,我真的很感激。
这是我的 swift 代码:
import CoreBluetooth
import UIKit
struct DisplayPeripheral{
var peripheral: CBPeripheral?
var lastRSSI: NSNumber?
var isConnectable: Bool?
}
class PeripheralViewController: UIViewController {
@IBOutlet weak var statusLabel: UILabel!
@IBOutlet weak var bluetoothIcon: UIImageView!
@IBOutlet weak var scanningButton: ScanButton!
var centralManager: CBCentralManager?
var peripherals: [DisplayPeripheral] = []
var viewReloadTimer: Timer?
let BEAN_NAME = "Security Tag"
let BEAN_SCRATCH_UUID = CBUUID(string: "90946c81-e466-4a43-9974-949e465d35a1")
let BEAN_SERVICE_UUID = CBUUID(string: "00001c00-d102-11e1-9b23-000efb0000a7")
var selectedPeripheral: CBPeripheral?
@IBOutlet weak var tableView: UITableView!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
//Initialise CoreBluetooth Central Manager
centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.main)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
viewReloadTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(PeripheralViewController.refreshScanView), userInfo: nil, repeats: true)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
viewReloadTimer?.invalidate()
}
func updateViewForScanning(){
statusLabel.text = "Scanning BLE Devices..."
bluetoothIcon.pulseAnimation()
bluetoothIcon.isHidden = false
scanningButton.buttonColorScheme(true)
}
func updateViewForStopScanning(){
let plural = peripherals.count > 1 ? "s" : ""
statusLabel.text = "\(peripherals.count) Device\(plural) Found"
bluetoothIcon.layer.removeAllAnimations()
bluetoothIcon.isHidden = true
scanningButton.buttonColorScheme(false)
}
@IBAction func scanningButtonPressed(_ sender: AnyObject){
if centralManager!.isScanning{
centralManager?.stopScan()
updateViewForStopScanning()
}else{
startScanning()
}
}
func startScanning(){
peripherals = []
self.centralManager?.scanForPeripherals(withServices: nil, options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
updateViewForScanning()
let triggerTime = (Int64(NSEC_PER_SEC) * 10)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(triggerTime) / Double(NSEC_PER_SEC), execute: { () -> Void in
if self.centralManager!.isScanning{
self.centralManager?.stopScan()
self.updateViewForStopScanning()
}
})
}
func refreshScanView()
{
if peripherals.count > 1 && centralManager!.isScanning{
tableView.reloadData()
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destinationViewController = segue.destination as? PeripheralConnectedViewController{
destinationViewController.peripheral = selectedPeripheral
}
}
}
extension PeripheralViewController: CBCentralManagerDelegate{
func centralManagerDidUpdateState(_ central: CBCentralManager){
//if (central.state == CBCentralManagerState.poweredOn){
startScanning()
//}else{
// do something like alert the user that ble is not on
//}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber){
for (index, foundPeripheral) in peripherals.enumerated(){
if foundPeripheral.peripheral?.identifier == peripheral.identifier{
peripherals[index].lastRSSI = RSSI
return
}
}
let isConnectable = advertisementData["kCBAdvDataIsConnectable"] as! Bool
if(peripheral.name == BEAN_NAME)
{
print(peripheral.name)
print(peripheral.identifier)
print("is?",isConnectable)
let displayPeripheral = DisplayPeripheral(peripheral: peripheral, lastRSSI: RSSI, isConnectable: isConnectable)
peripherals.append(displayPeripheral)
}
tableView.reloadData()
}
}
extension PeripheralViewController: CBPeripheralDelegate {
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
print("Error connecting peripheral: \(error?.localizedDescription)")
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral)
{
print("Peripheral connected")
performSegue(withIdentifier: "PeripheralConnectedSegue", sender: self)
peripheral.discoverServices(nil)
}
func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?)
{
print("jdbsud")
for service in peripheral.services!
{
let thisService = service as CBService
if service.uuid == BEAN_SERVICE_UUID {
peripheral.discoverCharacteristics(nil,for: thisService)
}
}
}
}
extension PeripheralViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell")! as! DeviceTableViewCell
cell.displayPeripheral = peripherals[indexPath.row]
cell.delegate = self
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return peripherals.count
}
}
extension PeripheralViewController: DeviceCellDelegate{
func connectPressed(_ peripheral: CBPeripheral) {
if peripheral.state != .connected {
selectedPeripheral = peripheral
peripheral.delegate = self
centralManager?.connect(peripheral, options: nil)
//you can listen to the commands here
}
}
}
我在 func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) 中打印了一些东西来检查我是否进入那里,显然我没有输入那部分代码。
经过努力,我自己解决了。
找到服务后,我应该将这两个函数添加到代码中,它的效果非常好:
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
debugPrint("Enabling ...")
for characteristic in service.characteristics! {
let thisCharacteristic = characteristic as CBCharacteristic
debugPrint("Characteristic: ", thisCharacteristic.uuid)
if thisCharacteristic.uuid == BEAN_SCRATCH_UUID {
debugPrint("Set to notify: ", thisCharacteristic.uuid)
// Prepare to show data
self.peripheral.setNotifyValue(true, for: thisCharacteristic)
}
}
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if characteristic.uuid == BEAN_SCRATCH_UUID {
let content = String(data: characteristic.value!, encoding: String.Encoding.utf8)
debugPrint("Notified.")
}
}
我有一个适用于低功耗蓝牙的 Dash 按钮。我可以扫描并找到它,连接到它并发现它的服务。
现在我想听听它的按钮是否被按下,或者 not.but 看来我的零件有一些严重的问题。我是 Swift 的新人,所以如果你能帮我解决这个问题,我真的很感激。
这是我的 swift 代码:
import CoreBluetooth
import UIKit
struct DisplayPeripheral{
var peripheral: CBPeripheral?
var lastRSSI: NSNumber?
var isConnectable: Bool?
}
class PeripheralViewController: UIViewController {
@IBOutlet weak var statusLabel: UILabel!
@IBOutlet weak var bluetoothIcon: UIImageView!
@IBOutlet weak var scanningButton: ScanButton!
var centralManager: CBCentralManager?
var peripherals: [DisplayPeripheral] = []
var viewReloadTimer: Timer?
let BEAN_NAME = "Security Tag"
let BEAN_SCRATCH_UUID = CBUUID(string: "90946c81-e466-4a43-9974-949e465d35a1")
let BEAN_SERVICE_UUID = CBUUID(string: "00001c00-d102-11e1-9b23-000efb0000a7")
var selectedPeripheral: CBPeripheral?
@IBOutlet weak var tableView: UITableView!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
//Initialise CoreBluetooth Central Manager
centralManager = CBCentralManager(delegate: self, queue: DispatchQueue.main)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
viewReloadTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(PeripheralViewController.refreshScanView), userInfo: nil, repeats: true)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
viewReloadTimer?.invalidate()
}
func updateViewForScanning(){
statusLabel.text = "Scanning BLE Devices..."
bluetoothIcon.pulseAnimation()
bluetoothIcon.isHidden = false
scanningButton.buttonColorScheme(true)
}
func updateViewForStopScanning(){
let plural = peripherals.count > 1 ? "s" : ""
statusLabel.text = "\(peripherals.count) Device\(plural) Found"
bluetoothIcon.layer.removeAllAnimations()
bluetoothIcon.isHidden = true
scanningButton.buttonColorScheme(false)
}
@IBAction func scanningButtonPressed(_ sender: AnyObject){
if centralManager!.isScanning{
centralManager?.stopScan()
updateViewForStopScanning()
}else{
startScanning()
}
}
func startScanning(){
peripherals = []
self.centralManager?.scanForPeripherals(withServices: nil, options: [CBCentralManagerScanOptionAllowDuplicatesKey: true])
updateViewForScanning()
let triggerTime = (Int64(NSEC_PER_SEC) * 10)
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(triggerTime) / Double(NSEC_PER_SEC), execute: { () -> Void in
if self.centralManager!.isScanning{
self.centralManager?.stopScan()
self.updateViewForStopScanning()
}
})
}
func refreshScanView()
{
if peripherals.count > 1 && centralManager!.isScanning{
tableView.reloadData()
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destinationViewController = segue.destination as? PeripheralConnectedViewController{
destinationViewController.peripheral = selectedPeripheral
}
}
}
extension PeripheralViewController: CBCentralManagerDelegate{
func centralManagerDidUpdateState(_ central: CBCentralManager){
//if (central.state == CBCentralManagerState.poweredOn){
startScanning()
//}else{
// do something like alert the user that ble is not on
//}
}
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber){
for (index, foundPeripheral) in peripherals.enumerated(){
if foundPeripheral.peripheral?.identifier == peripheral.identifier{
peripherals[index].lastRSSI = RSSI
return
}
}
let isConnectable = advertisementData["kCBAdvDataIsConnectable"] as! Bool
if(peripheral.name == BEAN_NAME)
{
print(peripheral.name)
print(peripheral.identifier)
print("is?",isConnectable)
let displayPeripheral = DisplayPeripheral(peripheral: peripheral, lastRSSI: RSSI, isConnectable: isConnectable)
peripherals.append(displayPeripheral)
}
tableView.reloadData()
}
}
extension PeripheralViewController: CBPeripheralDelegate {
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
print("Error connecting peripheral: \(error?.localizedDescription)")
}
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral)
{
print("Peripheral connected")
performSegue(withIdentifier: "PeripheralConnectedSegue", sender: self)
peripheral.discoverServices(nil)
}
func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?)
{
print("jdbsud")
for service in peripheral.services!
{
let thisService = service as CBService
if service.uuid == BEAN_SERVICE_UUID {
peripheral.discoverCharacteristics(nil,for: thisService)
}
}
}
}
extension PeripheralViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell")! as! DeviceTableViewCell
cell.displayPeripheral = peripherals[indexPath.row]
cell.delegate = self
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return peripherals.count
}
}
extension PeripheralViewController: DeviceCellDelegate{
func connectPressed(_ peripheral: CBPeripheral) {
if peripheral.state != .connected {
selectedPeripheral = peripheral
peripheral.delegate = self
centralManager?.connect(peripheral, options: nil)
//you can listen to the commands here
}
}
}
我在 func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) 中打印了一些东西来检查我是否进入那里,显然我没有输入那部分代码。
经过努力,我自己解决了。
找到服务后,我应该将这两个函数添加到代码中,它的效果非常好:
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
debugPrint("Enabling ...")
for characteristic in service.characteristics! {
let thisCharacteristic = characteristic as CBCharacteristic
debugPrint("Characteristic: ", thisCharacteristic.uuid)
if thisCharacteristic.uuid == BEAN_SCRATCH_UUID {
debugPrint("Set to notify: ", thisCharacteristic.uuid)
// Prepare to show data
self.peripheral.setNotifyValue(true, for: thisCharacteristic)
}
}
}
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
if characteristic.uuid == BEAN_SCRATCH_UUID {
let content = String(data: characteristic.value!, encoding: String.Encoding.utf8)
debugPrint("Notified.")
}
}