diff --git a/custom_components/ble_monitor/ble_parser/bthome_const.py b/custom_components/ble_monitor/ble_parser/bthome_const.py index a2fac78ad..cb8431e55 100644 --- a/custom_components/ble_monitor/ble_parser/bthome_const.py +++ b/custom_components/ble_monitor/ble_parser/bthome_const.py @@ -123,7 +123,7 @@ class MeasTypes: factor=0.01, ), 0x15: MeasTypes( - meas_format="battery", + meas_format="battery low", ), 0x16: MeasTypes( meas_format="battery charging", diff --git a/custom_components/ble_monitor/ble_parser/teltonika.py b/custom_components/ble_monitor/ble_parser/teltonika.py index 24808545b..c027c23d0 100644 --- a/custom_components/ble_monitor/ble_parser/teltonika.py +++ b/custom_components/ble_monitor/ble_parser/teltonika.py @@ -82,17 +82,17 @@ def parse_teltonika(self, data, complete_local_name, source_mac, rssi): # Magnetic sensor presence if flags & (1 << 3): # bit 3 # magnetic field is detected - result.update({"magnetic field": 1}) + result.update({"magnetic field detected": 1}) else: # magnetic field is not detected - result.update({"magnetic field": 0}) + result.update({"magnetic field detected": 0}) if flags & (1 << 4): # bit 4 # Movement sensor counter # Most significant bit indicates movement state # 15 least significant bits represent count of movement events. - movement = sensor_data[0] & (1 << 7) + moving = sensor_data[0] & (1 << 7) count = ((sensor_data[0] & 0b01111111) << 8) + sensor_data[1] - result.update({"movement": movement, "count": count}) + result.update({"moving": moving, "count": count}) sensor_data = sensor_data[2:] if flags & (1 << 5): # bit 5 # Movement sensor angle @@ -103,7 +103,7 @@ def parse_teltonika(self, data, complete_local_name, source_mac, rssi): sensor_data = sensor_data[3:] if flags & (1 << 6): # bit 6 # Low battery indication sensor presence - result.update({"low battery": 1}) + result.update({"battery low": 1}) if flags & (1 << 7): # bit 7 # Battery voltage value presence volt = round(2.0 + sensor_data[0] * 0.01, 3) diff --git a/custom_components/ble_monitor/const.py b/custom_components/ble_monitor/const.py index 5b7b44c37..f11b78e49 100755 --- a/custom_components/ble_monitor/const.py +++ b/custom_components/ble_monitor/const.py @@ -134,6 +134,15 @@ class BLEMonitorBinarySensorEntityDescription( device_class=BinarySensorDeviceClass.BATTERY_CHARGING, force_update=True, ), + BLEMonitorBinarySensorEntityDescription( + key="battery low", + sensor_class="BaseBinarySensor", + update_behavior="Instantly", + name="battery low", + unique_id="bl_", + device_class=BinarySensorDeviceClass.BATTERY, + force_update=True, + ), BLEMonitorBinarySensorEntityDescription( key="carbon monoxide", sensor_class="BaseBinarySensor", @@ -465,6 +474,16 @@ class BLEMonitorBinarySensorEntityDescription( device_class=None, force_update=False, ), + BLEMonitorBinarySensorEntityDescription( + key="magnetic field detected", + sensor_class="BaseBinarySensor", + update_behavior="Instantly", + name="magnetic field", + unique_id="magnetic_field_", + icon="mdi:magnet", + device_class=None, + force_update=False, + ), BLEMonitorBinarySensorEntityDescription( key="bed occupancy", sensor_class="BaseBinarySensor", @@ -1035,6 +1054,30 @@ class BLEMonitorBinarySensorEntityDescription( suggested_display_precision=1, state_class=SensorStateClass.MEASUREMENT, ), + BLEMonitorSensorEntityDescription( + key="roll", + sensor_class="InstantUpdateSensor", + update_behavior="Instantly", + name="roll", + unique_id="roll_", + icon="mdi:horizontal-rotate-clockwise", + native_unit_of_measurement="°", + device_class=None, + suggested_display_precision=0, + state_class=SensorStateClass.MEASUREMENT, + ), + BLEMonitorSensorEntityDescription( + key="pitch", + sensor_class="InstantUpdateSensor", + update_behavior="Instantly", + name="pitch", + unique_id="pitch_", + icon="mdi:rotate-right-variant", + native_unit_of_measurement="°", + device_class=None, + suggested_display_precision=0, + state_class=SensorStateClass.MEASUREMENT, + ), BLEMonitorSensorEntityDescription( key="distance", sensor_class="InstantUpdateSensor", @@ -1796,18 +1839,23 @@ class BLEMonitorBinarySensorEntityDescription( # Sensors that support automatic adding of sensors and binary sensors AUTO_MANUFACTURER_DICT = { 'Amazfit Smart Scale' : 'Amazfit', + 'Blustream' : 'Blustream', 'BTHome' : 'BTHome', 'HHCCJCY10' : 'HHCC', + 'HolyIOT BLE tracker' : 'HolyIOT', + 'Supramatic E4 BS' : 'Hörmann', 'IBS-TH' : 'Inkbird', 'IBS-TH2/P01B' : 'Inkbird', 'JHT' : 'Jaalee', 'TG-BT5-IN' : 'Mikrotik', 'TG-BT5-OUT' : 'Mikrotik', + 'Electra Washbasin Faucet': 'Oras', 'EClerk Eco' : 'Relsib', 'WT51' : 'Relsib', 'Blue Puck T' : 'Teltonika', 'Blue Coin T' : 'Teltonika', 'Blue Puck RHT' : 'Teltonika', + 'EYE sensor' : 'Teltonika', 'TP357' : 'Thermopro', 'TP359' : 'Thermopro', 'Tilt Red' : 'Tilt', @@ -1819,16 +1867,13 @@ class BLEMonitorBinarySensorEntityDescription( 'Tilt Yellow' : 'Tilt', 'Tilt Pink' : 'Tilt', 'MMC-W505' : 'Xiaomi', - 'Electra Washbasin Faucet': 'Oras', - 'Supramatic E4 BS' : 'Hörmann', - 'Blustream' : 'Blustream', - 'HolyIOT BLE tracker' : 'HolyIOT', } # Binary Sensors that are automatically added if device is in AUTO_MANUFACTURER_DICT AUTO_BINARY_SENSOR_LIST = [ "battery charging", + "battery low", "carbon monoxide", "cold", "connectivity", @@ -1841,6 +1886,7 @@ class BLEMonitorBinarySensorEntityDescription( "impact", "light", "lock", + "magnetic field detected", "motion", "moisture detected", "moving", @@ -1886,11 +1932,13 @@ class BLEMonitorBinarySensorEntityDescription( "moisture", "non-stabilized weight", "opening percentage", + "pitch", "pm2.5", "pm10", "power", "pressure", "pulse", + "roll", "rotation", "speed", "steps", diff --git a/custom_components/ble_monitor/sensor.py b/custom_components/ble_monitor/sensor.py index 239136560..d5a16e2b0 100644 --- a/custom_components/ble_monitor/sensor.py +++ b/custom_components/ble_monitor/sensor.py @@ -339,6 +339,8 @@ class BaseSensor(RestoreSensor, SensorEntity): # | |**pulse # | |**shake # | |**rotation + # | |**roll + # | |**pitch # | |**distance # | |**distance mm # | |**duration diff --git a/custom_components/ble_monitor/test/test_bthome_v2.py b/custom_components/ble_monitor/test/test_bthome_v2.py index 5e07f0975..606f58e7e 100644 --- a/custom_components/ble_monitor/test/test_bthome_v2.py +++ b/custom_components/ble_monitor/test/test_bthome_v2.py @@ -305,6 +305,23 @@ def test_bthome_v2_moisture(self): assert sensor_msg["moisture"] == 3.07 assert sensor_msg["rssi"] == -52 + def test_bthome_v2_battery_low(self): + """Test BTHome parser for battery low measurement""" + data_string = "043E1602010000A5808FE648540A0201060616D2FC401501CC" + data = bytes(bytearray.fromhex(data_string)) + + # pylint: disable=unused-variable + ble_parser = BleParser() + sensor_msg, tracker_msg = ble_parser.parse_raw_data(data) + + assert sensor_msg["firmware"] == "BTHome V2" + assert sensor_msg["type"] == "BTHome" + assert sensor_msg["mac"] == "5448E68F80A5" + assert sensor_msg["packet"] == "no packet id" + assert sensor_msg["data"] + assert sensor_msg["battery low"] == 1 + assert sensor_msg["rssi"] == -52 + def test_bthome_v2_battery_charging(self): """Test BTHome parser for battery charging measurement""" data_string = "043E1602010000A5808FE648540A0201060616D2FC401601CC" diff --git a/custom_components/ble_monitor/test/test_teltonika.py b/custom_components/ble_monitor/test/test_teltonika.py index 2009f68c7..47850e9c8 100644 --- a/custom_components/ble_monitor/test/test_teltonika.py +++ b/custom_components/ble_monitor/test/test_teltonika.py @@ -118,8 +118,8 @@ def test_teltonika_eye(self): assert sensor_msg["data"] assert sensor_msg["temperature"] == 22.28 assert sensor_msg["humidity"] == 18 - assert sensor_msg["magnetic field"] == 0 - assert sensor_msg["movement"] == 0 + assert sensor_msg["magnetic field detected"] == 0 + assert sensor_msg["moving"] == 0 assert sensor_msg["count"] == 3275 assert sensor_msg["roll"] == -57 assert sensor_msg["pitch"] == 11