mirror of
https://github.com/esphome/aioesphomeapi.git
synced 2024-11-22 12:05:12 +01:00
Add climate feature fan (#4)
* f1 * renamed to fan_mode * fixes, add back compat with ha * revert client_version - add swing
This commit is contained in:
parent
9be72930e6
commit
511cb62dd9
@ -653,6 +653,25 @@ enum ClimateMode {
|
|||||||
CLIMATE_MODE_AUTO = 1;
|
CLIMATE_MODE_AUTO = 1;
|
||||||
CLIMATE_MODE_COOL = 2;
|
CLIMATE_MODE_COOL = 2;
|
||||||
CLIMATE_MODE_HEAT = 3;
|
CLIMATE_MODE_HEAT = 3;
|
||||||
|
CLIMATE_MODE_FAN_ONLY = 4;
|
||||||
|
CLIMATE_MODE_DRY = 5;
|
||||||
|
}
|
||||||
|
enum ClimateFanMode {
|
||||||
|
CLIMATE_FAN_ON = 0;
|
||||||
|
CLIMATE_FAN_OFF = 1;
|
||||||
|
CLIMATE_FAN_AUTO = 2;
|
||||||
|
CLIMATE_FAN_LOW = 3;
|
||||||
|
CLIMATE_FAN_MEDIUM = 4;
|
||||||
|
CLIMATE_FAN_HIGH = 5;
|
||||||
|
CLIMATE_FAN_MIDDLE = 6;
|
||||||
|
CLIMATE_FAN_FOCUS = 7;
|
||||||
|
CLIMATE_FAN_DIFFUSE = 8;
|
||||||
|
}
|
||||||
|
enum ClimateSwingMode {
|
||||||
|
CLIMATE_SWING_OFF = 0;
|
||||||
|
CLIMATE_SWING_BOTH = 1;
|
||||||
|
CLIMATE_SWING_VERTICAL = 2;
|
||||||
|
CLIMATE_SWINT_HORIZONTAL = 3;
|
||||||
}
|
}
|
||||||
enum ClimateAction {
|
enum ClimateAction {
|
||||||
CLIMATE_ACTION_OFF = 0;
|
CLIMATE_ACTION_OFF = 0;
|
||||||
@ -678,6 +697,8 @@ message ListEntitiesClimateResponse {
|
|||||||
float visual_temperature_step = 10;
|
float visual_temperature_step = 10;
|
||||||
bool supports_away = 11;
|
bool supports_away = 11;
|
||||||
bool supports_action = 12;
|
bool supports_action = 12;
|
||||||
|
repeated ClimateFanMode supported_fan_modes = 13;
|
||||||
|
repeated ClimateSwingMode supported_swing_modes = 14;
|
||||||
}
|
}
|
||||||
message ClimateStateResponse {
|
message ClimateStateResponse {
|
||||||
option (id) = 47;
|
option (id) = 47;
|
||||||
@ -693,6 +714,8 @@ message ClimateStateResponse {
|
|||||||
float target_temperature_high = 6;
|
float target_temperature_high = 6;
|
||||||
bool away = 7;
|
bool away = 7;
|
||||||
ClimateAction action = 8;
|
ClimateAction action = 8;
|
||||||
|
ClimateFanMode fan_mode = 9;
|
||||||
|
ClimateSwingMode swing_mode = 10;
|
||||||
}
|
}
|
||||||
message ClimateCommandRequest {
|
message ClimateCommandRequest {
|
||||||
option (id) = 48;
|
option (id) = 48;
|
||||||
@ -711,4 +734,8 @@ message ClimateCommandRequest {
|
|||||||
float target_temperature_high = 9;
|
float target_temperature_high = 9;
|
||||||
bool has_away = 10;
|
bool has_away = 10;
|
||||||
bool away = 11;
|
bool away = 11;
|
||||||
|
bool has_fan_mode = 12;
|
||||||
|
ClimateFanMode fan_mode = 13;
|
||||||
|
bool has_swing_mode = 14;
|
||||||
|
ClimateSwingMode swing_mode = 15;
|
||||||
}
|
}
|
||||||
|
@ -1,54 +1,51 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||||
# source: api_options.proto
|
# source: api_options.proto
|
||||||
|
|
||||||
import sys
|
from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2
|
||||||
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
|
|
||||||
from google.protobuf.internal import enum_type_wrapper
|
|
||||||
from google.protobuf import descriptor as _descriptor
|
|
||||||
from google.protobuf import message as _message
|
|
||||||
from google.protobuf import reflection as _reflection
|
|
||||||
from google.protobuf import symbol_database as _symbol_database
|
from google.protobuf import symbol_database as _symbol_database
|
||||||
|
from google.protobuf import reflection as _reflection
|
||||||
|
from google.protobuf import message as _message
|
||||||
|
from google.protobuf import descriptor as _descriptor
|
||||||
|
from google.protobuf.internal import enum_type_wrapper
|
||||||
|
import sys
|
||||||
|
_b = sys.version_info[0] < 3 and (
|
||||||
|
lambda x: x) or (lambda x: x.encode('latin1'))
|
||||||
# @@protoc_insertion_point(imports)
|
# @@protoc_insertion_point(imports)
|
||||||
|
|
||||||
_sym_db = _symbol_database.Default()
|
_sym_db = _symbol_database.Default()
|
||||||
|
|
||||||
|
|
||||||
from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor__pb2
|
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTOR = _descriptor.FileDescriptor(
|
DESCRIPTOR = _descriptor.FileDescriptor(
|
||||||
name='api_options.proto',
|
name='api_options.proto',
|
||||||
package='',
|
package='',
|
||||||
syntax='proto2',
|
syntax='proto2',
|
||||||
serialized_options=None,
|
serialized_options=None,
|
||||||
serialized_pb=_b('\n\x11\x61pi_options.proto\x1a google/protobuf/descriptor.proto\"\x06\n\x04void*F\n\rAPISourceType\x12\x0f\n\x0bSOURCE_BOTH\x10\x00\x12\x11\n\rSOURCE_SERVER\x10\x01\x12\x11\n\rSOURCE_CLIENT\x10\x02:E\n\x16needs_setup_connection\x12\x1e.google.protobuf.MethodOptions\x18\x8e\x08 \x01(\x08:\x04true:C\n\x14needs_authentication\x12\x1e.google.protobuf.MethodOptions\x18\x8f\x08 \x01(\x08:\x04true:/\n\x02id\x12\x1f.google.protobuf.MessageOptions\x18\x8c\x08 \x01(\r:\x01\x30:M\n\x06source\x12\x1f.google.protobuf.MessageOptions\x18\x8d\x08 \x01(\x0e\x32\x0e.APISourceType:\x0bSOURCE_BOTH:/\n\x05ifdef\x12\x1f.google.protobuf.MessageOptions\x18\x8e\x08 \x01(\t:3\n\x03log\x12\x1f.google.protobuf.MessageOptions\x18\x8f\x08 \x01(\x08:\x04true:9\n\x08no_delay\x12\x1f.google.protobuf.MessageOptions\x18\x90\x08 \x01(\x08:\x05\x66\x61lse')
|
serialized_pb=_b('\n\x11\x61pi_options.proto\x1a google/protobuf/descriptor.proto\"\x06\n\x04void*F\n\rAPISourceType\x12\x0f\n\x0bSOURCE_BOTH\x10\x00\x12\x11\n\rSOURCE_SERVER\x10\x01\x12\x11\n\rSOURCE_CLIENT\x10\x02:E\n\x16needs_setup_connection\x12\x1e.google.protobuf.MethodOptions\x18\x8e\x08 \x01(\x08:\x04true:C\n\x14needs_authentication\x12\x1e.google.protobuf.MethodOptions\x18\x8f\x08 \x01(\x08:\x04true:/\n\x02id\x12\x1f.google.protobuf.MessageOptions\x18\x8c\x08 \x01(\r:\x01\x30:M\n\x06source\x12\x1f.google.protobuf.MessageOptions\x18\x8d\x08 \x01(\x0e\x32\x0e.APISourceType:\x0bSOURCE_BOTH:/\n\x05ifdef\x12\x1f.google.protobuf.MessageOptions\x18\x8e\x08 \x01(\t:3\n\x03log\x12\x1f.google.protobuf.MessageOptions\x18\x8f\x08 \x01(\x08:\x04true:9\n\x08no_delay\x12\x1f.google.protobuf.MessageOptions\x18\x90\x08 \x01(\x08:\x05\x66\x61lse'),
|
||||||
,
|
dependencies=[google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR, ])
|
||||||
dependencies=[google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,])
|
|
||||||
|
|
||||||
_APISOURCETYPE = _descriptor.EnumDescriptor(
|
_APISOURCETYPE = _descriptor.EnumDescriptor(
|
||||||
name='APISourceType',
|
name='APISourceType',
|
||||||
full_name='APISourceType',
|
full_name='APISourceType',
|
||||||
filename=None,
|
filename=None,
|
||||||
file=DESCRIPTOR,
|
file=DESCRIPTOR,
|
||||||
values=[
|
values=[
|
||||||
_descriptor.EnumValueDescriptor(
|
_descriptor.EnumValueDescriptor(
|
||||||
name='SOURCE_BOTH', index=0, number=0,
|
name='SOURCE_BOTH', index=0, number=0,
|
||||||
serialized_options=None,
|
serialized_options=None,
|
||||||
type=None),
|
type=None),
|
||||||
_descriptor.EnumValueDescriptor(
|
_descriptor.EnumValueDescriptor(
|
||||||
name='SOURCE_SERVER', index=1, number=1,
|
name='SOURCE_SERVER', index=1, number=1,
|
||||||
serialized_options=None,
|
serialized_options=None,
|
||||||
type=None),
|
type=None),
|
||||||
_descriptor.EnumValueDescriptor(
|
_descriptor.EnumValueDescriptor(
|
||||||
name='SOURCE_CLIENT', index=2, number=2,
|
name='SOURCE_CLIENT', index=2, number=2,
|
||||||
serialized_options=None,
|
serialized_options=None,
|
||||||
type=None),
|
type=None),
|
||||||
],
|
],
|
||||||
containing_type=None,
|
containing_type=None,
|
||||||
serialized_options=None,
|
serialized_options=None,
|
||||||
serialized_start=63,
|
serialized_start=63,
|
||||||
serialized_end=133,
|
serialized_end=133,
|
||||||
)
|
)
|
||||||
_sym_db.RegisterEnumDescriptor(_APISOURCETYPE)
|
_sym_db.RegisterEnumDescriptor(_APISOURCETYPE)
|
||||||
|
|
||||||
@ -59,83 +56,83 @@ SOURCE_CLIENT = 2
|
|||||||
|
|
||||||
NEEDS_SETUP_CONNECTION_FIELD_NUMBER = 1038
|
NEEDS_SETUP_CONNECTION_FIELD_NUMBER = 1038
|
||||||
needs_setup_connection = _descriptor.FieldDescriptor(
|
needs_setup_connection = _descriptor.FieldDescriptor(
|
||||||
name='needs_setup_connection', full_name='needs_setup_connection', index=0,
|
name='needs_setup_connection', full_name='needs_setup_connection', index=0,
|
||||||
number=1038, type=8, cpp_type=7, label=1,
|
number=1038, type=8, cpp_type=7, label=1,
|
||||||
has_default_value=True, default_value=True,
|
has_default_value=True, default_value=True,
|
||||||
message_type=None, enum_type=None, containing_type=None,
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
is_extension=True, extension_scope=None,
|
is_extension=True, extension_scope=None,
|
||||||
serialized_options=None, file=DESCRIPTOR)
|
serialized_options=None, file=DESCRIPTOR)
|
||||||
NEEDS_AUTHENTICATION_FIELD_NUMBER = 1039
|
NEEDS_AUTHENTICATION_FIELD_NUMBER = 1039
|
||||||
needs_authentication = _descriptor.FieldDescriptor(
|
needs_authentication = _descriptor.FieldDescriptor(
|
||||||
name='needs_authentication', full_name='needs_authentication', index=1,
|
name='needs_authentication', full_name='needs_authentication', index=1,
|
||||||
number=1039, type=8, cpp_type=7, label=1,
|
number=1039, type=8, cpp_type=7, label=1,
|
||||||
has_default_value=True, default_value=True,
|
has_default_value=True, default_value=True,
|
||||||
message_type=None, enum_type=None, containing_type=None,
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
is_extension=True, extension_scope=None,
|
is_extension=True, extension_scope=None,
|
||||||
serialized_options=None, file=DESCRIPTOR)
|
serialized_options=None, file=DESCRIPTOR)
|
||||||
ID_FIELD_NUMBER = 1036
|
ID_FIELD_NUMBER = 1036
|
||||||
id = _descriptor.FieldDescriptor(
|
id = _descriptor.FieldDescriptor(
|
||||||
name='id', full_name='id', index=2,
|
name='id', full_name='id', index=2,
|
||||||
number=1036, type=13, cpp_type=3, label=1,
|
number=1036, type=13, cpp_type=3, label=1,
|
||||||
has_default_value=True, default_value=0,
|
has_default_value=True, default_value=0,
|
||||||
message_type=None, enum_type=None, containing_type=None,
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
is_extension=True, extension_scope=None,
|
is_extension=True, extension_scope=None,
|
||||||
serialized_options=None, file=DESCRIPTOR)
|
serialized_options=None, file=DESCRIPTOR)
|
||||||
SOURCE_FIELD_NUMBER = 1037
|
SOURCE_FIELD_NUMBER = 1037
|
||||||
source = _descriptor.FieldDescriptor(
|
source = _descriptor.FieldDescriptor(
|
||||||
name='source', full_name='source', index=3,
|
name='source', full_name='source', index=3,
|
||||||
number=1037, type=14, cpp_type=8, label=1,
|
number=1037, type=14, cpp_type=8, label=1,
|
||||||
has_default_value=True, default_value=0,
|
has_default_value=True, default_value=0,
|
||||||
message_type=None, enum_type=None, containing_type=None,
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
is_extension=True, extension_scope=None,
|
is_extension=True, extension_scope=None,
|
||||||
serialized_options=None, file=DESCRIPTOR)
|
serialized_options=None, file=DESCRIPTOR)
|
||||||
IFDEF_FIELD_NUMBER = 1038
|
IFDEF_FIELD_NUMBER = 1038
|
||||||
ifdef = _descriptor.FieldDescriptor(
|
ifdef = _descriptor.FieldDescriptor(
|
||||||
name='ifdef', full_name='ifdef', index=4,
|
name='ifdef', full_name='ifdef', index=4,
|
||||||
number=1038, type=9, cpp_type=9, label=1,
|
number=1038, type=9, cpp_type=9, label=1,
|
||||||
has_default_value=False, default_value=_b("").decode('utf-8'),
|
has_default_value=False, default_value=_b("").decode('utf-8'),
|
||||||
message_type=None, enum_type=None, containing_type=None,
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
is_extension=True, extension_scope=None,
|
is_extension=True, extension_scope=None,
|
||||||
serialized_options=None, file=DESCRIPTOR)
|
serialized_options=None, file=DESCRIPTOR)
|
||||||
LOG_FIELD_NUMBER = 1039
|
LOG_FIELD_NUMBER = 1039
|
||||||
log = _descriptor.FieldDescriptor(
|
log = _descriptor.FieldDescriptor(
|
||||||
name='log', full_name='log', index=5,
|
name='log', full_name='log', index=5,
|
||||||
number=1039, type=8, cpp_type=7, label=1,
|
number=1039, type=8, cpp_type=7, label=1,
|
||||||
has_default_value=True, default_value=True,
|
has_default_value=True, default_value=True,
|
||||||
message_type=None, enum_type=None, containing_type=None,
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
is_extension=True, extension_scope=None,
|
is_extension=True, extension_scope=None,
|
||||||
serialized_options=None, file=DESCRIPTOR)
|
serialized_options=None, file=DESCRIPTOR)
|
||||||
NO_DELAY_FIELD_NUMBER = 1040
|
NO_DELAY_FIELD_NUMBER = 1040
|
||||||
no_delay = _descriptor.FieldDescriptor(
|
no_delay = _descriptor.FieldDescriptor(
|
||||||
name='no_delay', full_name='no_delay', index=6,
|
name='no_delay', full_name='no_delay', index=6,
|
||||||
number=1040, type=8, cpp_type=7, label=1,
|
number=1040, type=8, cpp_type=7, label=1,
|
||||||
has_default_value=True, default_value=False,
|
has_default_value=True, default_value=False,
|
||||||
message_type=None, enum_type=None, containing_type=None,
|
message_type=None, enum_type=None, containing_type=None,
|
||||||
is_extension=True, extension_scope=None,
|
is_extension=True, extension_scope=None,
|
||||||
serialized_options=None, file=DESCRIPTOR)
|
serialized_options=None, file=DESCRIPTOR)
|
||||||
|
|
||||||
|
|
||||||
_VOID = _descriptor.Descriptor(
|
_VOID = _descriptor.Descriptor(
|
||||||
name='void',
|
name='void',
|
||||||
full_name='void',
|
full_name='void',
|
||||||
filename=None,
|
filename=None,
|
||||||
file=DESCRIPTOR,
|
file=DESCRIPTOR,
|
||||||
containing_type=None,
|
containing_type=None,
|
||||||
fields=[
|
fields=[
|
||||||
],
|
],
|
||||||
extensions=[
|
extensions=[
|
||||||
],
|
],
|
||||||
nested_types=[],
|
nested_types=[],
|
||||||
enum_types=[
|
enum_types=[
|
||||||
],
|
],
|
||||||
serialized_options=None,
|
serialized_options=None,
|
||||||
is_extendable=False,
|
is_extendable=False,
|
||||||
syntax='proto2',
|
syntax='proto2',
|
||||||
extension_ranges=[],
|
extension_ranges=[],
|
||||||
oneofs=[
|
oneofs=[
|
||||||
],
|
],
|
||||||
serialized_start=55,
|
serialized_start=55,
|
||||||
serialized_end=61,
|
serialized_end=61,
|
||||||
)
|
)
|
||||||
|
|
||||||
DESCRIPTOR.message_types_by_name['void'] = _VOID
|
DESCRIPTOR.message_types_by_name['void'] = _VOID
|
||||||
@ -149,20 +146,24 @@ DESCRIPTOR.extensions_by_name['log'] = log
|
|||||||
DESCRIPTOR.extensions_by_name['no_delay'] = no_delay
|
DESCRIPTOR.extensions_by_name['no_delay'] = no_delay
|
||||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||||
|
|
||||||
void = _reflection.GeneratedProtocolMessageType('void', (_message.Message,), {
|
void = _reflection.GeneratedProtocolMessageType('void', (_message.Message,), dict(
|
||||||
'DESCRIPTOR' : _VOID,
|
DESCRIPTOR=_VOID,
|
||||||
'__module__' : 'api_options_pb2'
|
__module__='api_options_pb2'
|
||||||
# @@protoc_insertion_point(class_scope:void)
|
# @@protoc_insertion_point(class_scope:void)
|
||||||
})
|
))
|
||||||
_sym_db.RegisterMessage(void)
|
_sym_db.RegisterMessage(void)
|
||||||
|
|
||||||
google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension(needs_setup_connection)
|
google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension(
|
||||||
google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension(needs_authentication)
|
needs_setup_connection)
|
||||||
|
google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension(
|
||||||
|
needs_authentication)
|
||||||
google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(id)
|
google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(id)
|
||||||
source.enum_type = _APISOURCETYPE
|
source.enum_type = _APISOURCETYPE
|
||||||
google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(source)
|
google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(
|
||||||
|
source)
|
||||||
google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(ifdef)
|
google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(ifdef)
|
||||||
google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(log)
|
google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(log)
|
||||||
google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(no_delay)
|
google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(
|
||||||
|
no_delay)
|
||||||
|
|
||||||
# @@protoc_insertion_point(module_scope)
|
# @@protoc_insertion_point(module_scope)
|
||||||
|
File diff suppressed because one or more lines are too long
@ -50,7 +50,8 @@ class APIClient:
|
|||||||
raise
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await _on_stop()
|
await _on_stop()
|
||||||
raise APIConnectionError("Unexpected error while connecting: {}".format(e))
|
raise APIConnectionError(
|
||||||
|
"Unexpected error while connecting: {}".format(e))
|
||||||
|
|
||||||
connected = True
|
connected = True
|
||||||
|
|
||||||
@ -326,6 +327,8 @@ class APIClient:
|
|||||||
target_temperature_low: Optional[float] = None,
|
target_temperature_low: Optional[float] = None,
|
||||||
target_temperature_high: Optional[float] = None,
|
target_temperature_high: Optional[float] = None,
|
||||||
away: Optional[bool] = None,
|
away: Optional[bool] = None,
|
||||||
|
fan_mode: Optional[ClimateFanMode] = None,
|
||||||
|
swing_mode: Optional[ClimateSwingMode] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self._check_authenticated()
|
self._check_authenticated()
|
||||||
|
|
||||||
@ -346,6 +349,12 @@ class APIClient:
|
|||||||
if away is not None:
|
if away is not None:
|
||||||
req.has_away = True
|
req.has_away = True
|
||||||
req.away = away
|
req.away = away
|
||||||
|
if fan_mode is not None:
|
||||||
|
req.has_fan_mode = True
|
||||||
|
req.fan_mode = fan_mode
|
||||||
|
if swing_mode is not None:
|
||||||
|
req.has_swing_mode = True
|
||||||
|
req.swing_mode = swing_mode
|
||||||
await self._connection.send_message(req)
|
await self._connection.send_message(req)
|
||||||
|
|
||||||
async def execute_service(self, service: UserService, data: dict):
|
async def execute_service(self, service: UserService, data: dict):
|
||||||
@ -357,7 +366,8 @@ class APIClient:
|
|||||||
for arg_desc in service.args:
|
for arg_desc in service.args:
|
||||||
arg = pb.ExecuteServiceArgument()
|
arg = pb.ExecuteServiceArgument()
|
||||||
val = data[arg_desc.name]
|
val = data[arg_desc.name]
|
||||||
int_type = 'int_' if self.api_version >= APIVersion(1, 3) else 'legacy_int'
|
int_type = 'int_' if self.api_version >= APIVersion(
|
||||||
|
1, 3) else 'legacy_int'
|
||||||
map_single = {
|
map_single = {
|
||||||
UserServiceArgType.BOOL: 'bool_',
|
UserServiceArgType.BOOL: 'bool_',
|
||||||
UserServiceArgType.INT: int_type,
|
UserServiceArgType.INT: int_type,
|
||||||
|
@ -120,10 +120,12 @@ class APIConnection:
|
|||||||
await asyncio.wait_for(coro, 30.0)
|
await asyncio.wait_for(coro, 30.0)
|
||||||
except OSError as err:
|
except OSError as err:
|
||||||
await self._on_error()
|
await self._on_error()
|
||||||
raise APIConnectionError("Error connecting to {}: {}".format(sockaddr, err))
|
raise APIConnectionError(
|
||||||
|
"Error connecting to {}: {}".format(sockaddr, err))
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
await self._on_error()
|
await self._on_error()
|
||||||
raise APIConnectionError("Timeout while connecting to {}".format(sockaddr))
|
raise APIConnectionError(
|
||||||
|
"Timeout while connecting to {}".format(sockaddr))
|
||||||
|
|
||||||
_LOGGER.debug("%s: Opened socket for", self._params.address)
|
_LOGGER.debug("%s: Opened socket for", self._params.address)
|
||||||
self._socket_reader, self._socket_writer = await asyncio.open_connection(sock=self._socket)
|
self._socket_reader, self._socket_writer = await asyncio.open_connection(sock=self._socket)
|
||||||
@ -140,7 +142,8 @@ class APIConnection:
|
|||||||
_LOGGER.debug("%s: Successfully connected ('%s' API=%s.%s)",
|
_LOGGER.debug("%s: Successfully connected ('%s' API=%s.%s)",
|
||||||
self._params.address, resp.server_info, resp.api_version_major,
|
self._params.address, resp.server_info, resp.api_version_major,
|
||||||
resp.api_version_minor)
|
resp.api_version_minor)
|
||||||
self._api_version = APIVersion(resp.api_version_major, resp.api_version_minor)
|
self._api_version = APIVersion(
|
||||||
|
resp.api_version_major, resp.api_version_minor)
|
||||||
if self._api_version.major > 2:
|
if self._api_version.major > 2:
|
||||||
_LOGGER.error("%s: Incompatible version %s! Closing connection",
|
_LOGGER.error("%s: Incompatible version %s! Closing connection",
|
||||||
self._api_version.major)
|
self._api_version.major)
|
||||||
@ -187,7 +190,8 @@ class APIConnection:
|
|||||||
await self._socket_writer.drain()
|
await self._socket_writer.drain()
|
||||||
except OSError as err:
|
except OSError as err:
|
||||||
await self._on_error()
|
await self._on_error()
|
||||||
raise APIConnectionError("Error while writing data: {}".format(err))
|
raise APIConnectionError(
|
||||||
|
"Error while writing data: {}".format(err))
|
||||||
|
|
||||||
async def send_message(self, msg: message.Message) -> None:
|
async def send_message(self, msg: message.Message) -> None:
|
||||||
for message_type, klass in MESSAGE_TYPE_TO_PROTO.items():
|
for message_type, klass in MESSAGE_TYPE_TO_PROTO.items():
|
||||||
@ -197,7 +201,8 @@ class APIConnection:
|
|||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
encoded = msg.SerializeToString()
|
encoded = msg.SerializeToString()
|
||||||
_LOGGER.debug("%s: Sending %s: %s", self._params.address, type(msg), str(msg))
|
_LOGGER.debug("%s: Sending %s: %s",
|
||||||
|
self._params.address, type(msg), str(msg))
|
||||||
req = bytes([0])
|
req = bytes([0])
|
||||||
req += _varuint_to_bytes(len(encoded))
|
req += _varuint_to_bytes(len(encoded))
|
||||||
req += _varuint_to_bytes(message_type)
|
req += _varuint_to_bytes(message_type)
|
||||||
@ -231,7 +236,8 @@ class APIConnection:
|
|||||||
await asyncio.wait_for(fut, timeout)
|
await asyncio.wait_for(fut, timeout)
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
if self._stopped:
|
if self._stopped:
|
||||||
raise APIConnectionError("Disconnected while waiting for API response!")
|
raise APIConnectionError(
|
||||||
|
"Disconnected while waiting for API response!")
|
||||||
raise APIConnectionError("Timeout while waiting for API response!")
|
raise APIConnectionError("Timeout while waiting for API response!")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -250,7 +256,8 @@ class APIConnection:
|
|||||||
res = await self.send_message_await_response_complex(
|
res = await self.send_message_await_response_complex(
|
||||||
send_msg, is_response, is_response, timeout=timeout)
|
send_msg, is_response, is_response, timeout=timeout)
|
||||||
if len(res) != 1:
|
if len(res) != 1:
|
||||||
raise APIConnectionError("Expected one result, got {}".format(len(res)))
|
raise APIConnectionError(
|
||||||
|
"Expected one result, got {}".format(len(res)))
|
||||||
|
|
||||||
return res[0]
|
return res[0]
|
||||||
|
|
||||||
@ -261,7 +268,8 @@ class APIConnection:
|
|||||||
try:
|
try:
|
||||||
ret = await self._socket_reader.readexactly(amount)
|
ret = await self._socket_reader.readexactly(amount)
|
||||||
except (asyncio.IncompleteReadError, OSError, TimeoutError) as err:
|
except (asyncio.IncompleteReadError, OSError, TimeoutError) as err:
|
||||||
raise APIConnectionError("Error while receiving data: {}".format(err))
|
raise APIConnectionError(
|
||||||
|
"Error while receiving data: {}".format(err))
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@ -281,7 +289,8 @@ class APIConnection:
|
|||||||
|
|
||||||
raw_msg = await self._recv(length)
|
raw_msg = await self._recv(length)
|
||||||
if msg_type not in MESSAGE_TYPE_TO_PROTO:
|
if msg_type not in MESSAGE_TYPE_TO_PROTO:
|
||||||
_LOGGER.debug("%s: Skipping message type %s", self._params.address, msg_type)
|
_LOGGER.debug("%s: Skipping message type %s",
|
||||||
|
self._params.address, msg_type)
|
||||||
return
|
return
|
||||||
|
|
||||||
msg = MESSAGE_TYPE_TO_PROTO[msg_type]()
|
msg = MESSAGE_TYPE_TO_PROTO[msg_type]()
|
||||||
@ -289,7 +298,8 @@ class APIConnection:
|
|||||||
msg.ParseFromString(raw_msg)
|
msg.ParseFromString(raw_msg)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise APIConnectionError("Invalid protobuf message: {}".format(e))
|
raise APIConnectionError("Invalid protobuf message: {}".format(e))
|
||||||
_LOGGER.debug("%s: Got message of type %s: %s", self._params.address, type(msg), msg)
|
_LOGGER.debug("%s: Got message of type %s: %s",
|
||||||
|
self._params.address, type(msg), msg)
|
||||||
for msg_handler in self._message_handlers[:]:
|
for msg_handler in self._message_handlers[:]:
|
||||||
msg_handler(msg)
|
msg_handler(msg)
|
||||||
await self._handle_internal_messages(msg)
|
await self._handle_internal_messages(msg)
|
||||||
|
@ -194,6 +194,27 @@ class ClimateMode(enum.IntEnum):
|
|||||||
AUTO = 1
|
AUTO = 1
|
||||||
COOL = 2
|
COOL = 2
|
||||||
HEAT = 3
|
HEAT = 3
|
||||||
|
FAN_ONLY = 4
|
||||||
|
DRY = 5
|
||||||
|
|
||||||
|
|
||||||
|
class ClimateFanMode(enum.IntEnum):
|
||||||
|
ON = 0
|
||||||
|
OFF = 1
|
||||||
|
AUTO = 2
|
||||||
|
LOW = 3
|
||||||
|
MEDIUM = 4
|
||||||
|
HIGH = 5
|
||||||
|
MIDDLE = 6
|
||||||
|
FOCUS = 7
|
||||||
|
DIFFUSE = 8
|
||||||
|
|
||||||
|
|
||||||
|
class ClimateSwingMode(enum.IntEnum):
|
||||||
|
OFF = 0
|
||||||
|
BOTH = 1
|
||||||
|
VERTICAL = 2
|
||||||
|
HORIZONTAL = 3
|
||||||
|
|
||||||
|
|
||||||
class ClimateAction(enum.IntEnum):
|
class ClimateAction(enum.IntEnum):
|
||||||
@ -206,6 +227,14 @@ def _convert_climate_modes(value):
|
|||||||
return [ClimateMode(val) for val in value]
|
return [ClimateMode(val) for val in value]
|
||||||
|
|
||||||
|
|
||||||
|
def _convert_climate_fan_modes(value):
|
||||||
|
return [ClimateFanMode(val) for val in value]
|
||||||
|
|
||||||
|
|
||||||
|
def _convert_climate_swing_modes(value):
|
||||||
|
return [ClimateSwingMode(val) for val in value]
|
||||||
|
|
||||||
|
|
||||||
@attr.s
|
@attr.s
|
||||||
class ClimateInfo(EntityInfo):
|
class ClimateInfo(EntityInfo):
|
||||||
supports_current_temperature = attr.ib(type=bool, default=False)
|
supports_current_temperature = attr.ib(type=bool, default=False)
|
||||||
@ -217,17 +246,31 @@ class ClimateInfo(EntityInfo):
|
|||||||
visual_temperature_step = attr.ib(type=float, default=0.0)
|
visual_temperature_step = attr.ib(type=float, default=0.0)
|
||||||
supports_away = attr.ib(type=bool, default=False)
|
supports_away = attr.ib(type=bool, default=False)
|
||||||
supports_action = attr.ib(type=bool, default=False)
|
supports_action = attr.ib(type=bool, default=False)
|
||||||
|
supported_fan_modes = attr.ib(
|
||||||
|
type=List[ClimateFanMode], converter=_convert_climate_fan_modes, factory=list
|
||||||
|
)
|
||||||
|
supported_swing_modes = attr.ib(
|
||||||
|
type=List[ClimateSwingMode], converter=_convert_climate_swing_modes, factory=list
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@attr.s
|
@attr.s
|
||||||
class ClimateState(EntityState):
|
class ClimateState(EntityState):
|
||||||
mode = attr.ib(type=ClimateMode, converter=ClimateMode, default=ClimateMode.OFF)
|
mode = attr.ib(type=ClimateMode, converter=ClimateMode,
|
||||||
action = attr.ib(type=ClimateAction, converter=ClimateAction, default=ClimateAction.OFF)
|
default=ClimateMode.OFF)
|
||||||
|
action = attr.ib(type=ClimateAction, converter=ClimateAction,
|
||||||
|
default=ClimateAction.OFF)
|
||||||
current_temperature = attr.ib(type=float, default=0.0)
|
current_temperature = attr.ib(type=float, default=0.0)
|
||||||
target_temperature = attr.ib(type=float, default=0.0)
|
target_temperature = attr.ib(type=float, default=0.0)
|
||||||
target_temperature_low = attr.ib(type=float, default=0.0)
|
target_temperature_low = attr.ib(type=float, default=0.0)
|
||||||
target_temperature_high = attr.ib(type=float, default=0.0)
|
target_temperature_high = attr.ib(type=float, default=0.0)
|
||||||
away = attr.ib(type=bool, default=False)
|
away = attr.ib(type=bool, default=False)
|
||||||
|
fan_mode = attr.ib(
|
||||||
|
type=ClimateFanMode, converter=ClimateFanMode, default=ClimateFanMode.AUTO
|
||||||
|
)
|
||||||
|
swing_mode = attr.ib(
|
||||||
|
type=ClimateSwingMode, converter=ClimateSwingMode, default=ClimateSwingMode.OFF
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
COMPONENT_TYPE_TO_INFO = {
|
COMPONENT_TYPE_TO_INFO = {
|
||||||
|
@ -4,4 +4,4 @@
|
|||||||
protoc --python_out=aioesphomeapi -I aioesphomeapi aioesphomeapi/*.proto
|
protoc --python_out=aioesphomeapi -I aioesphomeapi aioesphomeapi/*.proto
|
||||||
|
|
||||||
# https://github.com/protocolbuffers/protobuf/issues/1491
|
# https://github.com/protocolbuffers/protobuf/issues/1491
|
||||||
sed -i '' 's/import api_options_pb2 as api__options__pb2/from . import api_options_pb2 as api__options__pb2/' aioesphomeapi/api_pb2.py
|
sed -i 's/import api_options_pb2 as api__options__pb2/from . import api_options_pb2 as api__options__pb2/' aioesphomeapi/api_pb2.py
|
||||||
|
Loading…
Reference in New Issue
Block a user