Я устанавливаю соединение между моим iOS-приложением и парой устройств BLE, созданных мной.У меня нет проблем, когда подключено только одно устройство, но когда оба подключены, я получаю эту ошибку с одним из них:
[CoreBluetooth] ПРЕДУПРЕЖДЕНИЕ: уведомление = НЕТ> не является допустимой характеристикой для периферийного устройства.
Оба устройства имеют одинаковые имя и характеристики службы, но имеют разные имя и идентификатор, и я использую имя для идентификации того или другого устройства.
Один и тот же код работает нормально, если толькоподключено одно устройство.
Я показываю вам свой код:
//BLE starts here
extension BTManager: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .unknown:
print("central.state is .unknown")
connectionStatus = -5
case .resetting:
print("central.state is .resetting")
connectionStatus = -4
case .unsupported:
print("central.state is .unsupported")
connectionStatus = -3
case .unauthorized:
print("central.state is .unauthorized")
connectionStatus = -2
case .poweredOff:
print("central.state is .poweredOff")
connectionStatus = -1
case .poweredOn:
print("central.state is .poweredOn and searching mode")
connectionStatus = 0
//Scan
if (!centralManager.isScanning){
centralManager.scanForPeripherals(withServices: [insoleServiceCBUUID])
}
}
}
//Some peripheral found
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral,
advertisementData: [String : Any], rssi RSSI: NSNumber) {
if(isInsolePresentInUserDefaults()){
let insolesDictionary = UserDefaults.standard.dictionary(forKey: "AriaSmartInsole") as! [String : String]
if (peripheral.name! == insolesDictionary["leftInsole"]){
leftDevicePeripheral = peripheral
leftDevicePeripheral.delegate = self
centralManager.connect(leftDevicePeripheral)
}
if (peripheral.name! == insolesDictionary["rightInsole"]){
rightDevicePeripheral = peripheral
rightDevicePeripheral.delegate = self
centralManager.connect(rightDevicePeripheral)
}
//ELSE record couple devices
}else{
if (peripheral.name!.contains("Aria") && peripheral.name!.count > 8){
if (dispositiviTrovati.count > 1){
var dispositiviTrovatiArray: [CBPeripheral] = Array(Set(dispositiviTrovati))
for (index, element) in dispositiviTrovatiArray.enumerated(){
let nextElement = index + 1
if (nextElement < dispositiviTrovatiArray.count){
let nomePrimoDevice: String = dispositiviTrovatiArray[index].name!
let primoDevice: CBPeripheral = dispositiviTrovatiArray[index]
let nomeSuccessivoDevice: String = dispositiviTrovatiArray[nextElement].name!
let successivoDevice: CBPeripheral = dispositiviTrovatiArray[nextElement]
let latoPrimoDevice: Character = nomePrimoDevice[nomePrimoDevice.index(nomePrimoDevice.startIndex, offsetBy: 5)]
let latoSuccessivoDevice: Character = nomeSuccessivoDevice[nomeSuccessivoDevice.index(nomeSuccessivoDevice.startIndex, offsetBy: 5)]
//HERE I SEARCH FOR LEFT DEVICE AND RIGHT DEVICE OF A COUPLE
if (nomePrimoDevice.suffix(8) == nomeSuccessivoDevice.suffix(8) && latoPrimoDevice != latoSuccessivoDevice){
var deviceDictionary: [String:String] = [:]
var deviceSinistro: CBPeripheral?
var deviceDestro: CBPeripheral?
if(latoPrimoDevice == "S"){
deviceDictionary["leftInsole"] = nomePrimoDevice
deviceSinistro = primoDevice
}else if(latoPrimoDevice == "D"){
deviceDictionary["rightInsole"] = nomePrimoDevice
deviceDestro = primoDevice
}
if(latoSuccessivoDevice == "S"){
deviceDictionary["leftInsole"] = nomeSuccessivoDevice
deviceSinistro = successivoDevice
}else if(latoSuccessivoDevice == "D"){
deviceDictionary["rightInsole"] = nomeSuccessivoDevice
deviceDestro = successivoDevice
}
//BINGO
if(deviceDictionary.count == 2){
print(deviceDictionary.description)
UserDefaults.standard.set(deviceDictionary, forKey: "AriaSmartInsole")
//ASK FOR CONNECTION COUPLE OF DEVICE
for device in dispositiviTrovati{
if (device.name! == UserDefaults.standard.dictionary(forKey: "AriaSmartInsole")!["leftInsole"] as! String){
leftDevicePeripheral = deviceSinistro
print(leftDevicePeripheral.name ?? "")
leftDevicePeripheral.delegate = self
centralManager.connect(leftDevicePeripheral)
}else if(device.name! == UserDefaults.standard.dictionary(forKey: "AriaSmartInsole")!["rightInsole"] as! String){
rightDevicePeripheral = deviceDestro
print(rightDevicePeripheral.name ?? "")
rightDevicePeripheral.delegate = self
centralManager.connect(rightDevicePeripheral)
}
}
}
}
}
}
}
}
}
}
//CONNECTED TO DEVICES
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
if (peripheral.name! == leftDevicePeripheral.name!){
leftDevicePeripheral.isConnected = true
leftDevicePeripheral.discoverServices([insoleServiceCBUUID])
self.connectionStatus = 1
}else if(peripheral.name! == rightDevicePeripheral.name!){
rightDevicePeripheral.isConnected = true
rightDevicePeripheral.discoverServices([insoleServiceCBUUID])
self.connectionStatus = 1
}
if (leftDevicePeripheral.isConnected == true && rightDevicePeripheral.isConnected == true){
self.connectionStatus = 2
centralManager.stopScan()//Safe power
}
}
}
extension BTManager: CBPeripheralDelegate {
//SERVICES FOUND
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
if (error != nil){
print("didDiscoverServices ERROR: ", error.debugDescription);
return;
}
var insoleServiceIsFound: Bool = false;
for service in peripheral.services! {
//FOUND MY SERVICE
if (service.uuid == insoleServiceCBUUID){
if (peripheral.name! == leftDevicePeripheral.name){
leftDevicePeripheral.insoleService = service
leftDevicePeripheral.discoverCharacteristics(nil, for: leftDevicePeripheral.insoleService)
insoleServiceIsFound = true;
}else if (peripheral.name! == rightDevicePeripheral.name){
rightDevicePeripheral.insoleService = service
rightDevicePeripheral.discoverCharacteristics(nil, for: rightDevicePeripheral.insoleService)
insoleServiceIsFound = true;
}
}
}
if (!insoleServiceIsFound){
print("didDiscoverServices: ARIA SERVICE NOT FOUND");
}
}
//CHARACTERISTIC OF MY SERVICE FOUND
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
if (error != nil){
print("didDiscoverCharacteristicsFor ERROR: ", error.debugDescription)
return
}
guard let characteristics = service.characteristics else {
print("NO CHARACTERESTICS FOUND")
return
}
if (peripheral.name! == leftDevicePeripheral.name){
for characteristic in characteristics {
switch characteristic.uuid {
case userEnableCBUUID:
leftDevicePeripheral.temperatureEnableCharacteristic = characteristic
if characteristic.properties.contains(.read) {
print("\(characteristic.uuid): properties contains .read")
leftDevicePeripheral.readValue(for: leftDevicePeripheral.temperatureEnableCharacteristic)
}
case batteryLevelCBUUID:
leftDevicePeripheral.batteryLevelCharacteristic = characteristic
if characteristic.properties.contains(.read) {
print("\(characteristic.uuid): properties contains .read")
leftDevicePeripheral.readValue(for: leftDevicePeripheral.batteryLevelCharacteristic)
}
default:
print("Unhandled Characteristic UUID: \(characteristic.uuid)")
}
}
}else if (peripheral.name! == rightDevicePeripheral.name){
for characteristic in characteristics {
switch characteristic.uuid {
case userEnableCBUUID:
rightDevicePeripheral.temperatureEnableCharacteristic = characteristic
if characteristic.properties.contains(.read) {
print("\(characteristic.uuid): properties contains .read")
rightDevicePeripheral.readValue(for: rightDevicePeripheral.temperatureEnableCharacteristic)
}
case batteryLevelCBUUID:
rightDevicePeripheral.batteryLevelCharacteristic = characteristic
if characteristic.properties.contains(.read) {
print("\(characteristic.uuid): properties contains .read")
rightDevicePeripheral.readValue(for: rightDevicePeripheral.batteryLevelCharacteristic)
}
default:
print("Unhandled Characteristic UUID: \(characteristic.uuid)")
}
}
}
}
//DATA RECEIVED
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
print("Nome: \(peripheral.name ?? "")")
if (error != nil){
print("didUpdateValueFor ERROR: ", error.debugDescription)
return
}
if (peripheral.name! == leftDevicePeripheral.name){
//Assegno valori prelevati alle caratteristiche
switch characteristic.uuid {
case userEnableCBUUID:
print("userEnableValue: ", characteristic.value?[0] ?? "no value")
//print("userTemp: ", characteristic.value?[0] ?? "no value")
var data = characteristic.value
var values = [UInt8](repeating:0, count:(data?.count)!)
data?.copyBytes(to: &values, count:(data?.count)!)
if(Int(values[0]) == 1){
leftDevicePeripheral.isThermalEnabled = true
}else if(Int(values[0]) == 0){
leftDevicePeripheral.isThermalEnabled = false
}
print("LEFT userEnableValue for \(peripheral.description) in delegate:", leftDevicePeripheral.isThermalEnabled)
print("\n")
case batteryLevelCBUUID:
//print("Battery level: ", characteristic.value?[0] ?? "no value")
let data = characteristic.value
var byte:UInt8 = 0
data?.copyBytes(to: &byte, count: 1)
leftDevicePeripheral.batteryLevel = Int(byte)
print("BATTERY level: ", leftDevicePeripheral.batteryLevel)
default:
print("Unhandled Characteristic UUID: \(characteristic.uuid)")
}
}else if (peripheral.name! == rightDevicePeripheral.name){
//Assegno valori prelevati alle caratteristiche
switch characteristic.uuid {
case userEnableCBUUID:
print("RIght userEnableValue: ", characteristic.value?[0] ?? "no value")
//print("userTemp: ", characteristic.value?[0] ?? "no value")
var data = characteristic.value
var values = [UInt8](repeating:0, count:(data?.count)!)
data?.copyBytes(to: &values, count:(data?.count)!)
if(Int(values[0]) == 1){
rightDevicePeripheral.isThermalEnabled = true
}else if(Int(values[0]) == 0){
rightDevicePeripheral.isThermalEnabled = false
}
print("RIGHT userEnableValue for \(peripheral.description) in delegate:", leftDevicePeripheral.isThermalEnabled)
print("\n")
case batteryLevelCBUUID:
//print("Battery level: ", characteristic.value?[0] ?? "no value")
let data = characteristic.value
var byte:UInt8 = 0
data?.copyBytes(to: &byte, count: 1)
let battLevel = Int(byte)
print("BATTERY level: ", battLevel)
default:
print("Unhandled Characteristic UUID: \(characteristic.uuid)")
}
}
}
//FUNC THAT I CALL
func enableThermal(forDevice: String){
//Se c'è connessione
if(self.checkConnessione() > 0){
var val = UInt8(1)
let data = NSData(bytes: &val, length: MemoryLayout<UInt8>.size)
print("Val: \(val)")
print("Data: \(data.description)")
if((forDevice == "left" || forDevice == "both") && leftDevicePeripheral.temperatureEnableCharacteristic != nil){
leftDevicePeripheral.writeValue(data as Data, for: leftDevicePeripheral.temperatureEnableCharacteristic, type: CBCharacteristicWriteType.withResponse)
}
if((forDevice == "right" || forDevice == "both") && rightDevicePeripheral.temperatureEnableCharacteristic != nil){
rightDevicePeripheral.writeValue(data as Data, for: rightDevicePeripheral.temperatureEnableCharacteristic, type: CBCharacteristicWriteType.withResponse)
}
//Error msg + Ritenta connessione
}else{
print("NO CONNECTION")
}
}
//Here I save my custom peripheral (left and right)
import Foundation
import CoreBluetooth
extension CBPeripheral{
struct Holder {
static var insoleService: CBService!
static var temperatureEnableCharacteristic: CBCharacteristic?
static var batteryLevelCharacteristic: CBCharacteristic?
static var isConnected: Bool = false
static var isThermalEnabled: Bool = false
static var batteryLevel: Int = 0
static var userTemperature: Double = 0
static var topTemperature: Double = 0
static var midTemperature: Double = 0
static var bottomTemperature: Double = 0
static var steps: Int = 0
}
var insoleService: CBService {
get {
return Holder.insoleService
}
set(newValue) {
Holder.insoleService = newValue
}
}
var temperatureEnableCharacteristic: CBCharacteristic {
get {
return Holder.temperatureEnableCharacteristic!
}
set(newValue) {
Holder.temperatureEnableCharacteristic = newValue
}
}
}
Я ожидаю записи на оба устройства, сначала одно, а затем другое, еслиоба связаны.
Спасибо.Эрос.