Skip to content

Commit

Permalink
Update Entities (#882)
Browse files Browse the repository at this point in the history
  • Loading branch information
jesserockz authored Jun 11, 2024
1 parent 516299e commit e41e9c9
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 60 deletions.
43 changes: 43 additions & 0 deletions aioesphomeapi/api.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1856,3 +1856,46 @@ message DateTimeCommandRequest {
fixed32 key = 1;
fixed32 epoch_seconds = 2;
}

// ==================== UPDATE ====================
message ListEntitiesUpdateResponse {
option (id) = 116;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_UPDATE";

string object_id = 1;
fixed32 key = 2;
string name = 3;
string unique_id = 4;

string icon = 5;
bool disabled_by_default = 6;
EntityCategory entity_category = 7;
string device_class = 8;
}
message UpdateStateResponse {
option (id) = 117;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_UPDATE";
option (no_delay) = true;

fixed32 key = 1;
bool missing_state = 2;
bool in_progress = 3;
bool has_progress = 4;
float progress = 5;
string current_version = 6;
string latest_version = 7;
string title = 8;
string release_summary = 9;
string release_url = 10;
}
message UpdateCommandRequest {
option (id) = 118;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_UPDATE";
option (no_delay) = true;

fixed32 key = 1;
bool install = 2;
}
154 changes: 95 additions & 59 deletions aioesphomeapi/api_pb2.py

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions aioesphomeapi/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
TextCommandRequest,
TimeCommandRequest,
UnsubscribeBluetoothLEAdvertisementsRequest,
UpdateCommandRequest,
ValveCommandRequest,
VoiceAssistantAudio,
VoiceAssistantEventData,
Expand Down Expand Up @@ -1214,6 +1215,11 @@ def media_player_command(
def text_command(self, key: int, state: str) -> None:
self._get_connection().send_message(TextCommandRequest(key=key, state=state))

def update_command(self, key: int, install: bool) -> None:
self._get_connection().send_message(
UpdateCommandRequest(key=key, install=install)
)

def execute_service(
self, service: UserService, data: ExecuteServiceDataType
) -> None:
Expand Down
6 changes: 6 additions & 0 deletions aioesphomeapi/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
ListEntitiesTextResponse,
ListEntitiesTextSensorResponse,
ListEntitiesTimeResponse,
ListEntitiesUpdateResponse,
ListEntitiesValveResponse,
LockCommandRequest,
LockStateResponse,
Expand Down Expand Up @@ -113,6 +114,8 @@
TimeCommandRequest,
TimeStateResponse,
UnsubscribeBluetoothLEAdvertisementsRequest,
UpdateCommandRequest,
UpdateStateResponse,
ValveCommandRequest,
ValveStateResponse,
VoiceAssistantAudio,
Expand Down Expand Up @@ -386,4 +389,7 @@ def __init__(self, error: BluetoothGATTError) -> None:
113: DateTimeStateResponse,
114: DateTimeCommandRequest,
115: VoiceAssistantTimerEventResponse,
116: ListEntitiesUpdateResponse,
117: UpdateStateResponse,
118: UpdateCommandRequest,
}
26 changes: 25 additions & 1 deletion aioesphomeapi/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ def converter_field(*, converter: Callable[[Any], _V], **kwargs: Any) -> _V:
metadata = kwargs.pop("metadata", {})
metadata["converter"] = converter
return cast(
_V, field(metadata=metadata, **kwargs) # pylint: disable=invalid-field-call
_V,
field(metadata=metadata, **kwargs), # pylint: disable=invalid-field-call
)


Expand Down Expand Up @@ -896,6 +897,27 @@ class TextState(EntityState):
missing_state: bool = False


# ==================== UPDATE ====================


@_frozen_dataclass_decorator
class UpdateInfo(EntityInfo):
device_class: str = ""


@_frozen_dataclass_decorator
class UpdateState(EntityState):
missing_state: bool = False
in_progress: bool = False
has_progress: bool = False
progress: float = 0.0
current_version: str = ""
latest_version: str = ""
title: str = ""
release_summary: str = ""
release_url: str = ""


# ==================== INFO MAP ====================

COMPONENT_TYPE_TO_INFO: dict[str, type[EntityInfo]] = {
Expand All @@ -921,6 +943,7 @@ class TextState(EntityState):
"time": TimeInfo,
"valve": ValveInfo,
"event": EventInfo,
"update": UpdateInfo,
}


Expand Down Expand Up @@ -1291,6 +1314,7 @@ class VoiceAssistantTimerEventType(APIIntEnum):
TimeInfo: "time",
ValveInfo: "valve",
EventInfo: "event",
UpdateInfo: "update",
}


Expand Down
6 changes: 6 additions & 0 deletions aioesphomeapi/model_conversions.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
ListEntitiesTextResponse,
ListEntitiesTextSensorResponse,
ListEntitiesTimeResponse,
ListEntitiesUpdateResponse,
ListEntitiesValveResponse,
LockStateResponse,
MediaPlayerStateResponse,
Expand All @@ -45,6 +46,7 @@
TextSensorStateResponse,
TextStateResponse,
TimeStateResponse,
UpdateStateResponse,
ValveStateResponse,
)
from .model import (
Expand Down Expand Up @@ -90,6 +92,8 @@
TextState,
TimeInfo,
TimeState,
UpdateInfo,
UpdateState,
ValveInfo,
ValveState,
)
Expand All @@ -114,6 +118,7 @@
TextSensorStateResponse: TextSensorState,
TextStateResponse: TextState,
TimeStateResponse: TimeState,
UpdateStateResponse: UpdateState,
ValveStateResponse: ValveState,
}

Expand All @@ -140,5 +145,6 @@
ListEntitiesTextResponse: TextInfo,
ListEntitiesTextSensorResponse: TextSensorInfo,
ListEntitiesTimeResponse: TimeInfo,
ListEntitiesUpdateResponse: UpdateInfo,
ListEntitiesValveResponse: ValveInfo,
}
21 changes: 21 additions & 0 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
SwitchCommandRequest,
TextCommandRequest,
TimeCommandRequest,
UpdateCommandRequest,
ValveCommandRequest,
VoiceAssistantAudio,
VoiceAssistantAudioSettings,
Expand Down Expand Up @@ -1031,6 +1032,23 @@ async def test_text_command(
send.assert_called_once_with(TextCommandRequest(**req))


@pytest.mark.asyncio
@pytest.mark.parametrize(
"cmd, req",
[
(dict(key=1, install=True), dict(key=1, install=True)),
(dict(key=1, install=False), dict(key=1, install=False)),
],
)
async def test_update_command(
auth_client: APIClient, cmd: dict[str, Any], req: dict[str, Any]
) -> None:
send = patch_send(auth_client)

auth_client.update_command(**cmd)
send.assert_called_once_with(UpdateCommandRequest(**req))


@pytest.mark.asyncio
async def test_noise_psk_handles_subclassed_string():
"""Test that the noise_psk gets converted to a string."""
Expand Down Expand Up @@ -2578,3 +2596,6 @@ async def test_calls_after_connection_closed(

with pytest.raises(APIConnectionError):
await client.text_command(1, "1")

with pytest.raises(APIConnectionError):
await client.update_command(1, True)
6 changes: 6 additions & 0 deletions tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
ListEntitiesSwitchResponse,
ListEntitiesTextSensorResponse,
ListEntitiesTimeResponse,
ListEntitiesUpdateResponse,
ListEntitiesValveResponse,
LockStateResponse,
MediaPlayerStateResponse,
Expand All @@ -52,6 +53,7 @@
TextSensorStateResponse,
TextStateResponse,
TimeStateResponse,
UpdateStateResponse,
ValveStateResponse,
)
from aioesphomeapi.model import (
Expand Down Expand Up @@ -112,6 +114,8 @@
TextState,
TimeInfo,
TimeState,
UpdateInfo,
UpdateState,
UserService,
UserServiceArg,
UserServiceArgType,
Expand Down Expand Up @@ -286,6 +290,8 @@ def test_api_version_ord():
(DateTimeState, DateTimeStateResponse),
(EventInfo, ListEntitiesEventResponse),
(Event, EventResponse),
(UpdateInfo, ListEntitiesUpdateResponse),
(UpdateState, UpdateStateResponse),
],
)
def test_basic_pb_conversions(model, pb):
Expand Down

0 comments on commit e41e9c9

Please sign in to comment.