forked from platypush/platypush
A more clever logic of parsing the manufacturer for BLE devices.
1. Check the manufacturer parsed via Bleak/Theengs 2. Check the MAC address prefix in the oui numbers table 3. Check from the reported `manufacturer_data`
This commit is contained in:
parent
f7e8cfe5a7
commit
f6e09d34e4
1 changed files with 28 additions and 5 deletions
|
@ -5,7 +5,7 @@ from typing import Any, Callable, Dict, List, Optional
|
||||||
|
|
||||||
from bleak.backends.device import BLEDevice
|
from bleak.backends.device import BLEDevice
|
||||||
from bleak.backends.scanner import AdvertisementData
|
from bleak.backends.scanner import AdvertisementData
|
||||||
from bluetooth_numbers import company
|
from bluetooth_numbers import company, oui
|
||||||
|
|
||||||
from TheengsDecoder import decodeBLE, getAttribute, getProperties
|
from TheengsDecoder import decodeBLE, getAttribute, getProperties
|
||||||
|
|
||||||
|
@ -228,10 +228,7 @@ def device_to_entity(device: BLEDevice, data: AdvertisementData) -> BluetoothDev
|
||||||
|
|
||||||
theengs_entity = _parse_advertisement_data(data)
|
theengs_entity = _parse_advertisement_data(data)
|
||||||
props = (device.details or {}).get('props', {})
|
props = (device.details or {}).get('props', {})
|
||||||
manufacturer = theengs_entity.manufacturer or company.get(
|
manufacturer = _parse_manufacturer(device, theengs_entity)
|
||||||
next(iter(key for key in device.metadata['manufacturer_data']), 0xFFFF)
|
|
||||||
)
|
|
||||||
|
|
||||||
parent_entity = BluetoothDevice(
|
parent_entity = BluetoothDevice(
|
||||||
id=device.address,
|
id=device.address,
|
||||||
model=theengs_entity.model,
|
model=theengs_entity.model,
|
||||||
|
@ -278,6 +275,32 @@ def device_to_entity(device: BLEDevice, data: AdvertisementData) -> BluetoothDev
|
||||||
return parent_entity
|
return parent_entity
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_manufacturer(device: BLEDevice, entity: TheengsEntity) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
:param device: The target device.
|
||||||
|
:param entity: The entity that maps the received beacon data.
|
||||||
|
:return: The parsed manufacturer name.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# If the manufacturer has already been parsed, return it.
|
||||||
|
if entity.manufacturer:
|
||||||
|
return entity.manufacturer
|
||||||
|
|
||||||
|
# Otherwise, infer it from the first three bytes of the MAC address.
|
||||||
|
manufacturer = oui.get(':'.join(device.address.split(':')[:3]).upper())
|
||||||
|
if manufacturer:
|
||||||
|
return manufacturer
|
||||||
|
|
||||||
|
# Otherwise, infer it from the reported manufacturer_data.
|
||||||
|
for key in device.metadata.get('manufacturer_data', {}):
|
||||||
|
manufacturer = company.get(key)
|
||||||
|
if manufacturer:
|
||||||
|
return manufacturer
|
||||||
|
|
||||||
|
# Otherwise, we couldn't parse the manufacturer.
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _parse_advertisement_data(data: AdvertisementData) -> TheengsEntity:
|
def _parse_advertisement_data(data: AdvertisementData) -> TheengsEntity:
|
||||||
"""
|
"""
|
||||||
:param data: The data received from a Bluetooth advertisement packet.
|
:param data: The data received from a Bluetooth advertisement packet.
|
||||||
|
|
Loading…
Reference in a new issue