Skip to content

Commit

Permalink
feat: add support for h5127 (#101)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco authored Jul 24, 2024
1 parent 304af5b commit 5e84208
Show file tree
Hide file tree
Showing 2 changed files with 219 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/govee_ble/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ class SensorType(Enum):
MOTION = "motion"
WINDOW = "window"
VIBRATION = "vibration"
PRESENCE = "presence"


@dataclass
Expand All @@ -149,6 +150,7 @@ class ModelInfo:
"H5124": ModelInfo("H5124", SensorType.VIBRATION, 0, True),
"H5125": ModelInfo("H5125", SensorType.BUTTON, 6, True),
"H5126": ModelInfo("H5126", SensorType.BUTTON, 2, True),
"H5127": ModelInfo("H5127", SensorType.PRESENCE, 0, True),
}


Expand Down Expand Up @@ -311,6 +313,20 @@ def _process_mfr_data(
self.fire_event(f"button_{button_number_pressed}", "press")
return

if msg_length == 6 and (
data.startswith(b"\xec\x00\x01\x01")
and "H5127" in local_name
or mgr_id == 0x8803
):
self.set_device_type("H5127")
self.set_device_name(f"H5127{short_address(address)}")
present = data[4] == 1
motion = data[5] == 17
self.update_predefined_binary_sensor(
BinarySensorDeviceClass.OCCUPANCY, present
)
self.update_predefined_binary_sensor(BinarySensorDeviceClass.MOTION, motion)

if msg_length == 6 and (
(is_5072 := "H5072" in local_name)
or (is_5075 := "H5075" in local_name)
Expand Down
203 changes: 203 additions & 0 deletions tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,37 @@
)


GVH5127_MOTION_SERVICE_INFO = BluetoothServiceInfo(
name="GVH51275E3F",
address="D0:C9:07:1B:5E:3F",
rssi=-61,
manufacturer_data={34819: b"\xec\x00\x01\x01\x01\x11"},
service_data={},
service_uuids=[],
source="Core Bluetooth",
)
GVH5127_PRESENT_SERVICE_INFO = BluetoothServiceInfo(
name="GVH51275E3F",
address="D0:C9:07:1B:5E:3F",
rssi=-60,
manufacturer_data={34819: b"\xec\x00\x01\x01\x01\x01"},
service_data={},
service_uuids=[],
source="Core Bluetooth",
)


GVH5127_ABSENT_SERVICE_INFO = BluetoothServiceInfo(
name="GVH51275E3F",
address="D0:C9:07:1B:5E:3F",
rssi=-53,
manufacturer_data={34819: b"\xec\x00\x01\x01\x00\x00"},
service_data={},
service_uuids=[],
source="Core Bluetooth",
)


def test_can_create():
GoveeBluetoothDeviceData()

Expand Down Expand Up @@ -4196,3 +4227,175 @@ def test_get_model_info():
assert get_model_info("H5126").sensor_type == SensorType.BUTTON
assert get_model_info("H5126").button_count == 2
assert get_model_info("H5124").sensor_type == SensorType.VIBRATION
assert get_model_info("H5127").sensor_type == SensorType.PRESENCE


def test_gvh5127_motion():
parser = GoveeBluetoothDeviceData()
service_info = GVH5127_MOTION_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 0
assert parser.sensor_type is SensorType.PRESENCE
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H51275E3F",
model="H5127",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
)
},
entity_values={
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-61,
)
},
binary_entity_descriptions={
DeviceKey(key="occupancy", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="occupancy", device_id=None),
device_class=BinarySensorDeviceClass.OCCUPANCY,
),
DeviceKey(key="motion", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="motion", device_id=None),
device_class=BinarySensorDeviceClass.MOTION,
),
},
binary_entity_values={
DeviceKey(key="occupancy", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="occupancy", device_id=None),
name="Occupancy",
native_value=True,
),
DeviceKey(key="motion", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="motion", device_id=None),
name="Motion",
native_value=True,
),
},
events={},
)


def test_gvh5127_presence():
parser = GoveeBluetoothDeviceData()
service_info = GVH5127_PRESENT_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 0
assert parser.sensor_type is SensorType.PRESENCE
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H51275E3F",
model="H5127",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
)
},
entity_values={
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-60,
)
},
binary_entity_descriptions={
DeviceKey(key="occupancy", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="occupancy", device_id=None),
device_class=BinarySensorDeviceClass.OCCUPANCY,
),
DeviceKey(key="motion", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="motion", device_id=None),
device_class=BinarySensorDeviceClass.MOTION,
),
},
binary_entity_values={
DeviceKey(key="occupancy", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="occupancy", device_id=None),
name="Occupancy",
native_value=True,
),
DeviceKey(key="motion", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="motion", device_id=None),
name="Motion",
native_value=False,
),
},
events={},
)


def test_gvh5127_absent():
parser = GoveeBluetoothDeviceData()
service_info = GVH5127_ABSENT_SERVICE_INFO
result = parser.update(service_info)
assert parser.button_count == 0
assert parser.sensor_type is SensorType.PRESENCE
assert result == SensorUpdate(
title=None,
devices={
None: SensorDeviceInfo(
name="H51275E3F",
model="H5127",
manufacturer="Govee",
sw_version=None,
hw_version=None,
)
},
entity_descriptions={
DeviceKey(key="signal_strength", device_id=None): SensorDescription(
device_key=DeviceKey(key="signal_strength", device_id=None),
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
native_unit_of_measurement=Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
)
},
entity_values={
DeviceKey(key="signal_strength", device_id=None): SensorValue(
device_key=DeviceKey(key="signal_strength", device_id=None),
name="Signal " "Strength",
native_value=-53,
)
},
binary_entity_descriptions={
DeviceKey(key="occupancy", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="occupancy", device_id=None),
device_class=BinarySensorDeviceClass.OCCUPANCY,
),
DeviceKey(key="motion", device_id=None): BinarySensorDescription(
device_key=DeviceKey(key="motion", device_id=None),
device_class=BinarySensorDeviceClass.MOTION,
),
},
binary_entity_values={
DeviceKey(key="occupancy", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="occupancy", device_id=None),
name="Occupancy",
native_value=False,
),
DeviceKey(key="motion", device_id=None): BinarySensorValue(
device_key=DeviceKey(key="motion", device_id=None),
name="Motion",
native_value=False,
),
},
events={},
)

0 comments on commit 5e84208

Please sign in to comment.