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

Add Govee H5055 #1418

Merged
merged 1 commit into from
Dec 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions custom_components/ble_monitor/ble_parser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,10 @@ def parse_advertisement(
# Thermobeacon
sensor_data = parse_thermobeacon(self, man_spec_data, mac)
break
elif comp_id == 0xEA1C and data_len == 0x17:
# Govee H50555
sensor_data = parse_govee(self, man_spec_data, service_class_uuid16, local_name, mac)
break
elif comp_id == 0xEC88 and data_len in [0x09, 0x0A, 0x0C, 0x22, 0x24, 0x25]:
# Govee H5051/H5071/H5072/H5075/H5074
sensor_data = parse_govee(self, man_spec_data, service_class_uuid16, local_name, mac)
Expand Down
43 changes: 43 additions & 0 deletions custom_components/ble_monitor/ble_parser/govee.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ def decode_temps_probes(packet_value: int) -> float:
return float(packet_value / 100)


def decode_temps_probes_negative(packet_value: int) -> float:
"""Filter potential negative temperatures."""
if packet_value < 0:
return 0.0
return float(packet_value)


def decode_pm25_from_4_bytes(packet_value: int) -> int:
"""Decode humidity values"""
packet_value &= 0x7FFFFFFF
Expand Down Expand Up @@ -231,6 +238,42 @@ def parse_govee(self, data: str, service_class_uuid16: int, local_name: str, mac
else:
_LOGGER.debug("Unknown sensor id found for Govee H5198. Data %s", data.hex())
return None
elif msg_length == 24 and device_id == 0xEA1C:
device_type = "H5055"
battery = data[6]
if battery:
result.update({"battery": battery})
sensor_id = data[7]
(temp_probe_first, high_temp_alarm_first, low_temp_alarm_first, _, temp_probe_second, high_temp_alarm_second, low_temp_alarm_second) = unpack(
"<hhhchhh", data[9:22]
)
if int(sensor_id) & 0xC0 == 0:
result.update({
"temperature probe 1": decode_temps_probes_negative(temp_probe_first),
"temperature alarm probe 1": decode_temps_probes_negative(high_temp_alarm_first),
"low temperature alarm probe 1": decode_temps_probes_negative(low_temp_alarm_first),
"temperature probe 2": decode_temps_probes_negative(temp_probe_second),
"temperature alarm probe 2": decode_temps_probes_negative(high_temp_alarm_second),
"low temperature alarm probe 2": decode_temps_probes_negative(low_temp_alarm_second)
})
elif int(sensor_id) & 0xC0 == 64:
result.update({
"temperature probe 3": decode_temps_probes_negative(temp_probe_first),
"temperature alarm probe 3": decode_temps_probes_negative(high_temp_alarm_first),
"low temperature alarm probe 3": decode_temps_probes_negative(low_temp_alarm_first),
"temperature probe 4": decode_temps_probes_negative(temp_probe_second),
"temperature alarm probe 4": decode_temps_probes_negative(high_temp_alarm_second),
"low temperature alarm probe 4": decode_temps_probes_negative(low_temp_alarm_second),
})
elif int(sensor_id) & 0xC0 == 128:
result.update({
"temperature probe 5": decode_temps_probes_negative(temp_probe_first),
"temperature alarm probe 5": decode_temps_probes_negative(high_temp_alarm_first),
"low temperature alarm probe 5": decode_temps_probes_negative(low_temp_alarm_first),
"temperature probe 6": decode_temps_probes_negative(temp_probe_second),
"temperature alarm probe 6": decode_temps_probes_negative(high_temp_alarm_second),
"low temperature alarm probe 6": decode_temps_probes_negative(low_temp_alarm_second),
})
else:
if self.report_unknown == "Govee":
_LOGGER.info(
Expand Down
46 changes: 46 additions & 0 deletions custom_components/ble_monitor/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,28 @@ class BLEMonitorBinarySensorEntityDescription(
suggested_display_precision=0,
state_class=SensorStateClass.MEASUREMENT,
),
BLEMonitorSensorEntityDescription(
key="temperature alarm probe 5",
sensor_class="TemperatureSensor",
update_behavior="Averaging",
name="ble temperature alarm probe 5",
unique_id="t_alarm_probe_5_",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
device_class=SensorDeviceClass.TEMPERATURE,
suggested_display_precision=0,
state_class=SensorStateClass.MEASUREMENT,
),
BLEMonitorSensorEntityDescription(
key="temperature alarm probe 6",
sensor_class="TemperatureSensor",
update_behavior="Averaging",
name="ble temperature alarm probe 6",
unique_id="t_alarm_probe_6_",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
device_class=SensorDeviceClass.TEMPERATURE,
suggested_display_precision=0,
state_class=SensorStateClass.MEASUREMENT,
),
BLEMonitorSensorEntityDescription(
key="low temperature alarm probe 1",
sensor_class="TemperatureSensor",
Expand Down Expand Up @@ -724,6 +746,28 @@ class BLEMonitorBinarySensorEntityDescription(
suggested_display_precision=0,
state_class=SensorStateClass.MEASUREMENT,
),
BLEMonitorSensorEntityDescription(
key="low temperature alarm probe 5",
sensor_class="TemperatureSensor",
update_behavior="Averaging",
name="ble low temperature alarm probe 5",
unique_id="t_alarm_low_probe_5_",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
device_class=SensorDeviceClass.TEMPERATURE,
suggested_display_precision=0,
state_class=SensorStateClass.MEASUREMENT,
),
BLEMonitorSensorEntityDescription(
key="low temperature alarm probe 6",
sensor_class="TemperatureSensor",
update_behavior="Averaging",
name="ble low temperature alarm probe 6",
unique_id="t_alarm_low_probe_6_",
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
device_class=SensorDeviceClass.TEMPERATURE,
suggested_display_precision=0,
state_class=SensorStateClass.MEASUREMENT,
),
BLEMonitorSensorEntityDescription(
key="temperature probe tip",
sensor_class="TemperatureSensor",
Expand Down Expand Up @@ -1922,6 +1966,7 @@ class BLEMonitorBinarySensorEntityDescription(
'H5101/H5102/H5177' : [["temperature", "humidity", "battery", "rssi"], [], []],
'H5051/H5071' : [["temperature", "humidity", "battery", "rssi"], [], []],
'H5052' : [["temperature", "humidity", "battery", "rssi"], [], []],
'H5055' : [["temperature probe 1", "temperature alarm probe 1", "low temperature alarm probe 1", "temperature probe 2", "temperature alarm probe 2", "low temperature alarm probe 2", "temperature probe 3", "temperature alarm probe 3", "low temperature alarm probe 3", "temperature probe 4", "temperature alarm probe 4", "low temperature alarm probe 4", "temperature probe 5", "temperature alarm probe 5", "low temperature alarm probe 5", "temperature probe 6", "temperature alarm probe 6", "low temperature alarm probe 6", "battery", "rssi"], [], []],
'H5071' : [["temperature", "humidity", "battery", "rssi"], [], []],
'H5074' : [["temperature", "humidity", "battery", "rssi"], [], []],
'H5106' : [["temperature", "humidity", "pm2.5", "rssi"], [], []],
Expand Down Expand Up @@ -2059,6 +2104,7 @@ class BLEMonitorBinarySensorEntityDescription(
'H5101/H5102/H5177' : 'Govee',
'H5051/H5071' : 'Govee',
'H5052' : 'Govee',
'H5055' : 'Govee',
'H5071' : 'Govee',
'H5074' : 'Govee',
'H5106' : 'Govee',
Expand Down
22 changes: 22 additions & 0 deletions custom_components/ble_monitor/test/test_govee_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,28 @@ def test_Govee_H5051(self):
assert sensor_msg["battery"] == 99
assert sensor_msg["rssi"] == -73

def test_Govee_H5055(self):
"""Test Govee H5055 parser."""
data_string = "043e270201000005351338c1a41b02010617ff1cea3500644120ffffffffffff203200ffffffff0000c4"
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"] == "Govee"
assert sensor_msg["type"] == "H5055"
assert sensor_msg["mac"] == "A4C138133505"
assert sensor_msg["packet"] == "no packet id"
assert sensor_msg["data"]
assert sensor_msg["temperature probe 3"] == 0.0
assert sensor_msg["temperature alarm probe 3"] == 0.0
assert sensor_msg["low temperature alarm probe 3"] == 0.0
assert sensor_msg["temperature probe 4"] == 50.0
assert sensor_msg["temperature alarm probe 4"] == 0.0
assert sensor_msg["low temperature alarm probe 4"] == 0.0
assert sensor_msg["battery"] == 100
assert sensor_msg["rssi"] == -60

def test_Govee_H5074(self):
"""Test Govee H5074 parser."""
data_string = "043e1702010400aabb611d12e00b0aff88ec0088078c116402a6"
Expand Down
19 changes: 19 additions & 0 deletions docs/_devices/Govee_H5055.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
manufacturer: Govee
name: Smart Meat Thermometer
model: H5055
image: Govee_H5055.png
physical_description: Square body, with 6 probes.
broadcasted_properties:
- temperature probe
- temperature alarm probe
- battery
- rssi
broadcasted_property_notes:
broadcast_rate:
active_scan: true
encryption_key:
custom_firmware:
notes:
- actve scan needs to be enabled in the BLE Monitor settings for this sensor to work.
---
Binary file added docs/assets/images/Govee_H5055.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading