diff --git a/aioesphomeapi/model.py b/aioesphomeapi/model.py index 85e7ed1..bb9aaec 100644 --- a/aioesphomeapi/model.py +++ b/aioesphomeapi/model.py @@ -1120,3 +1120,36 @@ class VoiceAssistantEventType(APIIntEnum): VOICE_ASSISTANT_WAKE_WORD_END = 10 VOICE_ASSISTANT_STT_VAD_START = 11 VOICE_ASSISTANT_STT_VAD_END = 12 + + +_TYPE_TO_NAME = { + BinarySensorInfo: "binary_sensor", + ButtonInfo: "button", + CoverInfo: "cover", + FanInfo: "fan", + LightInfo: "light", + NumberInfo: "number", + SelectInfo: "select", + SensorInfo: "sensor", + SirenInfo: "siren", + SwitchInfo: "switch", + TextSensorInfo: "text_sensor", + CameraInfo: "camera", + ClimateInfo: "climate", + LockInfo: "lock", + MediaPlayerInfo: "media_player", + AlarmControlPanelInfo: "alarm_control_panel", +} + + +def build_unique_id(formatted_mac: str, entity_info: EntityInfo) -> str: + """Build a unique id for an entity. + + This is the new format for unique ids which replaces the old format + that is included in the EntityInfo object. This new format is used + because the old format used the name in the unique id which is not + guaranteed to be unique. This new format is guaranteed to be unique + and is also more human readable. + """ + # -- + return f"{formatted_mac}-{_TYPE_TO_NAME[type(entity_info)]}-{entity_info.object_id}" diff --git a/tests/test_model.py b/tests/test_model.py index 592bce3..9871c4b 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -39,6 +39,7 @@ from aioesphomeapi.api_pb2 import ( TextSensorStateResponse, ) from aioesphomeapi.model import ( + _TYPE_TO_NAME, AlarmControlPanelEntityState, AlarmControlPanelInfo, APIIntEnum, @@ -47,6 +48,7 @@ from aioesphomeapi.model import ( BinarySensorInfo, BinarySensorState, ButtonInfo, + CameraInfo, ClimateInfo, ClimatePreset, ClimateState, @@ -69,6 +71,7 @@ from aioesphomeapi.model import ( SelectState, SensorInfo, SensorState, + SirenInfo, SwitchInfo, SwitchState, TextSensorInfo, @@ -76,6 +79,7 @@ from aioesphomeapi.model import ( UserService, UserServiceArg, UserServiceArgType, + build_unique_id, converter_field, ) @@ -321,3 +325,29 @@ def test_user_service_conversion(): assert UserService.from_dict({"args": [{"name": "arg", "type": 1}]}) == UserService( args=[UserServiceArg(name="arg", type=UserServiceArgType.INT)] ) + + +@pytest.mark.parametrize( + "model", + [ + BinarySensorInfo, + ButtonInfo, + CoverInfo, + FanInfo, + LightInfo, + NumberInfo, + SelectInfo, + SensorInfo, + SirenInfo, + SwitchInfo, + TextSensorInfo, + CameraInfo, + ClimateInfo, + LockInfo, + MediaPlayerInfo, + AlarmControlPanelInfo, + ], +) +def test_build_unique_id(model): + obj = model(object_id="id") + assert build_unique_id("mac", obj) == f"mac-{_TYPE_TO_NAME[type(obj)]}-id"