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 AnalogInput, MultistateInput, use description attribute for fallback_name #197

Open
wants to merge 15 commits into
base: dev
Choose a base branch
from
Open
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
1,100 changes: 0 additions & 1,100 deletions tests/data/devices/isilentllc-dog-feeder.json

This file was deleted.

1,176 changes: 0 additions & 1,176 deletions tests/data/devices/isilentllc-masterbed-light-controller.json

This file was deleted.

1,118 changes: 0 additions & 1,118 deletions tests/data/devices/lumi-lumi-airmonitor-acn01.json

This file was deleted.

3,400 changes: 0 additions & 3,400 deletions tests/data/devices/lumi-lumi-plug-maus01.json

This file was deleted.

1,582 changes: 0 additions & 1,582 deletions tests/data/devices/lumi-lumi-relay-c2acn01.json

This file was deleted.

689 changes: 0 additions & 689 deletions tests/data/devices/lumi-lumi-remote-b286opcn01.json

This file was deleted.

523 changes: 0 additions & 523 deletions tests/data/devices/lumi-lumi-remote-b486opcn01.json

This file was deleted.

671 changes: 0 additions & 671 deletions tests/data/devices/lumi-lumi-remote-b686opcn01.json

This file was deleted.

1,326 changes: 0 additions & 1,326 deletions tests/data/devices/lumi-lumi-remote-cagl02.json

This file was deleted.

1,903 changes: 0 additions & 1,903 deletions tests/data/devices/lumi-lumi-sensor-86sw2.json

This file was deleted.

643 changes: 0 additions & 643 deletions tests/data/devices/lumi-lumi-sensor-smoke.json

This file was deleted.

901 changes: 0 additions & 901 deletions tests/data/devices/lumi-lumi-sensor-switch-aq3.json

This file was deleted.

1,513 changes: 0 additions & 1,513 deletions tests/data/devices/lumi-lumi-vibration-aq1.json

This file was deleted.

882 changes: 0 additions & 882 deletions tests/data/devices/third-reality-inc-3rsb22bz.json

This file was deleted.

1,988 changes: 0 additions & 1,988 deletions tests/data/devices/third-reality-inc-3rsnl02043z.json

This file was deleted.

30 changes: 30 additions & 0 deletions tests/test_binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@
}
}

DEVICE_GENERAL = {
1: {
SIG_EP_PROFILE: zigpy.profiles.zha.PROFILE_ID,
SIG_EP_TYPE: zigpy.profiles.zha.DeviceType.ON_OFF_SENSOR,
SIG_EP_INPUT: [general.BinaryInput.cluster_id],
SIG_EP_OUTPUT: [],
}
}

DEVICE_SMARTTHINGS_MULTI = {
1: {
Expand Down Expand Up @@ -163,13 +171,35 @@ async def test_binary_sensor(
assert entity is not None
assert isinstance(entity, entity_type)
assert entity.PLATFORM == Platform.BINARY_SENSOR

assert entity.fallback_name is None
assert entity.is_on is False

# test getting messages that trigger and reset the sensors
cluster = getattr(zigpy_device.endpoints[1], cluster_name)
await on_off_test(zha_gateway, cluster, entity, plugs)


async def test_binary_sensor_general(
zha_gateway: Gateway,
) -> None:
"""Test binary sensor general - description."""
zigpy_device = create_mock_zigpy_device(
zha_gateway, DEVICE_GENERAL, manufacturer="DevManuf", model="DevModel"
)

cluster = getattr(zigpy_device.endpoints[1], "binary_input")
cluster.PLUGGED_ATTR_READS = {"description": "Binary Input", "present_value": 1}
update_attribute_cache(cluster)
zha_device = await join_zigpy_device(zha_gateway, zigpy_device)
entity: PlatformEntity = find_entity(zha_device, Platform.BINARY_SENSOR)

await entity.async_update()
await zha_gateway.async_block_till_done()
assert entity.fallback_name == "Binary Input"
assert entity.translation_key is None


async def test_smarttthings_multi(
zha_gateway: Gateway,
) -> None:
Expand Down
29 changes: 29 additions & 0 deletions tests/test_number.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ async def test_number(
assert cluster.read_attributes.call_count == 3

assert entity.description == "PWM1"
assert entity.fallback_name == "PWM1"
assert entity.translation_key is None

# test that the state is 15.0
assert entity.state["state"] == 15.0
Expand Down Expand Up @@ -185,6 +187,33 @@ async def test_number(
assert entity.state["state"] == 30.0


async def test_number_missing_description_attr(
zigpy_analog_output_device: ZigpyDevice, # pylint: disable=redefined-outer-name
zha_gateway: Gateway,
) -> None:
"""Test zha number platform - missing description attribute."""
cluster: general.AnalogOutput = zigpy_analog_output_device.endpoints.get(
1
).analog_output
cluster.PLUGGED_ATTR_READS = {
"max_present_value": 100.0,
"min_present_value": 1.0,
"relinquish_default": 50.0,
"resolution": 1.1,
"engineering_units": 98,
"application_type": 4 * 0x10000,
}
update_attribute_cache(cluster)
zha_device = await join_zigpy_device(zha_gateway, zigpy_analog_output_device)

entity: PlatformEntity = get_entity(zha_device, platform=Platform.NUMBER)
assert isinstance(entity, PlatformEntity)

assert entity.description is None
assert entity.fallback_name is None
assert entity.translation_key == "number"


@pytest.mark.parametrize(
("attr", "initial_value", "new_value", "max_value"),
(
Expand Down
131 changes: 131 additions & 0 deletions tests/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,65 @@ async def async_test_change_source_timestamp(
assert entity.state["state"] == datetime(2024, 10, 4, 11, 15, 15, tzinfo=UTC)


async def async_test_general_analog_input(
zha_gateway: Gateway, cluster: Cluster, entity: PlatformEntity
):
"""Test general analog input."""
await entity.async_update()

assert entity.device_class == SensorDeviceClass.HUMIDITY.value

if entity._cluster_handler.resolution is not None:
assert entity.suggested_display_precision == 1
else:
assert entity.suggested_display_precision is None

assert entity._cluster_handler.max_present_value == 100.0
assert entity._cluster_handler.min_present_value == 1.0
assert entity._cluster_handler.out_of_service == 0
assert entity._cluster_handler.reliability == 0
assert entity._cluster_handler.status_flags == 0
assert entity._cluster_handler.application_type == 0x00070100
assert entity._cluster_handler.present_value == 1.0

await send_attributes_report(
zha_gateway, cluster, {general.AnalogInput.AttributeDefs.present_value.id: 1.0}
)
assert_state(entity, 1.0, "%")


async def async_test_general_multistate_input(
zha_gateway: Gateway, cluster: Cluster, entity: PlatformEntity
):
"""Test general multistate input."""
await entity.async_update()

assert entity._cluster_handler.number_of_states == 2
assert entity._cluster_handler.out_of_service == 0
assert entity._cluster_handler.present_value == 1
assert entity._cluster_handler.reliability == 0
assert entity._cluster_handler.status_flags == 0
assert entity._cluster_handler.application_type == 0x00000009

if entity._cluster_handler.state_text is None:
assert_state(entity, "state_1", None)
await send_attributes_report(
zha_gateway,
cluster,
{general.MultistateInput.AttributeDefs.present_value.id: 2},
)
assert_state(entity, "state_2", None)
else:
assert entity._cluster_handler.state_text == ["Night", "Day", "Hold"]
assert_state(entity, "Night", None)
await send_attributes_report(
zha_gateway,
cluster,
{general.MultistateInput.AttributeDefs.present_value.id: 2},
)
assert_state(entity, "Day", None)


@pytest.mark.parametrize(
"cluster_id, entity_type, test_func, read_plug, unsupported_attrs",
(
Expand Down Expand Up @@ -570,6 +629,72 @@ async def async_test_change_source_timestamp(
None,
None,
),
(
general.AnalogInput.cluster_id,
sensor.AnalogInputSensor,
async_test_general_analog_input,
{
"present_value": 1.0,
"description": "Analog Input",
"max_present_value": 100.0,
"min_present_value": 1.0,
"out_of_service": 0,
"reliability": 0,
"resolution": 1.1,
"status_flags": 0,
"engineering_units": 98,
"application_type": 0x00070100,
},
None,
),
(
general.AnalogInput.cluster_id,
sensor.AnalogInputSensor,
async_test_general_analog_input,
{
"present_value": 1.0,
"description": "Analog Input",
"max_present_value": 100.0,
"min_present_value": 1.0,
"out_of_service": 0,
"reliability": 0,
"status_flags": 0,
"engineering_units": 98,
"application_type": 0x00070100,
},
None,
),
(
general.MultistateInput.cluster_id,
sensor.MultiStateInputSensor,
async_test_general_multistate_input,
{
"state_text": t.LVList(["Night", "Day", "Hold"]),
"description": "Multistate Input",
"number_of_states": 2,
"out_of_service": 0,
"present_value": 1,
"reliability": 0,
"status_flags": 0,
"application_type": 0x00000009,
},
None,
),
(
general.MultistateInput.cluster_id,
sensor.MultiStateInputSensor,
async_test_general_multistate_input,
{
"description": "Multistate Input",
"number_of_states": 2,
"out_of_service": 0,
"present_value": 1,
"reliability": 0,
"status_flags": 0,
"application_type": 0x00000009,
},
None,
),
),
)
async def test_sensor(
Expand Down Expand Up @@ -611,6 +736,12 @@ async def test_sensor(
)

await zha_gateway.async_block_till_done()

if read_plug and read_plug.get("description", None):
assert entity.fallback_name == read_plug.get("description", None)
assert entity.translation_key is None
else:
assert entity.fallback_name is None
# test sensor associated logic
await test_func(zha_gateway, cluster, entity)

Expand Down
6 changes: 6 additions & 0 deletions zha/application/platforms/binary_sensor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ def __init__(
CLUSTER_HANDLER_ATTRIBUTE_UPDATED,
self.handle_cluster_handler_attribute_updated,
)
if (
hasattr(self._cluster_handler, "description")
and self._cluster_handler.description is not None
):
self._attr_translation_key = None
self._attr_fallback_name: str = self._cluster_handler.description

def _init_from_quirks_metadata(self, entity_metadata: BinarySensorMetadata) -> None:
"""Init this entity from the quirks metadata."""
Expand Down
8 changes: 8 additions & 0 deletions zha/application/platforms/number/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,14 @@ def __init__(
CLUSTER_HANDLER_ATTRIBUTE_UPDATED,
self.handle_cluster_handler_attribute_updated,
)
if (
hasattr(self._analog_output_cluster_handler, "description")
and self._analog_output_cluster_handler.description is not None
):
self._attr_translation_key = None
self._attr_fallback_name: str = (
self._analog_output_cluster_handler.description
)

@functools.cached_property
def info_object(self) -> NumberEntityInfo:
Expand Down
Loading