Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 device.manufacturerData is undefined, however device.rawScanRecord has valid manufacturerData data. #1138

Closed
2 tasks done
supurloop opened this issue Nov 16, 2023 · 10 comments · Fixed by #1143
Closed
2 tasks done
Labels

Comments

@supurloop
Copy link

Prerequisites

  • I checked the documentation and FAQ without finding a solution
  • I checked to make sure that this issue has not already been filed

Expected Behavior

The device object should be populating the device.manufacturerData field with a Base64 encoded string that is the manufacturer data in the advertisement. This had been working on both iOS and Android with 2.0.3, but after upgrading to 3.1.1 only Android sets the device.manufacturerData field, on iOS it is undefined.

Current Behavior

The device.manufacturerData should be a Base64 encoded string, it is undefined. I am certain that the received advertisement contains manufacturer data. It works on Android, and even on iOS I can still correctly extract the missing device.manufacturerData from device.rawScanRecord field so I know the data is being received by iOS. Again, this was working with 2.0.3 of the library on both iOS and Android, and is working on Android with 3.1.1 as well.

Library version

3.1.1

Device

iPhone 8/iOS 16.7.2

Environment info

yarn info

{
  name: '@client',
  'dist-tags': {
    latest: '0.1.0'
  },
  versions: [
    '0.1.0',
  ],
  time: {
    '0.1.0': '2023-11-16T13:56:52Z'
  },
  description: 'Client',
  author: {
    name: 'Client',
    email: 'name@company.com',
    url: 'https://github.com/client'
  },
  license: 'UNLICENSED',
  homepage: 'https://github.com/client/client#readme',
  repository: {
    type: 'git',
    url: 'git+https://github.com/client/client.git'
  },
  bugs: {
    url: 'https://github.com/client/client/issues'
  },
  version: '0.1.0',
  dist: {
    integrity: 'sha512-',
    shasum: 'b4c849b787aafd9d',
    tarball: 'https://npm.pkg.github.com/download/@client/client/0.1.0/b4c8'
  },
  main: 'lib/commonjs/index',
  scripts: {
    format: 'prettier --write "src/**/*.{js,ts,tsx}" "*.js"',
    lint: 'eslint . --ignore-path .eslintignore --ext .js,.tsx,.ts',
    prepare: 'bob build',
    test: 'npm run typecheck && npm run lint',
    typecheck: 'tsc --noEmit'
  },
  dependencies: {
    '@client/ubjson': '^0.0.1',
    'aes-js': '^3.1.2',
    assert: '^1.5.0',
    buffer: '^4.9.2',
    'react-native-base64': '^0.2.1',
    'react-native-ble-plx': '^3.1.1',
    'text-encoding-polyfill': '^0.6.7'
  },
  devDependencies: {
    '@babel/eslint-parser': '^7.18.2',
    '@react-native-community/eslint-config': '^3.0.2',
    '@types/jest': '^28.1.2',
    '@types/react': '~17.0.21',
    '@types/react-native': '0.68.0',
    '@types/react-native-base64': '^0.2.0',
    commitlint: '^17.0.2',
    eslint: '^8.4.1',
    'eslint-config-prettier': '^8.5.0',
    'eslint-plugin-prettier': '^4.0.0',
    jest: '^28.1.1',
    'pod-install': '^0.1.0',
    prettier: '^2.0.5',
    react: '17.0.2',
    'react-native': '0.68.2',
    'react-native-builder-bob': '^0.18.3',
    typescript: '^4.5.2'
  },
  peerDependencies: {
    react: '*',
    'react-native': '*',
    'react-native-ble-plx': '^3.1.1'
  },
  gitHead: 'b877b87cbd712031ddc876130a155f9672b8ca48',
  files: [
    'src',
    'lib'
  ],
  directories: {},
  bin: {}
}

Steps to reproduce

  1. startDeviceScan()
  2. Receive advertisements with manufacturer data.

Formatted code sample or link to a repository

manager.startDeviceScan()

Relevant log output

RXed scan device object with manufactuerData undefined.
{ name: '3344_B0D27865639D',
  mtu: 23,
  id: '5FFA2637-0522-D0F8-89E7-0BFB06F7FC0C',
  rawScanRecord: 'eyJzZXJ2aWNlRGF0YSI6bnVsbCwiaXNDb25uZWN0YWJsZSI6dHJ1ZSwidHhQb3dlckxldmVsIjpudWxsLCJzZXJ2aWNlVVVJRHMiOlsiMDAwMGZjYTUtMDAwMC0xMDAwLTgwMDAtMDA4MDVmOWIzNGZiIl0sIm1hbnVmYWN0dXJlckRhdGEiOiI2Z3dCRUxEU2VHVmpuUT09Iiwib3ZlcmZsb3dTZXJ2aWNlVVVJRHMiOm51bGwsImxvY2FsTmFtZSI6bnVsbCwic29saWNpdGVkU2VydmljZVVVSURzIjpudWxsfQ==',
  rssi: -46,
  _manager: 
   { _eventEmitter: 
      { _nativeModule: 
         { createClient: { [Function: nonPromiseMethodWrapper] type: 'async' },
           destroyClient: { [Function: nonPromiseMethodWrapper] type: 'async' },
           enable: { [Function: promiseMethodWrapper] type: 'promise' },
           disable: { [Function: promiseMethodWrapper] type: 'promise' },
           state: { [Function: promiseMethodWrapper] type: 'promise' },
           startDeviceScan: { [Function: nonPromiseMethodWrapper] type: 'async' },
           stopDeviceScan: { [Function: nonPromiseMethodWrapper] type: 'async' },
           requestConnectionPriorityForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           readRSSIForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           requestMTUForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           devices: { [Function: promiseMethodWrapper] type: 'promise' },
           connectedDevices: { [Function: promiseMethodWrapper] type: 'promise' },
           connectToDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           cancelDeviceConnection: { [Function: promiseMethodWrapper] type: 'promise' },
           isDeviceConnected: { [Function: promiseMethodWrapper] type: 'promise' },
           discoverAllServicesAndCharacteristicsForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           servicesForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           characteristicsForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           characteristicsForService: { [Function: promiseMethodWrapper] type: 'promise' },
           descriptorsForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           descriptorsForService: { [Function: promiseMethodWrapper] type: 'promise' },
           descriptorsForCharacteristic: { [Function: promiseMethodWrapper] type: 'promise' },
           readCharacteristicForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           readCharacteristicForService: { [Function: promiseMethodWrapper] type: 'promise' },
           readCharacteristic: { [Function: promiseMethodWrapper] type: 'promise' },
           writeCharacteristicForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           writeCharacteristicForService: { [Function: promiseMethodWrapper] type: 'promise' },
           writeCharacteristic: { [Function: promiseMethodWrapper] type: 'promise' },
           monitorCharacteristicForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           monitorCharacteristicForService: { [Function: promiseMethodWrapper] type: 'promise' },
           monitorCharacteristic: { [Function: promiseMethodWrapper] type: 'promise' },
           readDescriptorForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           readDescriptorForService: { [Function: promiseMethodWrapper] type: 'promise' },
           readDescriptorForCharacteristic: { [Function: promiseMethodWrapper] type: 'promise' },
           readDescriptor: { [Function: promiseMethodWrapper] type: 'promise' },
           writeDescriptorForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           writeDescriptorForService: { [Function: promiseMethodWrapper] type: 'promise' },
           writeDescriptorForCharacteristic: { [Function: promiseMethodWrapper] type: 'promise' },
           writeDescriptor: { [Function: promiseMethodWrapper] type: 'promise' },
           cancelTransaction: { [Function: nonPromiseMethodWrapper] type: 'async' },
           setLogLevel: { [Function: nonPromiseMethodWrapper] type: 'async' },
           logLevel: { [Function: promiseMethodWrapper] type: 'promise' },
           addListener: { [Function: nonPromiseMethodWrapper] type: 'async' },
           removeListeners: { [Function: nonPromiseMethodWrapper] type: 'async' },
           ReadEvent: 'ReadEvent',
           RestoreStateEvent: 'RestoreStateEvent',
           ConnectingEvent: 'ConnectingEvent',
           ConnectedEvent: 'ConnectedEvent',
           StateChangeEvent: 'StateChangeEvent',
           ScanEvent: 'ScanEvent',
           DisconnectionEvent: 'DisconnectionEvent',
           getConstants: [Function] } },
     _uniqueId: 3,
     _activePromises: {},
     _activeSubscriptions: { '1': { remove: [Function: remove] } },
     _errorCodesToMessagesMapping: 
      { '0': 'Unknown error occurred. This is probably a bug! Check reason property.',
        '1': 'BleManager was destroyed',
        '2': 'Operation was cancelled',
        '3': 'Operation timed out',
        '4': 'Operation was rejected',
        '5': 'Invalid UUIDs or IDs were passed: {internalMessage}',
        '100': 'BluetoothLE is unsupported on this device',
        '101': 'Device is not authorized to use BluetoothLE',
        '102': 'BluetoothLE is powered off',
        '103': 'BluetoothLE is in unknown state',
        '104': 'BluetoothLE is resetting',
        '105': 'Bluetooth state change failed',
        '200': 'Device {deviceID} connection failed',
        '201': 'Device {deviceID} was disconnected',
        '202': 'RSSI read failed for device {deviceID}',
        '203': 'Device {deviceID} is already connected',
        '204': 'Device {deviceID} not found',
        '205': 'Device {deviceID} is not connected',
        '206': 'Device {deviceID} could not change MTU size',
        '300': 'Services discovery failed for device {deviceID}',
        '301': 'Included services discovery failed for device {deviceID} and service: {serviceUUID}',
        '302': 'Service {serviceUUID} for device {deviceID} not found',
        '303': 'Services not discovered for device {deviceID}',
        '400': 'Characteristic discovery failed for device {deviceID} and service {serviceUUID}',
        '401': 'Characteristic {characteristicUUID} write failed for device {deviceID} and service {serviceUUID}',
        '402': 'Characteristic {characteristicUUID} read failed for device {deviceID} and service {serviceUUID}',
        '403': 'Characteristic {characteristicUUID} notify change failed for device {deviceID} and service {serviceUUID}',
        '404': 'Characteristic {characteristicUUID} not found',
        '405': 'Characteristics not discovered for device {deviceID} and service {serviceUUID}',
        '406': 'Cannot write to characteristic {characteristicUUID} with invalid data format: {internalMessage}',
        '500': 'Descriptor {descriptorUUID} discovery failed for device {deviceID}, service {serviceUUID} and characteristic {characteristicUUID}',
        '501': 'Descriptor {descriptorUUID} write failed for device {deviceID}, service {serviceUUID} and characteristic {characteristicUUID}',
        '502': 'Descriptor {descriptorUUID} read failed for device {deviceID}, service {serviceUUID} and characteristic {characteristicUUID}',
        '503': 'Descriptor {descriptorUUID} not found',
        '504': 'Descriptors not discovered for device {deviceID}, service {serviceUUID} and characteristic {characteristicUUID}',
        '505': 'Cannot write to descriptor {descriptorUUID} with invalid data format: {internalMessage}',
        '506': 'Cannot write to descriptor {descriptorUUID}. It\'s not allowed by iOS and therefore forbidden on Android as well.',
        '600': 'Cannot start scanning operation',
        '601': 'Location services are disabled' },
     _scanEventSubscription: { remove: [Function: remove] } } }

Additional information

The Base64 decode of the above log output shows that there is manufacturerData. The value of the manufacturerData is valid for the particular device.

{"serviceData":null,"isConnectable":true,"txPowerLevel":null,"serviceUUIDs":["0000fca5-0000-1000-8000-00805f9b34fb"],"manufacturerData":"6gwBELDSeGVjnQ==","overflowServiceUUIDs":null,"localName":null,"solicitedServiceUUIDs":null}

@supurloop supurloop added the bug label Nov 16, 2023
@MahmoudNafiseh
Copy link

This happens on our application too, downgraded to 2.0.3 and it works. I assume this is because of the switch to the MultiplatformBleAdapter library?

@MahmoudNafiseh
Copy link

MahmoudNafiseh commented Nov 21, 2023

@KamilNatonek I tried your PR using patch-package and I don't think that fixes the issue, I seem to be getting undefined still.

@KamilNatonek
Copy link
Contributor

@MahmoudNafiseh thanks for info, I will continue working on it

@KamilNatonek
Copy link
Contributor

@MahmoudNafiseh in the meantime can you provide your current <ScannedPeripheral> output ? Sample one

@luca-tomasetti
Copy link

+1 same for me as well.
I also tried your PR patch @KamilNatonek and I still received undefined in the manufacturerData

@KamilNatonek
Copy link
Contributor

@luca-tomasetti @MahmoudNafiseh Check this out -> #605 (comment)
I've added console logs to our example app and these are my logs confirming the theory from the link.

LOG Device name: MIScooter2526,Device manufacturerData: null -> first record
LOG Device name: MIScooter2526,Device manufacturerData: TkIuAgAAAM8= -> second record

@supurloop
Copy link
Author

#605 is not the same problem I am reporting. On iOS with 3.1.1 manufactuerData is always undefined, not just the first time.

@MahmoudNafiseh
Copy link

@KamilNatonek this is my output data:

device.manufacturerData: undefined
{ rawScanRecord: 'eyJpc0Nvbm5lY3RhYmxlIjp0cnVlLCJvdmVyZmxvd1NlcnZpY2VVVUlEcyI6bnVsbCwic2VydmljZURhdGEiOm51bGwsInNvbGljaXRlZFNlcnZpY2VVVUlEcyI6bnVsbCwibG9jYWxOYW1lIjoiQkFORCBWMiAzMCIsIm1hbnVmYWN0dXJlckRhdGEiOiJnc2JTWG5CVEowSDlZTExpVmowZ3FPNTB3ZWZ1SUp1TnZTXC9nZllKWkVRNkhaZz09IiwidHhQb3dlckxldmVsIjpudWxsLCJzZXJ2aWNlVVVJRHMiOlsiNTM0N2FiYTItNjBkNi00MmFhLTg4YjktMTNiZGU5OWE0NWE5Il19',
  id: '3DF4DD74-5027-1722-0970-AB439897BA03',
  rssi: -67,
  name: 'BAND V2 30',
  mtu: 23,
  _manager: 
   { _eventEmitter: 
      { _nativeModule: 
         { stopDeviceScan: { [Function: nonPromiseMethodWrapper] type: 'async' },
           requestConnectionPriorityForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           readRSSIForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           requestMTUForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           devices: { [Function: promiseMethodWrapper] type: 'promise' },
           connectedDevices: { [Function: promiseMethodWrapper] type: 'promise' },
           connectToDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           cancelDeviceConnection: { [Function: promiseMethodWrapper] type: 'promise' },
           isDeviceConnected: { [Function: promiseMethodWrapper] type: 'promise' },
           discoverAllServicesAndCharacteristicsForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           servicesForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           characteristicsForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           characteristicsForService: { [Function: promiseMethodWrapper] type: 'promise' },
           descriptorsForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           descriptorsForService: { [Function: promiseMethodWrapper] type: 'promise' },
           descriptorsForCharacteristic: { [Function: promiseMethodWrapper] type: 'promise' },
           readCharacteristicForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           readCharacteristicForService: { [Function: promiseMethodWrapper] type: 'promise' },
           readCharacteristic: { [Function: promiseMethodWrapper] type: 'promise' },
           writeCharacteristicForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           writeCharacteristicForService: { [Function: promiseMethodWrapper] type: 'promise' },
           writeCharacteristic: { [Function: promiseMethodWrapper] type: 'promise' },
           monitorCharacteristicForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           monitorCharacteristicForService: { [Function: promiseMethodWrapper] type: 'promise' },
           monitorCharacteristic: { [Function: promiseMethodWrapper] type: 'promise' },
           readDescriptorForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           readDescriptorForService: { [Function: promiseMethodWrapper] type: 'promise' },
           readDescriptorForCharacteristic: { [Function: promiseMethodWrapper] type: 'promise' },
           readDescriptor: { [Function: promiseMethodWrapper] type: 'promise' },
           writeDescriptorForDevice: { [Function: promiseMethodWrapper] type: 'promise' },
           writeDescriptorForService: { [Function: promiseMethodWrapper] type: 'promise' },
           writeDescriptorForCharacteristic: { [Function: promiseMethodWrapper] type: 'promise' },
           writeDescriptor: { [Function: promiseMethodWrapper] type: 'promise' },
           cancelTransaction: { [Function: nonPromiseMethodWrapper] type: 'async' },
           setLogLevel: { [Function: nonPromiseMethodWrapper] type: 'async' },
           logLevel: { [Function: promiseMethodWrapper] type: 'promise' },
           createClient: { [Function: nonPromiseMethodWrapper] type: 'async' },
           destroyClient: { [Function: nonPromiseMethodWrapper] type: 'async' },
           enable: { [Function: promiseMethodWrapper] type: 'promise' },
           disable: { [Function: promiseMethodWrapper] type: 'promise' },
           state: { [Function: promiseMethodWrapper] type: 'promise' },
           startDeviceScan: { [Function: nonPromiseMethodWrapper] type: 'async' },
           addListener: { [Function: nonPromiseMethodWrapper] type: 'async' },
           removeListeners: { [Function: nonPromiseMethodWrapper] type: 'async' },
           DisconnectionEvent: 'DisconnectionEvent',
           ScanEvent: 'ScanEvent',
           StateChangeEvent: 'StateChangeEvent',
           ConnectedEvent: 'ConnectedEvent',
           ConnectingEvent: 'ConnectingEvent',
           RestoreStateEvent: 'RestoreStateEvent',
           ReadEvent: 'ReadEvent',
           getConstants: [Function] } },
     _uniqueId: 3,
     _activePromises: {},
     _activeSubscriptions: { '1': { remove: [Function: remove] } },
     _errorCodesToMessagesMapping: 
      { '0': 'Unknown error occurred. This is probably a bug! Check reason property.',
        '1': 'BleManager was destroyed',
        '2': 'Operation was cancelled',
        '3': 'Operation timed out',
        '4': 'Operation was rejected',
        '5': 'Invalid UUIDs or IDs were passed: {internalMessage}',
        '100': 'BluetoothLE is unsupported on this device',
        '101': 'Device is not authorized to use BluetoothLE',
        '102': 'BluetoothLE is powered off',
        '103': 'BluetoothLE is in unknown state',
        '104': 'BluetoothLE is resetting',
        '105': 'Bluetooth state change failed',
        '200': 'Device {deviceID} connection failed',
        '201': 'Device {deviceID} was disconnected',
        '202': 'RSSI read failed for device {deviceID}',
        '203': 'Device {deviceID} is already connected',
        '204': 'Device {deviceID} not found',
        '205': 'Device {deviceID} is not connected',
        '206': 'Device {deviceID} could not change MTU size',
        '300': 'Services discovery failed for device {deviceID}',
        '301': 'Included services discovery failed for device {deviceID} and service: {serviceUUID}',
        '302': 'Service {serviceUUID} for device {deviceID} not found',
        '303': 'Services not discovered for device {deviceID}',
        '400': 'Characteristic discovery failed for device {deviceID} and service {serviceUUID}',
        '401': 'Characteristic {characteristicUUID} write failed for device {deviceID} and service {serviceUUID}',
        '402': 'Characteristic {characteristicUUID} read failed for device {deviceID} and service {serviceUUID}',
        '403': 'Characteristic {characteristicUUID} notify change failed for device {deviceID} and service {serviceUUID}',
        '404': 'Characteristic {characteristicUUID} not found',
        '405': 'Characteristics not discovered for device {deviceID} and service {serviceUUID}',
        '406': 'Cannot write to characteristic {characteristicUUID} with invalid data format: {internalMessage}',
        '500': 'Descriptor {descriptorUUID} discovery failed for device {deviceID}, service {serviceUUID} and characteristic {characteristicUUID}',
        '501': 'Descriptor {descriptorUUID} write failed for device {deviceID}, service {serviceUUID} and characteristic {characteristicUUID}',
        '502': 'Descriptor {descriptorUUID} read failed for device {deviceID}, service {serviceUUID} and characteristic {characteristicUUID}',
        '503': 'Descriptor {descriptorUUID} not found',
        '504': 'Descriptors not discovered for device {deviceID}, service {serviceUUID} and characteristic {characteristicUUID}',
        '505': 'Cannot write to descriptor {descriptorUUID} with invalid data format: {internalMessage}',
        '506': 'Cannot write to descriptor {descriptorUUID}. It\'s not allowed by iOS and therefore forbidden on Android as well.',
        '600': 'Cannot start scanning operation',
        '601': 'Location services are disabled' },
     _scanEventSubscription: { remove: [Function: remove] } } }

@MahmoudNafiseh
Copy link

@KamilNatonek I just installed the example app on my iOS device, I do get an undefined when I use your PR + the same logs you put

@luca-tomasetti
Copy link

@luca-tomasetti @MahmoudNafiseh Check this out -> #605 (comment) I've added console logs to our example app and these are my logs confirming the theory from the link.

LOG Device name: MIScooter2526,Device manufacturerData: null -> first record LOG Device name: MIScooter2526,Device manufacturerData: TkIuAgAAAM8= -> second record

As @supurloop my problem is not related with #605, on iOS with 3.1.1 I always received manufacturerData === undefined, not just the first time. If I use Android and 3.1.1, the problem doesn't occur and manufacturerData is populated as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants