mirror of
https://github.com/esphome/aioesphomeapi.git
synced 2024-11-26 12:45:26 +01:00
Climate preset, custom fan mode and custom preset (#42)
Co-authored-by: Otto Winter <otto@otto-winter.com> Co-authored-by: Lumpusz <marton.keri@gmail.com>
This commit is contained in:
parent
313aa2d56f
commit
b1b36754ec
@ -672,11 +672,12 @@ message CameraImageRequest {
|
||||
// ==================== CLIMATE ====================
|
||||
enum ClimateMode {
|
||||
CLIMATE_MODE_OFF = 0;
|
||||
CLIMATE_MODE_AUTO = 1;
|
||||
CLIMATE_MODE_HEAT_COOL = 1;
|
||||
CLIMATE_MODE_COOL = 2;
|
||||
CLIMATE_MODE_HEAT = 3;
|
||||
CLIMATE_MODE_FAN_ONLY = 4;
|
||||
CLIMATE_MODE_DRY = 5;
|
||||
CLIMATE_MODE_AUTO = 6;
|
||||
}
|
||||
enum ClimateFanMode {
|
||||
CLIMATE_FAN_ON = 0;
|
||||
@ -704,6 +705,16 @@ enum ClimateAction {
|
||||
CLIMATE_ACTION_DRYING = 5;
|
||||
CLIMATE_ACTION_FAN = 6;
|
||||
}
|
||||
enum ClimatePreset {
|
||||
CLIMATE_PRESET_NONE = 0;
|
||||
CLIMATE_PRESET_HOME = 1;
|
||||
CLIMATE_PRESET_AWAY = 2;
|
||||
CLIMATE_PRESET_BOOST = 3;
|
||||
CLIMATE_PRESET_COMFORT = 4;
|
||||
CLIMATE_PRESET_ECO = 5;
|
||||
CLIMATE_PRESET_SLEEP = 6;
|
||||
CLIMATE_PRESET_ACTIVITY = 7;
|
||||
}
|
||||
message ListEntitiesClimateResponse {
|
||||
option (id) = 46;
|
||||
option (source) = SOURCE_SERVER;
|
||||
@ -720,10 +731,15 @@ message ListEntitiesClimateResponse {
|
||||
float visual_min_temperature = 8;
|
||||
float visual_max_temperature = 9;
|
||||
float visual_temperature_step = 10;
|
||||
bool supports_away = 11;
|
||||
// for older peer versions - in new system this
|
||||
// is if CLIMATE_PRESET_AWAY exists is supported_presets
|
||||
bool legacy_supports_away = 11;
|
||||
bool supports_action = 12;
|
||||
repeated ClimateFanMode supported_fan_modes = 13;
|
||||
repeated ClimateSwingMode supported_swing_modes = 14;
|
||||
repeated string supported_custom_fan_modes = 15;
|
||||
repeated ClimatePreset supported_presets = 16;
|
||||
repeated string supported_custom_presets = 17;
|
||||
}
|
||||
message ClimateStateResponse {
|
||||
option (id) = 47;
|
||||
@ -737,10 +753,14 @@ message ClimateStateResponse {
|
||||
float target_temperature = 4;
|
||||
float target_temperature_low = 5;
|
||||
float target_temperature_high = 6;
|
||||
bool away = 7;
|
||||
// For older peers, equal to preset == CLIMATE_PRESET_AWAY
|
||||
bool legacy_away = 7;
|
||||
ClimateAction action = 8;
|
||||
ClimateFanMode fan_mode = 9;
|
||||
ClimateSwingMode swing_mode = 10;
|
||||
string custom_fan_mode = 11;
|
||||
ClimatePreset preset = 12;
|
||||
string custom_preset = 13;
|
||||
}
|
||||
message ClimateCommandRequest {
|
||||
option (id) = 48;
|
||||
@ -757,10 +777,17 @@ message ClimateCommandRequest {
|
||||
float target_temperature_low = 7;
|
||||
bool has_target_temperature_high = 8;
|
||||
float target_temperature_high = 9;
|
||||
bool has_away = 10;
|
||||
bool away = 11;
|
||||
// legacy, for older peers, newer ones should use CLIMATE_PRESET_AWAY in preset
|
||||
bool has_legacy_away = 10;
|
||||
bool legacy_away = 11;
|
||||
bool has_fan_mode = 12;
|
||||
ClimateFanMode fan_mode = 13;
|
||||
bool has_swing_mode = 14;
|
||||
ClimateSwingMode swing_mode = 15;
|
||||
bool has_custom_fan_mode = 16;
|
||||
string custom_fan_mode = 17;
|
||||
bool has_preset = 18;
|
||||
ClimatePreset preset = 19;
|
||||
bool has_custom_preset = 20;
|
||||
string custom_preset = 21;
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
# type: ignore
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
||||
# source: api_options.proto
|
||||
|
||||
import sys
|
||||
_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
|
||||
@ -22,7 +21,8 @@ DESCRIPTOR = _descriptor.FileDescriptor(
|
||||
package='',
|
||||
syntax='proto2',
|
||||
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')
|
||||
create_key=_descriptor._internal_create_key,
|
||||
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,])
|
||||
|
||||
@ -31,19 +31,23 @@ _APISOURCETYPE = _descriptor.EnumDescriptor(
|
||||
full_name='APISourceType',
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
values=[
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='SOURCE_BOTH', index=0, number=0,
|
||||
serialized_options=None,
|
||||
type=None),
|
||||
type=None,
|
||||
create_key=_descriptor._internal_create_key),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='SOURCE_SERVER', index=1, number=1,
|
||||
serialized_options=None,
|
||||
type=None),
|
||||
type=None,
|
||||
create_key=_descriptor._internal_create_key),
|
||||
_descriptor.EnumValueDescriptor(
|
||||
name='SOURCE_CLIENT', index=2, number=2,
|
||||
serialized_options=None,
|
||||
type=None),
|
||||
type=None,
|
||||
create_key=_descriptor._internal_create_key),
|
||||
],
|
||||
containing_type=None,
|
||||
serialized_options=None,
|
||||
@ -64,7 +68,7 @@ needs_setup_connection = _descriptor.FieldDescriptor(
|
||||
has_default_value=True, default_value=True,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=True, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR)
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key)
|
||||
NEEDS_AUTHENTICATION_FIELD_NUMBER = 1039
|
||||
needs_authentication = _descriptor.FieldDescriptor(
|
||||
name='needs_authentication', full_name='needs_authentication', index=1,
|
||||
@ -72,7 +76,7 @@ needs_authentication = _descriptor.FieldDescriptor(
|
||||
has_default_value=True, default_value=True,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=True, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR)
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key)
|
||||
ID_FIELD_NUMBER = 1036
|
||||
id = _descriptor.FieldDescriptor(
|
||||
name='id', full_name='id', index=2,
|
||||
@ -80,7 +84,7 @@ id = _descriptor.FieldDescriptor(
|
||||
has_default_value=True, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=True, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR)
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key)
|
||||
SOURCE_FIELD_NUMBER = 1037
|
||||
source = _descriptor.FieldDescriptor(
|
||||
name='source', full_name='source', index=3,
|
||||
@ -88,15 +92,15 @@ source = _descriptor.FieldDescriptor(
|
||||
has_default_value=True, default_value=0,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=True, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR)
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key)
|
||||
IFDEF_FIELD_NUMBER = 1038
|
||||
ifdef = _descriptor.FieldDescriptor(
|
||||
name='ifdef', full_name='ifdef', index=4,
|
||||
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,
|
||||
is_extension=True, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR)
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key)
|
||||
LOG_FIELD_NUMBER = 1039
|
||||
log = _descriptor.FieldDescriptor(
|
||||
name='log', full_name='log', index=5,
|
||||
@ -104,7 +108,7 @@ log = _descriptor.FieldDescriptor(
|
||||
has_default_value=True, default_value=True,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=True, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR)
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key)
|
||||
NO_DELAY_FIELD_NUMBER = 1040
|
||||
no_delay = _descriptor.FieldDescriptor(
|
||||
name='no_delay', full_name='no_delay', index=6,
|
||||
@ -112,7 +116,7 @@ no_delay = _descriptor.FieldDescriptor(
|
||||
has_default_value=True, default_value=False,
|
||||
message_type=None, enum_type=None, containing_type=None,
|
||||
is_extension=True, extension_scope=None,
|
||||
serialized_options=None, file=DESCRIPTOR)
|
||||
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key)
|
||||
|
||||
|
||||
_VOID = _descriptor.Descriptor(
|
||||
@ -121,6 +125,7 @@ _VOID = _descriptor.Descriptor(
|
||||
filename=None,
|
||||
file=DESCRIPTOR,
|
||||
containing_type=None,
|
||||
create_key=_descriptor._internal_create_key,
|
||||
fields=[
|
||||
],
|
||||
extensions=[
|
||||
@ -149,11 +154,11 @@ DESCRIPTOR.extensions_by_name['log'] = log
|
||||
DESCRIPTOR.extensions_by_name['no_delay'] = no_delay
|
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
|
||||
|
||||
void = _reflection.GeneratedProtocolMessageType('void', (_message.Message,), dict(
|
||||
DESCRIPTOR = _VOID,
|
||||
__module__ = 'api_options_pb2'
|
||||
void = _reflection.GeneratedProtocolMessageType('void', (_message.Message,), {
|
||||
'DESCRIPTOR' : _VOID,
|
||||
'__module__' : 'api_options_pb2'
|
||||
# @@protoc_insertion_point(class_scope:void)
|
||||
))
|
||||
})
|
||||
_sym_db.RegisterMessage(void)
|
||||
|
||||
google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension(needs_setup_connection)
|
||||
|
File diff suppressed because one or more lines are too long
@ -59,6 +59,7 @@ from aioesphomeapi.model import (
|
||||
ClimateFanMode,
|
||||
ClimateInfo,
|
||||
ClimateMode,
|
||||
ClimatePreset,
|
||||
ClimateState,
|
||||
ClimateSwingMode,
|
||||
CoverInfo,
|
||||
@ -471,9 +472,11 @@ class APIClient:
|
||||
target_temperature: Optional[float] = None,
|
||||
target_temperature_low: Optional[float] = None,
|
||||
target_temperature_high: Optional[float] = None,
|
||||
away: Optional[bool] = None,
|
||||
fan_mode: Optional[ClimateFanMode] = None,
|
||||
swing_mode: Optional[ClimateSwingMode] = None,
|
||||
custom_fan_mode: Optional[str] = None,
|
||||
preset: Optional[ClimatePreset] = None,
|
||||
custom_preset: Optional[str] = None,
|
||||
) -> None:
|
||||
self._check_authenticated()
|
||||
|
||||
@ -491,15 +494,26 @@ class APIClient:
|
||||
if target_temperature_high is not None:
|
||||
req.has_target_temperature_high = True
|
||||
req.target_temperature_high = target_temperature_high
|
||||
if away is not None:
|
||||
req.has_away = True
|
||||
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
|
||||
if custom_fan_mode is not None:
|
||||
req.has_custom_fan_mode = True
|
||||
req.custom_fan_mode = custom_fan_mode
|
||||
if preset is not None:
|
||||
apiv = cast(APIVersion, self.api_version)
|
||||
if apiv < APIVersion(1, 5):
|
||||
req.has_legacy_away = True
|
||||
req.legacy_away = preset == ClimatePreset.AWAY
|
||||
else:
|
||||
req.has_preset = True
|
||||
req.preset = preset
|
||||
if custom_preset is not None:
|
||||
req.has_custom_preset = True
|
||||
req.custom_preset = custom_preset
|
||||
assert self._connection is not None
|
||||
await self._connection.send_message(req)
|
||||
|
||||
|
@ -251,11 +251,12 @@ class CameraState(EntityState):
|
||||
# ==================== CLIMATE ====================
|
||||
class ClimateMode(APIIntEnum):
|
||||
OFF = 0
|
||||
AUTO = 1
|
||||
HEAT_COOL = 1
|
||||
COOL = 2
|
||||
HEAT = 3
|
||||
FAN_ONLY = 4
|
||||
DRY = 5
|
||||
AUTO = 6
|
||||
|
||||
|
||||
class ClimateFanMode(APIIntEnum):
|
||||
@ -286,6 +287,17 @@ class ClimateAction(APIIntEnum):
|
||||
FAN = 6
|
||||
|
||||
|
||||
class ClimatePreset(APIIntEnum):
|
||||
NONE = 0
|
||||
HOME = 1
|
||||
AWAY = 2
|
||||
BOOST = 3
|
||||
COMFORT = 4
|
||||
ECO = 5
|
||||
SLEEP = 6
|
||||
ACTIVITY = 7
|
||||
|
||||
|
||||
@attr.s
|
||||
class ClimateInfo(EntityInfo):
|
||||
supports_current_temperature = attr.ib(type=bool, default=False)
|
||||
@ -298,7 +310,7 @@ class ClimateInfo(EntityInfo):
|
||||
visual_min_temperature = attr.ib(type=float, default=0.0)
|
||||
visual_max_temperature = 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)
|
||||
legacy_supports_away = attr.ib(type=bool, default=False)
|
||||
supports_action = attr.ib(type=bool, default=False)
|
||||
supported_fan_modes = attr.ib(
|
||||
type=List[ClimateFanMode],
|
||||
@ -310,6 +322,20 @@ class ClimateInfo(EntityInfo):
|
||||
converter=ClimateSwingMode.convert_list, # type: ignore
|
||||
factory=list,
|
||||
)
|
||||
supported_custom_fan_modes = attr.ib(type=List[str], converter=list, factory=list)
|
||||
supported_presets = attr.ib(
|
||||
type=List[ClimatePreset], converter=ClimatePreset.convert_list, factory=list # type: ignore
|
||||
)
|
||||
supported_custom_presets = attr.ib(type=List[str], converter=list, factory=list)
|
||||
|
||||
def supported_presets_compat(self, api_version: APIVersion) -> List[ClimatePreset]:
|
||||
if api_version < APIVersion(1, 5):
|
||||
return (
|
||||
[ClimatePreset.HOME, ClimatePreset.AWAY]
|
||||
if self.legacy_supports_away
|
||||
else []
|
||||
)
|
||||
return self.supported_presets
|
||||
|
||||
|
||||
@attr.s
|
||||
@ -328,7 +354,7 @@ class ClimateState(EntityState):
|
||||
target_temperature = 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)
|
||||
away = attr.ib(type=bool, default=False)
|
||||
legacy_away = attr.ib(type=bool, default=False)
|
||||
fan_mode = attr.ib(
|
||||
type=Optional[ClimateFanMode],
|
||||
converter=ClimateFanMode.convert, # type: ignore
|
||||
@ -339,6 +365,18 @@ class ClimateState(EntityState):
|
||||
converter=ClimateSwingMode.convert, # type: ignore
|
||||
default=ClimateSwingMode.OFF,
|
||||
)
|
||||
custom_fan_mode = attr.ib(type=str, default="")
|
||||
preset = attr.ib(
|
||||
type=Optional[ClimatePreset],
|
||||
converter=ClimatePreset.convert, # type: ignore
|
||||
default=ClimatePreset.HOME,
|
||||
)
|
||||
custom_preset = attr.ib(type=str, default="")
|
||||
|
||||
def preset_compat(self, api_version: APIVersion) -> Optional[ClimatePreset]:
|
||||
if api_version < APIVersion(1, 5):
|
||||
return ClimatePreset.AWAY if self.legacy_away else ClimatePreset.HOME
|
||||
return self.preset
|
||||
|
||||
|
||||
COMPONENT_TYPE_TO_INFO = {
|
||||
|
Loading…
Reference in New Issue
Block a user