Skip to content

Commit

Permalink
feat: add ability to set the bind key after init (#83)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: the bindkey should no longer be set directly on the object, call `set_bindkey` instead
  • Loading branch information
bdraco authored Jul 15, 2023
1 parent 9ccb7bf commit 1826139
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 5 deletions.
14 changes: 9 additions & 5 deletions src/bthome_ble/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,7 @@ class BTHomeBluetoothDeviceData(BluetoothData):

def __init__(self, bindkey: bytes | None = None) -> None:
super().__init__()
self.bindkey = bindkey
if bindkey:
self.cipher: AESCCM | None = AESCCM(bindkey, tag_length=4)
else:
self.cipher = None
self.set_bindkey(bindkey)

# Data that we know how to parse but don't yet map to the SensorData model.
self.unhandled: dict[str, Any] = {}
Expand Down Expand Up @@ -152,6 +148,14 @@ def __init__(self, bindkey: bytes | None = None) -> None:
# If this is True, the device is not sending advertisements in a regular interval
self.sleepy_device = False

def set_bindkey(self, bindkey: bytes | None) -> None:
"""Set the bindkey."""
self.bindkey = bindkey
if bindkey:
self.cipher: AESCCM | None = AESCCM(bindkey, tag_length=4)
else:
self.cipher = None

def supported(self, data: BluetoothServiceInfo) -> bool:
if not super().supported(data):
return False
Expand Down
56 changes: 56 additions & 0 deletions tests/test_parser_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,62 @@ def test_bindkey_correct():
)


def test_bindkey_set_late():
"""Test BTHome parser with correct encryption key set after the device is created."""
bindkey = "231d39c1d7cc1ab1aee224cd096db932"
data_string = b"\x41\xa4\x72\x66\xc9\x5f\x73\x00\x11\x22\x33\x78\x23\x72\x14"
advertisement = bytes_to_service_info(
data_string,
local_name="TEST DEVICE",
address="54:48:E6:8F:80:A5",
)

device = BTHomeBluetoothDeviceData()
device.set_bindkey(bytes.fromhex(bindkey))
assert device.supported(advertisement)
assert device.bindkey_verified
assert device.update(advertisement) == SensorUpdate(
title="TEST DEVICE 80A5",
devices={
None: SensorDeviceInfo(
name="TEST DEVICE 80A5",
manufacturer=None,
model="BTHome sensor",
sw_version="BTHome BLE v2 (encrypted)",
hw_version=None,
)
},
entity_descriptions={
KEY_TEMPERATURE: SensorDescription(
device_key=KEY_TEMPERATURE,
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=Units.TEMP_CELSIUS,
),
KEY_HUMIDITY: SensorDescription(
device_key=KEY_HUMIDITY,
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=Units.PERCENTAGE,
),
KEY_SIGNAL_STRENGTH: SensorDescription(
device_key=KEY_SIGNAL_STRENGTH,
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
),
},
entity_values={
KEY_TEMPERATURE: SensorValue(
device_key=KEY_TEMPERATURE, name="Temperature", native_value=25.06
),
KEY_HUMIDITY: SensorValue(
device_key=KEY_HUMIDITY, name="Humidity", native_value=50.55
),
KEY_SIGNAL_STRENGTH: SensorValue(
device_key=KEY_SIGNAL_STRENGTH, name="Signal Strength", native_value=-60
),
},
)


def test_bindkey_verified_can_be_unset():
"""Test BTHome parser with wrong encryption key."""
bindkey = "814aac74c4f17b6c1581e1ab87816b99"
Expand Down

0 comments on commit 1826139

Please sign in to comment.