我正在编写一个iOS应用程序来与BLE设备通信。设备可以在连接之间更改名称(不是在BLE连接期间),但iOS拒绝更改设备名称。
例如:我可以在名称为SadName时连接到设备。我断开它,关闭应用程序等,并将设备的名称更改为HappyName。但是,当我扫描设备时,iOS仍然将外围设备名称显示为SadName。
如果我调试应用程序并查看:
(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
peripheral.name的值是SadName所以我不认为这是我在代码中错误解释的东西。我应该提一下,当我扫描设备时,我的代码是:
[self.CM scanForPeripheralsWithServices:nil options:0]; // Start scanning
我猜这只是因为设备UUID是相同的,所以iOS将其从缓存设备列表中拉出来,但我想覆盖它。
思考?对不起,我是iOS新手。 干杯 - MSchmidtbauer
答案 0 :(得分:23)
iOS SDK的CoreBluetooth API不提供强制刷新外围设备名称的方法。
目前,当BLE设备中的设备名称发生变化时,在iOS中使用peripheral.name是不可行的。
Apple建议通过指定传递给scanForPeripheralsWithServices的CBUUID对象(包含一个或多个服务UUID)列表来扫描特定设备:
NSArray *services = @[[CBUUID UUIDWithString: @"2456e1b9-26e2-8f83-e744-f34f01e9d701"] ]; // change to your service UUID!
NSDictionary *dictionary = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:1] forKey:CBCentralManagerScanOptionAllowDuplicatesKey];
[self.manager scanForPeripheralsWithServices:services options:dictionary];
这减少了didDiscoverPeripheral的调用次数。不要只将nil传递给scanForPeripheralsWithServices。它还允许您的应用在处于后台状态时扫描外围设备。
如果您正在寻找在建立连接之前广播可用信息的方法,则可以使用播发或扫描响应数据。外围设备可配置为广播名为本地名称和制造商特定数据的条目。这些数据在didDiscoverPeripheral:
中可用- (void)centralManager: (CBCentralManager *)central
didDiscoverPeripheral: (CBPeripheral *)peripheral
advertisementData: (NSDictionary *)advertisementData
RSSI: (NSNumber *)RSSI {
NSString *localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey];
NSData *manufacturerData = [advertisementData objectForKey:CBAdvertisementDataManufacturerDataKey];
NSLog(@"Local: name: %@", localName);
NSLog(@"Manufact. Data: %@", [manufacturerData description]);
}
本地名称是NSString ,因此在此字段中仅在BLE设备上写入可打印字符。 制造商数据是NSData ,它可以包含任何字节值,因此您甚至可以在此处获得二进制数据。
根据您使用的BLE设备,本地名称和制造商特定数据的长度是有限的。
在我的BLE设备上,我可以使用广告数据发送128位服务UUID和8字符本地名称。制造商特定数据进入扫描响应数据,可以是29个字节长。
使用Adv./Scan响应数据的好处是,它可以在没有电源循环的情况下在此BLE设备上进行更改。
建议:
答案 1 :(得分:6)
你的猜测是正确的。
这是因为core-blutetooth
缓存。
通常在BLE设备上更改名称/服务/特性是“不支持"”。所有这些参数都被缓存了。
有两种方法可以解决这个问题:
或者检查您的BLE设备的广告数据。它可能具有name
属性,每次BLE设备广告数据时都应该刷新(广告数据不会被缓存)。
答案 2 :(得分:0)
CBPeripheralDelegate
协议包含方法......
- (void)peripheralDidUpdateName:(CBPeripheral *)peripheral NS_AVAILABLE(NA, 6_0);
......这是为此而制作的。
答案 3 :(得分:0)
编辑 - 刚才意识到上面接受的答案的第二部分有相同的解决方案:-(我应该仔细阅读。无论如何我会在这里留下这个答案,因为它包含RoboVM代码。
我找到了解决这个问题的方法。添加GATT服务更改的特性不起作用,也没有直接从设备名称特征2A00读取设备名称,因为iOS隐藏了通用访问服务。但是,如果外围设备在广告包中包含其本地名称,则可以使用检索关键字scan result从CBAdvertisementDataLocalNameKey
上提供的广告数据字典中获取。我将其复制到我的BLE设备包装器中并使用它而不是CBPeripheral提供的名称。用于RoboVM的Java示例代码如下。 OBJC或Swift等价物很简单。
@Override
public void didDiscoverPeripheral(CBCentralManager cbCentralManager, CBPeripheral cbPeripheral, CBAdvertisementData cbAdvertisementData, NSNumber rssi) {
NSData manufacturerData = cbAdvertisementData.getManufacturerData();
byte[] data = null;
if(manufacturerData != null)
data = manufacturerData.getBytes();
IosBleDevice bleDevice = new IosBleDevice(cbPeripheral);
String name = cbAdvertisementData.getLocalName();
if(name != null && !name.equals(cbPeripheral.getName())) {
CJLog.logMsg("Set local name to %s (was %s)", name, cbPeripheral.getName());
bleDevice.setName(name);
}
deviceList.put(bleDevice.getAddress(), bleDevice);
if(!iosBlueMaxService.getSubscriber().isDisposed()) {
BleScanResult bleScanResult = new IosBleScanResult(bleDevice,
cbAdvertisementData.isConnectable(),
data);
bleScanResult.setRssi(rssi.intValue());
iosBlueMaxService.getSubscriber().onNext(bleScanResult);
}
}