Add select entities (#75)

This commit is contained in:
Jesse Hills 2021-07-27 06:51:12 +12:00 committed by GitHub
parent 4fe818b95c
commit 551a1acd0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 311 additions and 31 deletions

View File

@ -39,6 +39,7 @@ service APIConnection {
rpc camera_image (CameraImageRequest) returns (void) {}
rpc climate_command (ClimateCommandRequest) returns (void) {}
rpc number_command (NumberCommandRequest) returns (void) {}
rpc select_command (SelectCommandRequest) returns (void) {}
}
@ -841,3 +842,39 @@ message NumberCommandRequest {
fixed32 key = 1;
float state = 2;
}
// ==================== SELECT ====================
message ListEntitiesSelectResponse {
option (id) = 52;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_SELECT";
string object_id = 1;
fixed32 key = 2;
string name = 3;
string unique_id = 4;
string icon = 5;
repeated string options = 6;
}
message SelectStateResponse {
option (id) = 53;
option (source) = SOURCE_SERVER;
option (ifdef) = "USE_SELECT";
option (no_delay) = true;
fixed32 key = 1;
string state = 2;
// If the select does not have a valid state yet.
// Equivalent to `!obj->has_state()` - inverse logic to make state packets smaller
bool missing_state = 3;
}
message SelectCommandRequest {
option (id) = 54;
option (source) = SOURCE_CLIENT;
option (ifdef) = "USE_SELECT";
option (no_delay) = true;
fixed32 key = 1;
string state = 2;
}

File diff suppressed because one or more lines are too long

View File

@ -42,12 +42,15 @@ from .api_pb2 import ( # type: ignore
ListEntitiesLightResponse,
ListEntitiesNumberResponse,
ListEntitiesRequest,
ListEntitiesSelectResponse,
ListEntitiesSensorResponse,
ListEntitiesServicesResponse,
ListEntitiesSwitchResponse,
ListEntitiesTextSensorResponse,
NumberCommandRequest,
NumberStateResponse,
SelectCommandRequest,
SelectStateResponse,
SensorStateResponse,
SubscribeHomeassistantServicesRequest,
SubscribeHomeAssistantStateResponse,
@ -90,6 +93,8 @@ from .model import (
LogLevel,
NumberInfo,
NumberState,
SelectInfo,
SelectState,
SensorInfo,
SensorState,
SwitchInfo,
@ -219,6 +224,7 @@ class APIClient:
ListEntitiesFanResponse: FanInfo,
ListEntitiesLightResponse: LightInfo,
ListEntitiesNumberResponse: NumberInfo,
ListEntitiesSelectResponse: SelectInfo,
ListEntitiesSensorResponse: SensorInfo,
ListEntitiesSwitchResponse: SwitchInfo,
ListEntitiesTextSensorResponse: TextSensorInfo,
@ -262,6 +268,7 @@ class APIClient:
FanStateResponse: FanState,
LightStateResponse: LightState,
NumberStateResponse: NumberState,
SelectStateResponse: SelectState,
SensorStateResponse: SensorState,
SwitchStateResponse: SwitchState,
TextSensorStateResponse: TextSensorState,
@ -533,6 +540,15 @@ class APIClient:
assert self._connection is not None
await self._connection.send_message(req)
async def select_command(self, key: int, state: str) -> None:
self._check_authenticated()
req = SelectCommandRequest()
req.key = key
req.state = state
assert self._connection is not None
await self._connection.send_message(req)
async def execute_service(
self, service: UserService, data: ExecuteServiceDataType
) -> None:

View File

@ -32,6 +32,7 @@ from .api_pb2 import ( # type: ignore
ListEntitiesLightResponse,
ListEntitiesNumberResponse,
ListEntitiesRequest,
ListEntitiesSelectResponse,
ListEntitiesSensorResponse,
ListEntitiesServicesResponse,
ListEntitiesSwitchResponse,
@ -40,6 +41,8 @@ from .api_pb2 import ( # type: ignore
NumberStateResponse,
PingRequest,
PingResponse,
SelectCommandRequest,
SelectStateResponse,
SensorStateResponse,
SubscribeHomeassistantServicesRequest,
SubscribeHomeAssistantStateResponse,
@ -109,4 +112,7 @@ MESSAGE_TYPE_TO_PROTO = {
49: ListEntitiesNumberResponse,
50: NumberStateResponse,
51: NumberCommandRequest,
52: ListEntitiesSelectResponse,
53: SelectStateResponse,
54: SelectCommandRequest,
}

View File

@ -432,6 +432,19 @@ class NumberState(EntityState):
missing_state: bool = False
# ==================== SELECT ====================
@dataclass(frozen=True)
class SelectInfo(EntityInfo):
icon: str = ""
options: List[str] = converter_field(default_factory=list, converter=list)
@dataclass(frozen=True)
class SelectState(EntityState):
state: str = ""
missing_state: bool = False
COMPONENT_TYPE_TO_INFO: Dict[str, Type[EntityInfo]] = {
"binary_sensor": BinarySensorInfo,
"cover": CoverInfo,
@ -443,6 +456,7 @@ COMPONENT_TYPE_TO_INFO: Dict[str, Type[EntityInfo]] = {
"camera": CameraInfo,
"climate": ClimateInfo,
"number": NumberInfo,
"select": SelectInfo,
}

View File

@ -17,6 +17,7 @@ from aioesphomeapi.api_pb2 import (
ListEntitiesDoneResponse,
ListEntitiesServicesResponse,
NumberCommandRequest,
SelectCommandRequest,
SwitchCommandRequest,
)
from aioesphomeapi.client import APIClient
@ -356,6 +357,21 @@ async def test_number_command(auth_client, cmd, req):
send.assert_called_once_with(NumberCommandRequest(**req))
@pytest.mark.asyncio
@pytest.mark.parametrize(
"cmd, req",
[
(dict(key=1, state="One"), dict(key=1, state="One")),
(dict(key=1, state="Two"), dict(key=1, state="Two")),
],
)
async def test_select_command(auth_client, cmd, req):
send = patch_send(auth_client)
await auth_client.select_command(**cmd)
send.assert_called_once_with(SelectCommandRequest(**req))
@pytest.mark.asyncio
async def test_execute_service(auth_client):
send = patch_send(auth_client)

View File

@ -18,12 +18,14 @@ from aioesphomeapi.api_pb2 import (
ListEntitiesFanResponse,
ListEntitiesLightResponse,
ListEntitiesNumberResponse,
ListEntitiesSelectResponse,
ListEntitiesSensorResponse,
ListEntitiesServicesArgument,
ListEntitiesServicesResponse,
ListEntitiesSwitchResponse,
ListEntitiesTextSensorResponse,
NumberStateResponse,
SelectStateResponse,
SensorStateResponse,
ServiceArgType,
SwitchStateResponse,
@ -49,6 +51,8 @@ from aioesphomeapi.model import (
LightState,
NumberInfo,
NumberState,
SelectInfo,
SelectState,
SensorInfo,
SensorState,
SwitchInfo,
@ -208,6 +212,8 @@ def test_api_version_ord():
(ClimateState, ClimateStateResponse),
(NumberInfo, ListEntitiesNumberResponse),
(NumberState, NumberStateResponse),
(SelectInfo, ListEntitiesSelectResponse),
(SelectState, SelectStateResponse),
(HomeassistantServiceCall, HomeassistantServiceResponse),
(UserServiceArg, ListEntitiesServicesArgument),
(UserService, ListEntitiesServicesResponse),