iOS中的BLE外设名称不正确

2nbm6dog  于 2023-05-30  发布在  iOS
关注(0)|答案(4)|浏览(300)

我正在编写一个iOS应用程序来与BLE设备进行通信。设备可以在连接之间更改名称(不是在BLE连接期间),但iOS拒绝更改设备名称。
例如:我可以连接到名称为SadName的设备。我断开连接,关闭应用程序,等等。并将设备的名称更改为HappyName。但是,当我扫描设备时,iOS仍然将外围设备名称显示为SadName。
如果我调试应用程序并查看:

(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI

www.example.com的值peripheral.name是SadName,所以我不认为这是我在代码中解释错误的东西。我应该提到,当我扫描设备时,我的代码是:

[self.CM scanForPeripheralsWithServices:nil options:0]; // Start scanning

我猜这仅仅是因为设备UUID是相同的,所以iOS将其从缓存设备列表中拉出,但我想覆盖它。
抱歉,我是iOS新手。干杯- MSchmidtbauer

de90aj5v

de90aj5v1#

iOS SDK的CoreBluetooth API没有提供强制刷新外设名称的方法。

目前,peripheral.name当BLEdevice中的设备名称发生变化时,iOS中无法使用www.example.com

Apple建议您通过指定CBUID对象列表(包含一个或多个服务UUID)来扫描特定设备,并将其传递给scanForPeripheralsWithServices:

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设备上的可打印字符。Manufacturer Data是一个NSData,它可以包含任何字节值,所以这里甚至可以有二进制数据。

根据您使用的BLE设备,本地名称和制造商特定数据的长度有限。
在我的BLE设备上,我可以发送128位服务UUID和带有公告数据的8字符本地名称。制造商特定数据进入扫描响应数据,长度可为29字节。
使用Adv./Scan响应数据的好处是,它可以在这个BLE设备上改变,而不需要电源循环。
建议:
1.扫描时使用服务UUID进行筛选(UUID必须是广告数据的一部分!我在上面的描述中省略了)
1.使用通告/扫描响应数据进行进一步筛选
1.只要peripheral.name没有可用的确定性刷新,请忘记www.example.com

pnwntuvh

pnwntuvh2#

你的猜测是正确的。
因为core-blutetoothcache
一般来说,更改BLE设备上的名称/服务/特性是“不支持”的。所有这些参数都被缓存了。
有两种解决方法:

  • 重新启动蓝牙适配器,所以蓝牙缓存被清除(我担心没有办法做到这一点编程,但我可能是错的)
  • 您的设备BLE实现了GATT Service Changed特性:在这里阅读关于这个:core_v4.1.zip

第3卷,G部分,2.5.2和第3卷,G部分,7.1
或者检查BLE设备的广告数据。它可能具有name属性,每次BLE设备正在通告数据时,该属性应该被刷新(通告数据不会被缓存)。

5lwkijsr

5lwkijsr3#

CBPeripheralDelegate协议包含一个方法...

- (void)peripheralDidUpdateName:(CBPeripheral *)peripheral NS_AVAILABLE(NA, 6_0);

...就是为此目的而做的。

xzlaal3s

xzlaal3s4#

编辑-刚刚意识到上面接受的答案的第二部分有同样的解决方案:-(我应该更仔细地阅读。我将把这个答案留在这里,因为它包含了RoboVM代码。
我找到了解决这个问题的办法。添加GATT Service Changed特性不起作用,直接从Device Name特性2A 00阅读设备名称也不起作用,因为iOS隐藏了Generic Access服务。然而,如果外围设备在广告分组中包括其本地名称,则可以使用检索关键字CBAdvertisementDataLocalNameKeyscan result上提供的广告数据字典中获得。我将此复制到我的BLE设备 Package 器中,并使用它而不是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);
        }
    }

相关问题