|
1 | 1 | """Parser for SensorPro BLE advertisements. |
2 | 2 |
|
3 | 3 | This file is shamelessly copied from the following repository: |
4 | | -https://github.com/Ernst79/bleparser/blob/c42ae922e1abed2720c7fac993777e1bd59c0c93/package/bleparser/thermoplus.py |
| 4 | +https://github.com/Ernst79/bleparser/blob/c42ae922e1abed2720c7fac993777e1bd59c0c93/package/bleparser/brifit.py |
5 | 5 |
|
6 | 6 | MIT License applies. |
7 | 7 | """ |
8 | 8 | from __future__ import annotations |
9 | 9 |
|
10 | 10 | import logging |
11 | | -from dataclasses import dataclass |
12 | 11 | from struct import unpack |
13 | 12 |
|
14 | 13 | from bluetooth_data_tools import short_address |
15 | 14 | from bluetooth_sensor_state_data import BluetoothData |
16 | 15 | from home_assistant_bluetooth import BluetoothServiceInfo |
17 | | -from sensor_state_data import BinarySensorDeviceClass, SensorLibrary |
| 16 | +from sensor_state_data import SensorLibrary |
18 | 17 |
|
19 | 18 | _LOGGER = logging.getLogger(__name__) |
20 | 19 |
|
21 | 20 |
|
22 | | -@dataclass |
23 | | -class SensorProDevice: |
24 | | - |
25 | | - model: str |
26 | | - name: str |
27 | | - |
28 | | - |
29 | 21 | DEVICE_TYPES = { |
30 | | - 0x10: SensorProDevice("16", "Lanyard/mini hygrometer"), |
31 | | - 0x11: SensorProDevice("17", "Smart hygrometer"), |
32 | | - 0x15: SensorProDevice("21", "Smart hygrometer"), |
| 22 | + 0x01: "T201", |
| 23 | + 0x05: "T301", |
33 | 24 | } |
| 25 | +DEFAULT_MODEL = "T201" |
34 | 26 | MFR_IDS = set(DEVICE_TYPES) |
35 | 27 |
|
36 | | -SERVICE_UUID = "0000fff0-0000-1000-8000-00805f9b34fb" |
37 | | - |
38 | 28 |
|
39 | 29 | class SensorProBluetoothDeviceData(BluetoothData): |
40 | 30 | """Date update for SensorPro Bluetooth devices.""" |
41 | 31 |
|
42 | 32 | def _start_update(self, service_info: BluetoothServiceInfo) -> None: |
43 | 33 | """Update from BLE advertisement data.""" |
44 | 34 | _LOGGER.debug("Parsing sensorpro BLE advertisement data: %s", service_info) |
45 | | - if SERVICE_UUID not in service_info.service_uuids: |
46 | | - return |
47 | | - if not MFR_IDS.intersection(service_info.manufacturer_data): |
| 35 | + if 43605 not in service_info.manufacturer_data: |
48 | 36 | return |
49 | 37 | changed_manufacturer_data = self.changed_manufacturer_data(service_info) |
50 | 38 | if not changed_manufacturer_data: |
51 | 39 | return |
52 | 40 | last_id = list(changed_manufacturer_data)[-1] |
53 | | - data = ( |
54 | | - int(last_id).to_bytes(2, byteorder="little") |
55 | | - + changed_manufacturer_data[last_id] |
56 | | - ) |
57 | | - msg_length = len(data) |
58 | | - if msg_length not in (20, 22): |
| 41 | + |
| 42 | + changed = changed_manufacturer_data[last_id] |
| 43 | + if not changed.startswith(b"\x01\x01\xa4\xc1") and not changed.startswith( |
| 44 | + b"\x01\x05\xa4\xc1" |
| 45 | + ): |
59 | 46 | return |
60 | | - device_id = data[0] |
61 | | - device_type = DEVICE_TYPES[device_id] |
62 | | - name = device_type.name |
| 47 | + data = int(last_id).to_bytes(2, byteorder="little") + changed |
| 48 | + device_id = data[3] |
| 49 | + device_type = service_info.name or DEVICE_TYPES.get(device_id) or DEFAULT_MODEL |
| 50 | + name = device_type |
63 | 51 | self.set_precision(2) |
64 | 52 | self.set_device_type(device_id) |
65 | 53 | self.set_title(f"{name} {short_address(service_info.address)}") |
66 | 54 | self.set_device_name(f"{name} {short_address(service_info.address)}") |
67 | 55 | self.set_device_manufacturer("SensorPro") |
68 | | - self._process_update(data) |
69 | | - |
70 | | - def _process_update(self, data: bytes) -> None: |
71 | | - """Update from BLE advertisement data.""" |
72 | | - _LOGGER.debug("Parsing SensorPro BLE advertisement data: %s", data) |
73 | | - if len(data) != 20: |
74 | | - return |
75 | | - |
76 | | - button_pushed = data[3] & 0x80 |
77 | | - xvalue = data[10:16] |
78 | | - |
79 | | - (volt, temp, humi) = unpack("<HhH", xvalue) |
80 | | - |
81 | | - if volt >= 3000: |
82 | | - batt = 100 |
83 | | - elif volt >= 2600: |
84 | | - batt = 60 + (volt - 2600) * 0.1 |
85 | | - elif volt >= 2500: |
86 | | - batt = 40 + (volt - 2500) * 0.2 |
87 | | - elif volt >= 2450: |
88 | | - batt = 20 + (volt - 2450) * 0.4 |
89 | | - else: |
90 | | - batt = 0 |
91 | | - |
| 56 | + xvalue = data[10:17] |
| 57 | + (volt, temp, humi, batt) = unpack(">hHHB", xvalue) |
92 | 58 | self.update_predefined_sensor(SensorLibrary.BATTERY__PERCENTAGE, batt) |
93 | | - self.update_predefined_sensor(SensorLibrary.TEMPERATURE__CELSIUS, temp / 16) |
94 | | - self.update_predefined_sensor(SensorLibrary.HUMIDITY__PERCENTAGE, humi / 16) |
| 59 | + self.update_predefined_sensor(SensorLibrary.TEMPERATURE__CELSIUS, temp / 100) |
| 60 | + self.update_predefined_sensor(SensorLibrary.HUMIDITY__PERCENTAGE, humi / 100) |
95 | 61 | self.update_predefined_sensor( |
96 | | - SensorLibrary.VOLTAGE__ELECTRIC_POTENTIAL_VOLT, volt / 1000 |
97 | | - ) |
98 | | - self.update_predefined_binary_sensor( |
99 | | - BinarySensorDeviceClass.OCCUPANCY, bool(button_pushed) |
| 62 | + SensorLibrary.VOLTAGE__ELECTRIC_POTENTIAL_VOLT, volt / 100 |
100 | 63 | ) |
0 commit comments