From da2821ab3627c3be06f0a94eaaed2906dbb4dad6 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Tue, 18 Dec 2018 19:31:43 +0100 Subject: [PATCH] Add native ESPHome API (#265) * Esphomeapi * Updates * Remove MQTT from wizard * Add protobuf to requirements * Fix * API Client updates * Dump config on API connect * Old WiFi config migration * Home Assistant state import * Lint --- .github/ISSUE_TEMPLATE/bug_report.md | 8 +- .github/ISSUE_TEMPLATE/feature_request.md | 17 +- .github/ISSUE_TEMPLATE/new-integration.md | 15 +- .github/PULL_REQUEST_TEMPLATE.md | 6 - esphomeyaml-edge/config.json | 5 +- esphomeyaml/__main__.py | 8 +- esphomeyaml/api/__init__.py | 0 esphomeyaml/api/api.proto | 329 +++ esphomeyaml/api/api_pb2.py | 2445 +++++++++++++++++ esphomeyaml/api/client.py | 474 ++++ esphomeyaml/automation.py | 5 +- esphomeyaml/components/api.py | 85 + .../components/binary_sensor/__init__.py | 15 +- .../components/binary_sensor/custom.py | 4 +- .../components/binary_sensor/status.py | 1 - esphomeyaml/components/custom_component.py | 4 +- esphomeyaml/components/deep_sleep.py | 3 +- esphomeyaml/components/interval.py | 23 + esphomeyaml/components/light/__init__.py | 15 +- esphomeyaml/components/logger.py | 2 +- esphomeyaml/components/mqtt.py | 7 +- esphomeyaml/components/output/custom.py | 8 +- esphomeyaml/components/remote_receiver.py | 3 +- esphomeyaml/components/sensor/__init__.py | 4 +- esphomeyaml/components/sensor/custom.py | 4 +- .../components/sensor/homeassistant.py | 32 + esphomeyaml/components/switch/custom.py | 4 +- esphomeyaml/components/text_sensor/custom.py | 4 +- .../components/text_sensor/homeassistant.py | 33 + esphomeyaml/components/time/homeassistant.py | 25 + esphomeyaml/components/time/sntp.py | 7 +- esphomeyaml/components/wifi.py | 79 +- esphomeyaml/config_validation.py | 42 +- esphomeyaml/const.py | 6 + esphomeyaml/core.py | 2 + esphomeyaml/core_config.py | 4 +- esphomeyaml/dashboard/dashboard.py | 54 +- esphomeyaml/dashboard/static/esphomeyaml.js | 4 +- esphomeyaml/dashboard/templates/index.html | 104 +- esphomeyaml/espota2.py | 60 +- esphomeyaml/helpers.py | 24 + esphomeyaml/util.py | 39 + esphomeyaml/wizard.py | 80 +- esphomeyaml/writer.py | 22 + pylintrc | 1 + requirements.txt | 1 + setup.cfg | 1 + setup.py | 1 + tests/.gitignore | 10 + 49 files changed, 3783 insertions(+), 346 deletions(-) create mode 100644 esphomeyaml/api/__init__.py create mode 100644 esphomeyaml/api/api.proto create mode 100644 esphomeyaml/api/api_pb2.py create mode 100644 esphomeyaml/api/client.py create mode 100644 esphomeyaml/components/api.py create mode 100644 esphomeyaml/components/interval.py create mode 100644 esphomeyaml/components/sensor/homeassistant.py create mode 100644 esphomeyaml/components/text_sensor/homeassistant.py create mode 100644 esphomeyaml/components/time/homeassistant.py create mode 100644 tests/.gitignore diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 3d46b9a2f9..52ee89e4f6 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,6 +1,6 @@ --- name: Bug report -about: Create a report to help us improve +about: Create a report to help esphomelib improve --- @@ -9,7 +9,9 @@ about: Create a report to help us improve - esphomeyaml [here] - This is mostly for reporting bugs when compiling and when you get a long stack trace while compiling or if a configuration fails to validate. - esphomelib [https://github.com/OttoWinter/esphomelib] - Report bugs there if the ESP is crashing or a feature is not working as expected. - esphomedocs [https://github.com/OttoWinter/esphomedocs] - Report bugs there if the documentation is wrong/outdated. -- Provide as many details as possible. Paste logs, configuration sample and code into the backticks (```). Do not delete any text from this template! +- Provide as many details as possible. Paste logs, configuration sample and code into the backticks (```). + + DO NOT DELETE ANY TEXT from this template! Otherwise the issue may be closed without a comment. --> **Operating environment (Hass.io/Docker/pip/etc.):** @@ -33,7 +35,7 @@ Please add the link to the documentation at https://esphomelib.com/esphomeyaml/i **Problem-relevant YAML-configuration entries:** ```yaml - +PASTE YAML FILE HERE ``` **Traceback (if applicable):** diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 05b02948b2..2a033e374e 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -7,16 +7,15 @@ about: Suggest an idea for this project -**Is your feature request related to a problem? Please describe.** - -Ex. I'm always frustrated when [...] +**Is your feature request related to a problem/use-case? Please describe.** + -**Describe the solution you'd like** -A description of what you want to happen. +**Describe the solution you'd like:** + -**Additional context** -Add any other context about the feature request here. +**Additional context:** + diff --git a/.github/ISSUE_TEMPLATE/new-integration.md b/.github/ISSUE_TEMPLATE/new-integration.md index fe80521c6f..34fdb086ad 100644 --- a/.github/ISSUE_TEMPLATE/new-integration.md +++ b/.github/ISSUE_TEMPLATE/new-integration.md @@ -4,17 +4,10 @@ about: Suggest a new integration for esphomelib --- - +DO NOT POST NEW INTEGRATION REQUESTS HERE! -**What new integration would you wish to have?** - +Please post all new integration requests in the esphomelib repository: -**If possible, provide a link to an existing library for the integration:** +https://github.com/OttoWinter/esphomelib/issues -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Additional context** +Thank you! diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6e1fc9be00..f0fdd660ae 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -6,15 +6,9 @@ **Pull request in [esphomedocs](https://github.com/OttoWinter/esphomedocs) with documentation (if applicable):** OttoWinter/esphomedocs# **Pull request in [esphomelib](https://github.com/OttoWinter/esphomelib) with C++ framework changes (if applicable):** OttoWinter/esphomelib# -## Example entry for YAML configuration (if applicable): -```yaml - -``` - ## Checklist: - [ ] The code change is tested and works locally. - [ ] Tests have been added to verify that the new code works (under `tests/` folder). - - [ ] Check this box if you have read, understand, comply, and agree with the [Code of Conduct](https://github.com/OttoWinter/esphomeyaml/blob/master/CODE_OF_CONDUCT.md). If user exposed functionality or configuration variables are added/changed: - [ ] Documentation added/updated in [esphomedocs](https://github.com/OttoWinter/esphomedocs). diff --git a/esphomeyaml-edge/config.json b/esphomeyaml-edge/config.json index afdb500c6f..ab5d8eb052 100644 --- a/esphomeyaml-edge/config.json +++ b/esphomeyaml-edge/config.json @@ -14,12 +14,9 @@ ], "hassio_api": true, "auth_api": true, - "services": [ - "mqtt:want" - ], "hassio_role": "default", "homeassistant_api": false, - "host_network": false, + "host_network": true, "boot": "auto", "ports": { "6052/tcp": 6052 diff --git a/esphomeyaml/__main__.py b/esphomeyaml/__main__.py index 9a95d4cfbe..8b04e1df95 100644 --- a/esphomeyaml/__main__.py +++ b/esphomeyaml/__main__.py @@ -9,6 +9,7 @@ import random import sys from esphomeyaml import const, core_config, mqtt, platformio_api, wizard, writer, yaml_util +from esphomeyaml.api.client import run_logs from esphomeyaml.config import get_component, iter_components, read_config, strip_default_ids from esphomeyaml.const import CONF_BAUD_RATE, CONF_DOMAIN, CONF_ESPHOMEYAML, \ CONF_HOSTNAME, CONF_LOGGER, CONF_MANUAL_IP, CONF_NAME, CONF_STATIC_IP, CONF_USE_CUSTOM_CODE, \ @@ -22,7 +23,7 @@ from esphomeyaml.util import run_external_command, safe_print _LOGGER = logging.getLogger(__name__) -PRE_INITIALIZE = ['esphomeyaml', 'logger', 'wifi', 'ota', 'mqtt', 'web_server', 'i2c'] +PRE_INITIALIZE = ['esphomeyaml', 'logger', 'wifi', 'ota', 'mqtt', 'web_server', 'api', 'i2c'] def get_serial_ports(): @@ -202,6 +203,8 @@ def show_logs(config, args, port): if port != 'OTA' and serial_port: run_miniterm(config, port) return 0 + if 'api' in config: + return run_logs(config, get_upload_host(config)) return mqtt.show_logs(config, args.topic, args.username, args.password, args.client_id) @@ -368,6 +371,8 @@ def parse_args(argv): parser = argparse.ArgumentParser(prog='esphomeyaml') parser.add_argument('-v', '--verbose', help="Enable verbose esphomeyaml logs.", action='store_true') + parser.add_argument('--dashboard', help="Internal flag to set if the command is run from the " + "dashboard.", action='store_true') parser.add_argument('configuration', help='Your YAML configuration file.') subparsers = parser.add_subparsers(help='Commands', dest='command') @@ -445,6 +450,7 @@ def parse_args(argv): def run_esphomeyaml(argv): args = parse_args(argv) + CORE.dashboard = args.dashboard setup_log(args.verbose) if args.command in PRE_CONFIG_ACTIONS: diff --git a/esphomeyaml/api/__init__.py b/esphomeyaml/api/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/esphomeyaml/api/api.proto b/esphomeyaml/api/api.proto new file mode 100644 index 0000000000..33d087099a --- /dev/null +++ b/esphomeyaml/api/api.proto @@ -0,0 +1,329 @@ +syntax = "proto3"; + +// The Home Assistant protocol is structured as a simple +// TCP socket with short binary messages encoded in the protocol buffers format +// First, a message in this protocol has a specific format: +// * VarInt denoting the size of the message object. (type is not part of this) +// * VarInt denoting the type of message. +// * The message object encoded as a ProtoBuf message + +// The connection is established in 4 steps: +// * First, the client connects to the server and sends a "Hello Request" identifying itself +// * The server responds with a "Hello Response" and selects the protocol version +// * After receiving this message, the client attempts to authenticate itself using +// the password and a "Connect Request" +// * The server responds with a "Connect Response" and notifies of invalid password. +// If anything in this initial process fails, the connection must immediately closed +// by both sides and _no_ disconnection message is to be sent. + +// Message sent at the beginning of each connection +// Can only be sent by the client and only at the beginning of the connection +message HelloRequest { + // Description of client (like User Agent) + // For example "Home Assistant" + // Not strictly necessary to send but nice for debugging + // purposes. + string client_info = 1; +} + +// Confirmation of successful connection request. +// Can only be sent by the server and only at the beginning of the connection +message HelloResponse { + // The version of the API to use. The _client_ (for example Home Assistant) needs to check + // for compatibility and if necessary adopt to an older API. + // Major is for breaking changes in the base protocol - a mismatch will lead to immediate disconnect_client_ + // Minor is for breaking changes in individual messages - a mismatch will lead to a warning message + uint32 api_version_major = 1; + uint32 api_version_minor = 2; + + // A string identifying the server (ESP); like client info this may be empty + // and only exists for debugging/logging purposes. + // For example "ESPHome v1.10.0 on ESP8266" + string server_info = 3; +} + +// Message sent at the beginning of each connection to authenticate the client +// Can only be sent by the client and only at the beginning of the connection +message ConnectRequest { + // The password to log in with + string password = 1; +} + +// Confirmation of successful connection. After this the connection is available for all traffic. +// Can only be sent by the server and only at the beginning of the connection +message ConnectResponse { + bool invalid_password = 1; +} + +// Request to close the connection. +// Can be sent by both the client and server +message DisconnectRequest { + // Do not close the connection before the acknowledgement arrives +} + +message DisconnectResponse { + // Empty - Both parties are required to close the connection after this + // message has been received. +} + +message PingRequest { + // Empty +} + +message PingResponse { + // Empty +} + +message DeviceInfoRequest { + // Empty +} + +message DeviceInfoResponse { + bool uses_password = 1; + + // The name of the node, given by "App.set_name()" + string name = 2; + + // The mac address of the device. For example "AC:BC:32:89:0E:A9" + string mac_address = 3; + + // A string describing the ESPHome version. For example "1.10.0" + string esphome_core_version = 4; + + // A string describing the date of compilation, this is generated by the compiler + // and therefore may not be in the same format all the time. + // If the user isn't using esphomeyaml, this will also not be set. + string compilation_time = 5; + + // The model of the board. For example NodeMCU + string model = 6; + + bool has_deep_sleep = 7; +} + +message ListEntitiesRequest { + // Empty +} + +message ListEntitiesBinarySensorResponse { + string object_id = 1; + fixed32 key = 2; + string name = 3; + string unique_id = 4; + + string device_class = 5; + bool is_status_binary_sensor = 6; +} +message ListEntitiesCoverResponse { + string object_id = 1; + fixed32 key = 2; + string name = 3; + string unique_id = 4; + + bool is_optimistic = 5; +} +message ListEntitiesFanResponse { + string object_id = 1; + fixed32 key = 2; + string name = 3; + string unique_id = 4; + + bool supports_oscillation = 5; + bool supports_speed = 6; +} +message ListEntitiesLightResponse { + string object_id = 1; + fixed32 key = 2; + string name = 3; + string unique_id = 4; + + bool supports_brightness = 5; + bool supports_rgb = 6; + bool supports_white_value = 7; + bool supports_color_temperature = 8; + float min_mireds = 9; + float max_mireds = 10; + repeated string effects = 11; +} +message ListEntitiesSensorResponse { + string object_id = 1; + fixed32 key = 2; + string name = 3; + string unique_id = 4; + + string icon = 5; + string unit_of_measurement = 6; + int32 accuracy_decimals = 7; +} +message ListEntitiesSwitchResponse { + string object_id = 1; + fixed32 key = 2; + string name = 3; + string unique_id = 4; + + string icon = 5; + bool optimistic = 6; +} +message ListEntitiesTextSensorResponse { + string object_id = 1; + fixed32 key = 2; + string name = 3; + string unique_id = 4; + + string icon = 5; +} +message ListEntitiesDoneResponse { + // Empty +} + +message SubscribeStatesRequest { + // Empty +} +message BinarySensorStateResponse { + fixed32 key = 1; + bool state = 2; +} +message CoverStateResponse { + fixed32 key = 1; + enum CoverState { + OPEN = 0; + CLOSED = 1; + } + CoverState state = 2; +} +enum FanSpeed { + LOW = 0; + MEDIUM = 1; + HIGH = 2; +} +message FanStateResponse { + fixed32 key = 1; + bool state = 2; + bool oscillating = 3; + FanSpeed speed = 4; +} +message LightStateResponse { + fixed32 key = 1; + bool state = 2; + float brightness = 3; + float red = 4; + float green = 5; + float blue = 6; + float white = 7; + float color_temperature = 8; + string effect = 9; +} +message SensorStateResponse { + fixed32 key = 1; + float state = 2; +} +message SwitchStateResponse { + fixed32 key = 1; + bool state = 2; +} +message TextSensorStateResponse { + fixed32 key = 1; + string state = 2; +} + +message CoverCommandRequest { + fixed32 key = 1; + enum CoverCommand { + OPEN = 0; + CLOSE = 1; + STOP = 2; + } + bool has_state = 2; + CoverCommand command = 3; +} +message FanCommandRequest { + fixed32 key = 1; + bool has_state = 2; + bool state = 3; + bool has_speed = 4; + FanSpeed speed = 5; + bool has_oscillating = 6; + bool oscillating = 7; +} +message LightCommandRequest { + fixed32 key = 1; + bool has_state = 2; + bool state = 3; + bool has_brightness = 4; + float brightness = 5; + bool has_rgb = 6; + float red = 7; + float green = 8; + float blue = 9; + bool has_white = 10; + float white = 11; + bool has_color_temperature = 12; + float color_temperature = 13; + bool has_transition_length = 14; + uint32 transition_length = 15; + bool has_flash_length = 16; + uint32 flash_length = 17; + bool has_effect = 18; + string effect = 19; +} +message SwitchCommandRequest { + fixed32 key = 1; + bool state = 2; +} + +enum LogLevel { + NONE = 0; + ERROR = 1; + WARN = 2; + INFO = 3; + DEBUG = 4; + VERBOSE = 5; + VERY_VERBOSE = 6; +} + +message SubscribeLogsRequest { + LogLevel level = 1; + bool dump_config = 2; +} + +message SubscribeLogsResponse { + LogLevel level = 1; + string tag = 2; + string message = 3; +} + +message SubscribeServiceCallsRequest { + +} + +message ServiceCallResponse { + string service = 1; + map data = 2; + map data_template = 3; + map variables = 4; +} + +// 1. Client sends SubscribeHomeAssistantStatesRequest +// 2. Server responds with zero or more SubscribeHomeAssistantStateResponse (async) +// 3. Client sends HomeAssistantStateResponse for state changes. +message SubscribeHomeAssistantStatesRequest { + +} + +message SubscribeHomeAssistantStateResponse { + string entity_id = 1; +} + +message HomeAssistantStateResponse { + string entity_id = 1; + string state = 2; +} + +message GetTimeRequest { + +} + +message GetTimeResponse { + fixed32 epoch_seconds = 1; +} + diff --git a/esphomeyaml/api/api_pb2.py b/esphomeyaml/api/api_pb2.py new file mode 100644 index 0000000000..3c6131c287 --- /dev/null +++ b/esphomeyaml/api/api_pb2.py @@ -0,0 +1,2445 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: api.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 +from google.protobuf import reflection as _reflection +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor.FileDescriptor( + name='api.proto', + package='', + syntax='proto3', + serialized_options=None, + serialized_pb=_b('\n\tapi.proto\"#\n\x0cHelloRequest\x12\x13\n\x0b\x63lient_info\x18\x01 \x01(\t\"Z\n\rHelloResponse\x12\x19\n\x11\x61pi_version_major\x18\x01 \x01(\r\x12\x19\n\x11\x61pi_version_minor\x18\x02 \x01(\r\x12\x13\n\x0bserver_info\x18\x03 \x01(\t\"\"\n\x0e\x43onnectRequest\x12\x10\n\x08password\x18\x01 \x01(\t\"+\n\x0f\x43onnectResponse\x12\x18\n\x10invalid_password\x18\x01 \x01(\x08\"\x13\n\x11\x44isconnectRequest\"\x14\n\x12\x44isconnectResponse\"\r\n\x0bPingRequest\"\x0e\n\x0cPingResponse\"\x13\n\x11\x44\x65viceInfoRequest\"\xad\x01\n\x12\x44\x65viceInfoResponse\x12\x15\n\ruses_password\x18\x01 \x01(\x08\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0bmac_address\x18\x03 \x01(\t\x12\x1c\n\x14\x65sphome_core_version\x18\x04 \x01(\t\x12\x18\n\x10\x63ompilation_time\x18\x05 \x01(\t\x12\r\n\x05model\x18\x06 \x01(\t\x12\x16\n\x0ehas_deep_sleep\x18\x07 \x01(\x08\"\x15\n\x13ListEntitiesRequest\"\x9a\x01\n ListEntitiesBinarySensorResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x14\n\x0c\x64\x65vice_class\x18\x05 \x01(\t\x12\x1f\n\x17is_status_binary_sensor\x18\x06 \x01(\x08\"s\n\x19ListEntitiesCoverResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x15\n\ris_optimistic\x18\x05 \x01(\x08\"\x90\x01\n\x17ListEntitiesFanResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x1c\n\x14supports_oscillation\x18\x05 \x01(\x08\x12\x16\n\x0esupports_speed\x18\x06 \x01(\x08\"\x8a\x02\n\x19ListEntitiesLightResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x1b\n\x13supports_brightness\x18\x05 \x01(\x08\x12\x14\n\x0csupports_rgb\x18\x06 \x01(\x08\x12\x1c\n\x14supports_white_value\x18\x07 \x01(\x08\x12\"\n\x1asupports_color_temperature\x18\x08 \x01(\x08\x12\x12\n\nmin_mireds\x18\t \x01(\x02\x12\x12\n\nmax_mireds\x18\n \x01(\x02\x12\x0f\n\x07\x65\x66\x66\x65\x63ts\x18\x0b \x03(\t\"\xa3\x01\n\x1aListEntitiesSensorResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x0c\n\x04icon\x18\x05 \x01(\t\x12\x1b\n\x13unit_of_measurement\x18\x06 \x01(\t\x12\x19\n\x11\x61\x63\x63uracy_decimals\x18\x07 \x01(\x05\"\x7f\n\x1aListEntitiesSwitchResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x0c\n\x04icon\x18\x05 \x01(\t\x12\x12\n\noptimistic\x18\x06 \x01(\x08\"o\n\x1eListEntitiesTextSensorResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x0c\n\x04icon\x18\x05 \x01(\t\"\x1a\n\x18ListEntitiesDoneResponse\"\x18\n\x16SubscribeStatesRequest\"7\n\x19\x42inarySensorStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x08\"t\n\x12\x43overStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12-\n\x05state\x18\x02 \x01(\x0e\x32\x1e.CoverStateResponse.CoverState\"\"\n\nCoverState\x12\x08\n\x04OPEN\x10\x00\x12\n\n\x06\x43LOSED\x10\x01\"]\n\x10\x46\x61nStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x08\x12\x13\n\x0boscillating\x18\x03 \x01(\x08\x12\x18\n\x05speed\x18\x04 \x01(\x0e\x32\t.FanSpeed\"\xa8\x01\n\x12LightStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x08\x12\x12\n\nbrightness\x18\x03 \x01(\x02\x12\x0b\n\x03red\x18\x04 \x01(\x02\x12\r\n\x05green\x18\x05 \x01(\x02\x12\x0c\n\x04\x62lue\x18\x06 \x01(\x02\x12\r\n\x05white\x18\x07 \x01(\x02\x12\x19\n\x11\x63olor_temperature\x18\x08 \x01(\x02\x12\x0e\n\x06\x65\x66\x66\x65\x63t\x18\t \x01(\t\"1\n\x13SensorStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x02\"1\n\x13SwitchStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x08\"5\n\x17TextSensorStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\t\"\x98\x01\n\x13\x43overCommandRequest\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\x11\n\thas_state\x18\x02 \x01(\x08\x12\x32\n\x07\x63ommand\x18\x03 \x01(\x0e\x32!.CoverCommandRequest.CoverCommand\"-\n\x0c\x43overCommand\x12\x08\n\x04OPEN\x10\x00\x12\t\n\x05\x43LOSE\x10\x01\x12\x08\n\x04STOP\x10\x02\"\x9d\x01\n\x11\x46\x61nCommandRequest\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\x11\n\thas_state\x18\x02 \x01(\x08\x12\r\n\x05state\x18\x03 \x01(\x08\x12\x11\n\thas_speed\x18\x04 \x01(\x08\x12\x18\n\x05speed\x18\x05 \x01(\x0e\x32\t.FanSpeed\x12\x17\n\x0fhas_oscillating\x18\x06 \x01(\x08\x12\x13\n\x0boscillating\x18\x07 \x01(\x08\"\x95\x03\n\x13LightCommandRequest\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\x11\n\thas_state\x18\x02 \x01(\x08\x12\r\n\x05state\x18\x03 \x01(\x08\x12\x16\n\x0ehas_brightness\x18\x04 \x01(\x08\x12\x12\n\nbrightness\x18\x05 \x01(\x02\x12\x0f\n\x07has_rgb\x18\x06 \x01(\x08\x12\x0b\n\x03red\x18\x07 \x01(\x02\x12\r\n\x05green\x18\x08 \x01(\x02\x12\x0c\n\x04\x62lue\x18\t \x01(\x02\x12\x11\n\thas_white\x18\n \x01(\x08\x12\r\n\x05white\x18\x0b \x01(\x02\x12\x1d\n\x15has_color_temperature\x18\x0c \x01(\x08\x12\x19\n\x11\x63olor_temperature\x18\r \x01(\x02\x12\x1d\n\x15has_transition_length\x18\x0e \x01(\x08\x12\x19\n\x11transition_length\x18\x0f \x01(\r\x12\x18\n\x10has_flash_length\x18\x10 \x01(\x08\x12\x14\n\x0c\x66lash_length\x18\x11 \x01(\r\x12\x12\n\nhas_effect\x18\x12 \x01(\x08\x12\x0e\n\x06\x65\x66\x66\x65\x63t\x18\x13 \x01(\t\"2\n\x14SwitchCommandRequest\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x08\"E\n\x14SubscribeLogsRequest\x12\x18\n\x05level\x18\x01 \x01(\x0e\x32\t.LogLevel\x12\x13\n\x0b\x64ump_config\x18\x02 \x01(\x08\"O\n\x15SubscribeLogsResponse\x12\x18\n\x05level\x18\x01 \x01(\x0e\x32\t.LogLevel\x12\x0b\n\x03tag\x18\x02 \x01(\t\x12\x0f\n\x07message\x18\x03 \x01(\t\"\x1e\n\x1cSubscribeServiceCallsRequest\"\xdf\x02\n\x13ServiceCallResponse\x12\x0f\n\x07service\x18\x01 \x01(\t\x12,\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32\x1e.ServiceCallResponse.DataEntry\x12=\n\rdata_template\x18\x03 \x03(\x0b\x32&.ServiceCallResponse.DataTemplateEntry\x12\x36\n\tvariables\x18\x04 \x03(\x0b\x32#.ServiceCallResponse.VariablesEntry\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x33\n\x11\x44\x61taTemplateEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x30\n\x0eVariablesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"7\n\"SubscribeHomeAssistantStateRequest\x12\x11\n\tentity_id\x18\x01 \x01(\t\"G\n#SubscribeHomeAssistantStateResponse\x12\x11\n\tentity_id\x18\x01 \x01(\t\x12\r\n\x05state\x18\x02 \x01(\t\"\x10\n\x0eGetTimeRequest\"(\n\x0fGetTimeResponse\x12\x15\n\repoch_seconds\x18\x01 \x01(\x07*)\n\x08\x46\x61nSpeed\x12\x07\n\x03LOW\x10\x00\x12\n\n\x06MEDIUM\x10\x01\x12\x08\n\x04HIGH\x10\x02*]\n\x08LogLevel\x12\x08\n\x04NONE\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x08\n\x04WARN\x10\x02\x12\x08\n\x04INFO\x10\x03\x12\t\n\x05\x44\x45\x42UG\x10\x04\x12\x0b\n\x07VERBOSE\x10\x05\x12\x10\n\x0cVERY_VERBOSE\x10\x06\x62\x06proto3') +) + +_FANSPEED = _descriptor.EnumDescriptor( + name='FanSpeed', + full_name='FanSpeed', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='LOW', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='MEDIUM', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='HIGH', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3770, + serialized_end=3811, +) +_sym_db.RegisterEnumDescriptor(_FANSPEED) + +FanSpeed = enum_type_wrapper.EnumTypeWrapper(_FANSPEED) +_LOGLEVEL = _descriptor.EnumDescriptor( + name='LogLevel', + full_name='LogLevel', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='NONE', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='ERROR', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='WARN', index=2, number=2, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='INFO', index=3, number=3, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='DEBUG', index=4, number=4, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='VERBOSE', index=5, number=5, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='VERY_VERBOSE', index=6, number=6, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=3813, + serialized_end=3906, +) +_sym_db.RegisterEnumDescriptor(_LOGLEVEL) + +LogLevel = enum_type_wrapper.EnumTypeWrapper(_LOGLEVEL) +LOW = 0 +MEDIUM = 1 +HIGH = 2 +NONE = 0 +ERROR = 1 +WARN = 2 +INFO = 3 +DEBUG = 4 +VERBOSE = 5 +VERY_VERBOSE = 6 + + +_COVERSTATERESPONSE_COVERSTATE = _descriptor.EnumDescriptor( + name='CoverState', + full_name='CoverStateResponse.CoverState', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='OPEN', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CLOSED', index=1, number=1, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=1808, + serialized_end=1842, +) +_sym_db.RegisterEnumDescriptor(_COVERSTATERESPONSE_COVERSTATE) + +_COVERCOMMANDREQUEST_COVERCOMMAND = _descriptor.EnumDescriptor( + name='CoverCommand', + full_name='CoverCommandRequest.CoverCommand', + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name='OPEN', index=0, number=0, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='CLOSE', index=1, number=1, + serialized_options=None, + type=None), + _descriptor.EnumValueDescriptor( + name='STOP', index=2, number=2, + serialized_options=None, + type=None), + ], + containing_type=None, + serialized_options=None, + serialized_start=2375, + serialized_end=2420, +) +_sym_db.RegisterEnumDescriptor(_COVERCOMMANDREQUEST_COVERCOMMAND) + + +_HELLOREQUEST = _descriptor.Descriptor( + name='HelloRequest', + full_name='HelloRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='client_info', full_name='HelloRequest.client_info', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=13, + serialized_end=48, +) + + +_HELLORESPONSE = _descriptor.Descriptor( + name='HelloResponse', + full_name='HelloResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='api_version_major', full_name='HelloResponse.api_version_major', index=0, + number=1, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='api_version_minor', full_name='HelloResponse.api_version_minor', index=1, + number=2, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='server_info', full_name='HelloResponse.server_info', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=50, + serialized_end=140, +) + + +_CONNECTREQUEST = _descriptor.Descriptor( + name='ConnectRequest', + full_name='ConnectRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='password', full_name='ConnectRequest.password', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=142, + serialized_end=176, +) + + +_CONNECTRESPONSE = _descriptor.Descriptor( + name='ConnectResponse', + full_name='ConnectResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='invalid_password', full_name='ConnectResponse.invalid_password', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=178, + serialized_end=221, +) + + +_DISCONNECTREQUEST = _descriptor.Descriptor( + name='DisconnectRequest', + full_name='DisconnectRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=223, + serialized_end=242, +) + + +_DISCONNECTRESPONSE = _descriptor.Descriptor( + name='DisconnectResponse', + full_name='DisconnectResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=244, + serialized_end=264, +) + + +_PINGREQUEST = _descriptor.Descriptor( + name='PingRequest', + full_name='PingRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=266, + serialized_end=279, +) + + +_PINGRESPONSE = _descriptor.Descriptor( + name='PingResponse', + full_name='PingResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=281, + serialized_end=295, +) + + +_DEVICEINFOREQUEST = _descriptor.Descriptor( + name='DeviceInfoRequest', + full_name='DeviceInfoRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=297, + serialized_end=316, +) + + +_DEVICEINFORESPONSE = _descriptor.Descriptor( + name='DeviceInfoResponse', + full_name='DeviceInfoResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='uses_password', full_name='DeviceInfoResponse.uses_password', index=0, + number=1, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='name', full_name='DeviceInfoResponse.name', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='mac_address', full_name='DeviceInfoResponse.mac_address', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='esphome_core_version', full_name='DeviceInfoResponse.esphome_core_version', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='compilation_time', full_name='DeviceInfoResponse.compilation_time', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='model', full_name='DeviceInfoResponse.model', index=5, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='has_deep_sleep', full_name='DeviceInfoResponse.has_deep_sleep', index=6, + number=7, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=319, + serialized_end=492, +) + + +_LISTENTITIESREQUEST = _descriptor.Descriptor( + name='ListEntitiesRequest', + full_name='ListEntitiesRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=494, + serialized_end=515, +) + + +_LISTENTITIESBINARYSENSORRESPONSE = _descriptor.Descriptor( + name='ListEntitiesBinarySensorResponse', + full_name='ListEntitiesBinarySensorResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='object_id', full_name='ListEntitiesBinarySensorResponse.object_id', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='key', full_name='ListEntitiesBinarySensorResponse.key', index=1, + number=2, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='name', full_name='ListEntitiesBinarySensorResponse.name', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unique_id', full_name='ListEntitiesBinarySensorResponse.unique_id', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='device_class', full_name='ListEntitiesBinarySensorResponse.device_class', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='is_status_binary_sensor', full_name='ListEntitiesBinarySensorResponse.is_status_binary_sensor', index=5, + number=6, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=518, + serialized_end=672, +) + + +_LISTENTITIESCOVERRESPONSE = _descriptor.Descriptor( + name='ListEntitiesCoverResponse', + full_name='ListEntitiesCoverResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='object_id', full_name='ListEntitiesCoverResponse.object_id', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='key', full_name='ListEntitiesCoverResponse.key', index=1, + number=2, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='name', full_name='ListEntitiesCoverResponse.name', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unique_id', full_name='ListEntitiesCoverResponse.unique_id', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='is_optimistic', full_name='ListEntitiesCoverResponse.is_optimistic', index=4, + number=5, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=674, + serialized_end=789, +) + + +_LISTENTITIESFANRESPONSE = _descriptor.Descriptor( + name='ListEntitiesFanResponse', + full_name='ListEntitiesFanResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='object_id', full_name='ListEntitiesFanResponse.object_id', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='key', full_name='ListEntitiesFanResponse.key', index=1, + number=2, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='name', full_name='ListEntitiesFanResponse.name', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unique_id', full_name='ListEntitiesFanResponse.unique_id', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='supports_oscillation', full_name='ListEntitiesFanResponse.supports_oscillation', index=4, + number=5, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='supports_speed', full_name='ListEntitiesFanResponse.supports_speed', index=5, + number=6, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=792, + serialized_end=936, +) + + +_LISTENTITIESLIGHTRESPONSE = _descriptor.Descriptor( + name='ListEntitiesLightResponse', + full_name='ListEntitiesLightResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='object_id', full_name='ListEntitiesLightResponse.object_id', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='key', full_name='ListEntitiesLightResponse.key', index=1, + number=2, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='name', full_name='ListEntitiesLightResponse.name', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unique_id', full_name='ListEntitiesLightResponse.unique_id', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='supports_brightness', full_name='ListEntitiesLightResponse.supports_brightness', index=4, + number=5, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='supports_rgb', full_name='ListEntitiesLightResponse.supports_rgb', index=5, + number=6, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='supports_white_value', full_name='ListEntitiesLightResponse.supports_white_value', index=6, + number=7, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='supports_color_temperature', full_name='ListEntitiesLightResponse.supports_color_temperature', index=7, + number=8, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='min_mireds', full_name='ListEntitiesLightResponse.min_mireds', index=8, + number=9, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='max_mireds', full_name='ListEntitiesLightResponse.max_mireds', index=9, + number=10, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='effects', full_name='ListEntitiesLightResponse.effects', index=10, + number=11, type=9, cpp_type=9, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=939, + serialized_end=1205, +) + + +_LISTENTITIESSENSORRESPONSE = _descriptor.Descriptor( + name='ListEntitiesSensorResponse', + full_name='ListEntitiesSensorResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='object_id', full_name='ListEntitiesSensorResponse.object_id', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='key', full_name='ListEntitiesSensorResponse.key', index=1, + number=2, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='name', full_name='ListEntitiesSensorResponse.name', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unique_id', full_name='ListEntitiesSensorResponse.unique_id', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='icon', full_name='ListEntitiesSensorResponse.icon', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unit_of_measurement', full_name='ListEntitiesSensorResponse.unit_of_measurement', index=5, + number=6, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='accuracy_decimals', full_name='ListEntitiesSensorResponse.accuracy_decimals', index=6, + number=7, type=5, cpp_type=1, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1208, + serialized_end=1371, +) + + +_LISTENTITIESSWITCHRESPONSE = _descriptor.Descriptor( + name='ListEntitiesSwitchResponse', + full_name='ListEntitiesSwitchResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='object_id', full_name='ListEntitiesSwitchResponse.object_id', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='key', full_name='ListEntitiesSwitchResponse.key', index=1, + number=2, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='name', full_name='ListEntitiesSwitchResponse.name', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unique_id', full_name='ListEntitiesSwitchResponse.unique_id', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='icon', full_name='ListEntitiesSwitchResponse.icon', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='optimistic', full_name='ListEntitiesSwitchResponse.optimistic', index=5, + number=6, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1373, + serialized_end=1500, +) + + +_LISTENTITIESTEXTSENSORRESPONSE = _descriptor.Descriptor( + name='ListEntitiesTextSensorResponse', + full_name='ListEntitiesTextSensorResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='object_id', full_name='ListEntitiesTextSensorResponse.object_id', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='key', full_name='ListEntitiesTextSensorResponse.key', index=1, + number=2, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='name', full_name='ListEntitiesTextSensorResponse.name', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='unique_id', full_name='ListEntitiesTextSensorResponse.unique_id', index=3, + number=4, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='icon', full_name='ListEntitiesTextSensorResponse.icon', index=4, + number=5, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1502, + serialized_end=1613, +) + + +_LISTENTITIESDONERESPONSE = _descriptor.Descriptor( + name='ListEntitiesDoneResponse', + full_name='ListEntitiesDoneResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1615, + serialized_end=1641, +) + + +_SUBSCRIBESTATESREQUEST = _descriptor.Descriptor( + name='SubscribeStatesRequest', + full_name='SubscribeStatesRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1643, + serialized_end=1667, +) + + +_BINARYSENSORSTATERESPONSE = _descriptor.Descriptor( + name='BinarySensorStateResponse', + full_name='BinarySensorStateResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='BinarySensorStateResponse.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='state', full_name='BinarySensorStateResponse.state', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1669, + serialized_end=1724, +) + + +_COVERSTATERESPONSE = _descriptor.Descriptor( + name='CoverStateResponse', + full_name='CoverStateResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='CoverStateResponse.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='state', full_name='CoverStateResponse.state', index=1, + number=2, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _COVERSTATERESPONSE_COVERSTATE, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1726, + serialized_end=1842, +) + + +_FANSTATERESPONSE = _descriptor.Descriptor( + name='FanStateResponse', + full_name='FanStateResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='FanStateResponse.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='state', full_name='FanStateResponse.state', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oscillating', full_name='FanStateResponse.oscillating', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='speed', full_name='FanStateResponse.speed', index=3, + number=4, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1844, + serialized_end=1937, +) + + +_LIGHTSTATERESPONSE = _descriptor.Descriptor( + name='LightStateResponse', + full_name='LightStateResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='LightStateResponse.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='state', full_name='LightStateResponse.state', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='brightness', full_name='LightStateResponse.brightness', index=2, + number=3, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='red', full_name='LightStateResponse.red', index=3, + number=4, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='green', full_name='LightStateResponse.green', index=4, + number=5, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='blue', full_name='LightStateResponse.blue', index=5, + number=6, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='white', full_name='LightStateResponse.white', index=6, + number=7, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='color_temperature', full_name='LightStateResponse.color_temperature', index=7, + number=8, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='effect', full_name='LightStateResponse.effect', index=8, + number=9, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=1940, + serialized_end=2108, +) + + +_SENSORSTATERESPONSE = _descriptor.Descriptor( + name='SensorStateResponse', + full_name='SensorStateResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='SensorStateResponse.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='state', full_name='SensorStateResponse.state', index=1, + number=2, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2110, + serialized_end=2159, +) + + +_SWITCHSTATERESPONSE = _descriptor.Descriptor( + name='SwitchStateResponse', + full_name='SwitchStateResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='SwitchStateResponse.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='state', full_name='SwitchStateResponse.state', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2161, + serialized_end=2210, +) + + +_TEXTSENSORSTATERESPONSE = _descriptor.Descriptor( + name='TextSensorStateResponse', + full_name='TextSensorStateResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='TextSensorStateResponse.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='state', full_name='TextSensorStateResponse.state', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2212, + serialized_end=2265, +) + + +_COVERCOMMANDREQUEST = _descriptor.Descriptor( + name='CoverCommandRequest', + full_name='CoverCommandRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='CoverCommandRequest.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='has_state', full_name='CoverCommandRequest.has_state', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='command', full_name='CoverCommandRequest.command', index=2, + number=3, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + _COVERCOMMANDREQUEST_COVERCOMMAND, + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2268, + serialized_end=2420, +) + + +_FANCOMMANDREQUEST = _descriptor.Descriptor( + name='FanCommandRequest', + full_name='FanCommandRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='FanCommandRequest.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='has_state', full_name='FanCommandRequest.has_state', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='state', full_name='FanCommandRequest.state', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='has_speed', full_name='FanCommandRequest.has_speed', index=3, + number=4, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='speed', full_name='FanCommandRequest.speed', index=4, + number=5, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='has_oscillating', full_name='FanCommandRequest.has_oscillating', index=5, + number=6, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='oscillating', full_name='FanCommandRequest.oscillating', index=6, + number=7, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2423, + serialized_end=2580, +) + + +_LIGHTCOMMANDREQUEST = _descriptor.Descriptor( + name='LightCommandRequest', + full_name='LightCommandRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='LightCommandRequest.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='has_state', full_name='LightCommandRequest.has_state', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='state', full_name='LightCommandRequest.state', index=2, + number=3, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='has_brightness', full_name='LightCommandRequest.has_brightness', index=3, + number=4, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='brightness', full_name='LightCommandRequest.brightness', index=4, + number=5, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='has_rgb', full_name='LightCommandRequest.has_rgb', index=5, + number=6, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='red', full_name='LightCommandRequest.red', index=6, + number=7, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='green', full_name='LightCommandRequest.green', index=7, + number=8, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='blue', full_name='LightCommandRequest.blue', index=8, + number=9, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='has_white', full_name='LightCommandRequest.has_white', index=9, + number=10, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='white', full_name='LightCommandRequest.white', index=10, + number=11, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='has_color_temperature', full_name='LightCommandRequest.has_color_temperature', index=11, + number=12, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='color_temperature', full_name='LightCommandRequest.color_temperature', index=12, + number=13, type=2, cpp_type=6, label=1, + has_default_value=False, default_value=float(0), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='has_transition_length', full_name='LightCommandRequest.has_transition_length', index=13, + number=14, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='transition_length', full_name='LightCommandRequest.transition_length', index=14, + number=15, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='has_flash_length', full_name='LightCommandRequest.has_flash_length', index=15, + number=16, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='flash_length', full_name='LightCommandRequest.flash_length', index=16, + number=17, type=13, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='has_effect', full_name='LightCommandRequest.has_effect', index=17, + number=18, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='effect', full_name='LightCommandRequest.effect', index=18, + number=19, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2583, + serialized_end=2988, +) + + +_SWITCHCOMMANDREQUEST = _descriptor.Descriptor( + name='SwitchCommandRequest', + full_name='SwitchCommandRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='SwitchCommandRequest.key', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='state', full_name='SwitchCommandRequest.state', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=2990, + serialized_end=3040, +) + + +_SUBSCRIBELOGSREQUEST = _descriptor.Descriptor( + name='SubscribeLogsRequest', + full_name='SubscribeLogsRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='level', full_name='SubscribeLogsRequest.level', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='dump_config', full_name='SubscribeLogsRequest.dump_config', index=1, + number=2, type=8, cpp_type=7, label=1, + has_default_value=False, default_value=False, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3042, + serialized_end=3111, +) + + +_SUBSCRIBELOGSRESPONSE = _descriptor.Descriptor( + name='SubscribeLogsResponse', + full_name='SubscribeLogsResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='level', full_name='SubscribeLogsResponse.level', index=0, + number=1, type=14, cpp_type=8, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='tag', full_name='SubscribeLogsResponse.tag', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='message', full_name='SubscribeLogsResponse.message', index=2, + number=3, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3113, + serialized_end=3192, +) + + +_SUBSCRIBESERVICECALLSREQUEST = _descriptor.Descriptor( + name='SubscribeServiceCallsRequest', + full_name='SubscribeServiceCallsRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3194, + serialized_end=3224, +) + + +_SERVICECALLRESPONSE_DATAENTRY = _descriptor.Descriptor( + name='DataEntry', + full_name='ServiceCallResponse.DataEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='ServiceCallResponse.DataEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='ServiceCallResponse.DataEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3432, + serialized_end=3475, +) + +_SERVICECALLRESPONSE_DATATEMPLATEENTRY = _descriptor.Descriptor( + name='DataTemplateEntry', + full_name='ServiceCallResponse.DataTemplateEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='ServiceCallResponse.DataTemplateEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='ServiceCallResponse.DataTemplateEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3477, + serialized_end=3528, +) + +_SERVICECALLRESPONSE_VARIABLESENTRY = _descriptor.Descriptor( + name='VariablesEntry', + full_name='ServiceCallResponse.VariablesEntry', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='key', full_name='ServiceCallResponse.VariablesEntry.key', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='value', full_name='ServiceCallResponse.VariablesEntry.value', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=_b('8\001'), + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3530, + serialized_end=3578, +) + +_SERVICECALLRESPONSE = _descriptor.Descriptor( + name='ServiceCallResponse', + full_name='ServiceCallResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='service', full_name='ServiceCallResponse.service', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='data', full_name='ServiceCallResponse.data', index=1, + number=2, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='data_template', full_name='ServiceCallResponse.data_template', index=2, + number=3, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='variables', full_name='ServiceCallResponse.variables', index=3, + number=4, type=11, cpp_type=10, label=3, + has_default_value=False, default_value=[], + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[_SERVICECALLRESPONSE_DATAENTRY, _SERVICECALLRESPONSE_DATATEMPLATEENTRY, _SERVICECALLRESPONSE_VARIABLESENTRY, ], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3227, + serialized_end=3578, +) + + +_SUBSCRIBEHOMEASSISTANTSTATEREQUEST = _descriptor.Descriptor( + name='SubscribeHomeAssistantStateRequest', + full_name='SubscribeHomeAssistantStateRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='entity_id', full_name='SubscribeHomeAssistantStateRequest.entity_id', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3580, + serialized_end=3635, +) + + +_SUBSCRIBEHOMEASSISTANTSTATERESPONSE = _descriptor.Descriptor( + name='SubscribeHomeAssistantStateResponse', + full_name='SubscribeHomeAssistantStateResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='entity_id', full_name='SubscribeHomeAssistantStateResponse.entity_id', index=0, + number=1, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + _descriptor.FieldDescriptor( + name='state', full_name='SubscribeHomeAssistantStateResponse.state', index=1, + number=2, type=9, cpp_type=9, label=1, + has_default_value=False, default_value=_b("").decode('utf-8'), + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3637, + serialized_end=3708, +) + + +_GETTIMEREQUEST = _descriptor.Descriptor( + name='GetTimeRequest', + full_name='GetTimeRequest', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3710, + serialized_end=3726, +) + + +_GETTIMERESPONSE = _descriptor.Descriptor( + name='GetTimeResponse', + full_name='GetTimeResponse', + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name='epoch_seconds', full_name='GetTimeResponse.epoch_seconds', index=0, + number=1, type=7, cpp_type=3, label=1, + has_default_value=False, default_value=0, + message_type=None, enum_type=None, containing_type=None, + is_extension=False, extension_scope=None, + serialized_options=None, file=DESCRIPTOR), + ], + extensions=[ + ], + nested_types=[], + enum_types=[ + ], + serialized_options=None, + is_extendable=False, + syntax='proto3', + extension_ranges=[], + oneofs=[ + ], + serialized_start=3728, + serialized_end=3768, +) + +_COVERSTATERESPONSE.fields_by_name['state'].enum_type = _COVERSTATERESPONSE_COVERSTATE +_COVERSTATERESPONSE_COVERSTATE.containing_type = _COVERSTATERESPONSE +_FANSTATERESPONSE.fields_by_name['speed'].enum_type = _FANSPEED +_COVERCOMMANDREQUEST.fields_by_name['command'].enum_type = _COVERCOMMANDREQUEST_COVERCOMMAND +_COVERCOMMANDREQUEST_COVERCOMMAND.containing_type = _COVERCOMMANDREQUEST +_FANCOMMANDREQUEST.fields_by_name['speed'].enum_type = _FANSPEED +_SUBSCRIBELOGSREQUEST.fields_by_name['level'].enum_type = _LOGLEVEL +_SUBSCRIBELOGSRESPONSE.fields_by_name['level'].enum_type = _LOGLEVEL +_SERVICECALLRESPONSE_DATAENTRY.containing_type = _SERVICECALLRESPONSE +_SERVICECALLRESPONSE_DATATEMPLATEENTRY.containing_type = _SERVICECALLRESPONSE +_SERVICECALLRESPONSE_VARIABLESENTRY.containing_type = _SERVICECALLRESPONSE +_SERVICECALLRESPONSE.fields_by_name['data'].message_type = _SERVICECALLRESPONSE_DATAENTRY +_SERVICECALLRESPONSE.fields_by_name['data_template'].message_type = _SERVICECALLRESPONSE_DATATEMPLATEENTRY +_SERVICECALLRESPONSE.fields_by_name['variables'].message_type = _SERVICECALLRESPONSE_VARIABLESENTRY +DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST +DESCRIPTOR.message_types_by_name['HelloResponse'] = _HELLORESPONSE +DESCRIPTOR.message_types_by_name['ConnectRequest'] = _CONNECTREQUEST +DESCRIPTOR.message_types_by_name['ConnectResponse'] = _CONNECTRESPONSE +DESCRIPTOR.message_types_by_name['DisconnectRequest'] = _DISCONNECTREQUEST +DESCRIPTOR.message_types_by_name['DisconnectResponse'] = _DISCONNECTRESPONSE +DESCRIPTOR.message_types_by_name['PingRequest'] = _PINGREQUEST +DESCRIPTOR.message_types_by_name['PingResponse'] = _PINGRESPONSE +DESCRIPTOR.message_types_by_name['DeviceInfoRequest'] = _DEVICEINFOREQUEST +DESCRIPTOR.message_types_by_name['DeviceInfoResponse'] = _DEVICEINFORESPONSE +DESCRIPTOR.message_types_by_name['ListEntitiesRequest'] = _LISTENTITIESREQUEST +DESCRIPTOR.message_types_by_name['ListEntitiesBinarySensorResponse'] = _LISTENTITIESBINARYSENSORRESPONSE +DESCRIPTOR.message_types_by_name['ListEntitiesCoverResponse'] = _LISTENTITIESCOVERRESPONSE +DESCRIPTOR.message_types_by_name['ListEntitiesFanResponse'] = _LISTENTITIESFANRESPONSE +DESCRIPTOR.message_types_by_name['ListEntitiesLightResponse'] = _LISTENTITIESLIGHTRESPONSE +DESCRIPTOR.message_types_by_name['ListEntitiesSensorResponse'] = _LISTENTITIESSENSORRESPONSE +DESCRIPTOR.message_types_by_name['ListEntitiesSwitchResponse'] = _LISTENTITIESSWITCHRESPONSE +DESCRIPTOR.message_types_by_name['ListEntitiesTextSensorResponse'] = _LISTENTITIESTEXTSENSORRESPONSE +DESCRIPTOR.message_types_by_name['ListEntitiesDoneResponse'] = _LISTENTITIESDONERESPONSE +DESCRIPTOR.message_types_by_name['SubscribeStatesRequest'] = _SUBSCRIBESTATESREQUEST +DESCRIPTOR.message_types_by_name['BinarySensorStateResponse'] = _BINARYSENSORSTATERESPONSE +DESCRIPTOR.message_types_by_name['CoverStateResponse'] = _COVERSTATERESPONSE +DESCRIPTOR.message_types_by_name['FanStateResponse'] = _FANSTATERESPONSE +DESCRIPTOR.message_types_by_name['LightStateResponse'] = _LIGHTSTATERESPONSE +DESCRIPTOR.message_types_by_name['SensorStateResponse'] = _SENSORSTATERESPONSE +DESCRIPTOR.message_types_by_name['SwitchStateResponse'] = _SWITCHSTATERESPONSE +DESCRIPTOR.message_types_by_name['TextSensorStateResponse'] = _TEXTSENSORSTATERESPONSE +DESCRIPTOR.message_types_by_name['CoverCommandRequest'] = _COVERCOMMANDREQUEST +DESCRIPTOR.message_types_by_name['FanCommandRequest'] = _FANCOMMANDREQUEST +DESCRIPTOR.message_types_by_name['LightCommandRequest'] = _LIGHTCOMMANDREQUEST +DESCRIPTOR.message_types_by_name['SwitchCommandRequest'] = _SWITCHCOMMANDREQUEST +DESCRIPTOR.message_types_by_name['SubscribeLogsRequest'] = _SUBSCRIBELOGSREQUEST +DESCRIPTOR.message_types_by_name['SubscribeLogsResponse'] = _SUBSCRIBELOGSRESPONSE +DESCRIPTOR.message_types_by_name['SubscribeServiceCallsRequest'] = _SUBSCRIBESERVICECALLSREQUEST +DESCRIPTOR.message_types_by_name['ServiceCallResponse'] = _SERVICECALLRESPONSE +DESCRIPTOR.message_types_by_name['SubscribeHomeAssistantStateRequest'] = _SUBSCRIBEHOMEASSISTANTSTATEREQUEST +DESCRIPTOR.message_types_by_name['SubscribeHomeAssistantStateResponse'] = _SUBSCRIBEHOMEASSISTANTSTATERESPONSE +DESCRIPTOR.message_types_by_name['GetTimeRequest'] = _GETTIMEREQUEST +DESCRIPTOR.message_types_by_name['GetTimeResponse'] = _GETTIMERESPONSE +DESCRIPTOR.enum_types_by_name['FanSpeed'] = _FANSPEED +DESCRIPTOR.enum_types_by_name['LogLevel'] = _LOGLEVEL +_sym_db.RegisterFileDescriptor(DESCRIPTOR) + +HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), dict( + DESCRIPTOR = _HELLOREQUEST, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:HelloRequest) + )) +_sym_db.RegisterMessage(HelloRequest) + +HelloResponse = _reflection.GeneratedProtocolMessageType('HelloResponse', (_message.Message,), dict( + DESCRIPTOR = _HELLORESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:HelloResponse) + )) +_sym_db.RegisterMessage(HelloResponse) + +ConnectRequest = _reflection.GeneratedProtocolMessageType('ConnectRequest', (_message.Message,), dict( + DESCRIPTOR = _CONNECTREQUEST, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:ConnectRequest) + )) +_sym_db.RegisterMessage(ConnectRequest) + +ConnectResponse = _reflection.GeneratedProtocolMessageType('ConnectResponse', (_message.Message,), dict( + DESCRIPTOR = _CONNECTRESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:ConnectResponse) + )) +_sym_db.RegisterMessage(ConnectResponse) + +DisconnectRequest = _reflection.GeneratedProtocolMessageType('DisconnectRequest', (_message.Message,), dict( + DESCRIPTOR = _DISCONNECTREQUEST, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:DisconnectRequest) + )) +_sym_db.RegisterMessage(DisconnectRequest) + +DisconnectResponse = _reflection.GeneratedProtocolMessageType('DisconnectResponse', (_message.Message,), dict( + DESCRIPTOR = _DISCONNECTRESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:DisconnectResponse) + )) +_sym_db.RegisterMessage(DisconnectResponse) + +PingRequest = _reflection.GeneratedProtocolMessageType('PingRequest', (_message.Message,), dict( + DESCRIPTOR = _PINGREQUEST, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:PingRequest) + )) +_sym_db.RegisterMessage(PingRequest) + +PingResponse = _reflection.GeneratedProtocolMessageType('PingResponse', (_message.Message,), dict( + DESCRIPTOR = _PINGRESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:PingResponse) + )) +_sym_db.RegisterMessage(PingResponse) + +DeviceInfoRequest = _reflection.GeneratedProtocolMessageType('DeviceInfoRequest', (_message.Message,), dict( + DESCRIPTOR = _DEVICEINFOREQUEST, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:DeviceInfoRequest) + )) +_sym_db.RegisterMessage(DeviceInfoRequest) + +DeviceInfoResponse = _reflection.GeneratedProtocolMessageType('DeviceInfoResponse', (_message.Message,), dict( + DESCRIPTOR = _DEVICEINFORESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:DeviceInfoResponse) + )) +_sym_db.RegisterMessage(DeviceInfoResponse) + +ListEntitiesRequest = _reflection.GeneratedProtocolMessageType('ListEntitiesRequest', (_message.Message,), dict( + DESCRIPTOR = _LISTENTITIESREQUEST, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:ListEntitiesRequest) + )) +_sym_db.RegisterMessage(ListEntitiesRequest) + +ListEntitiesBinarySensorResponse = _reflection.GeneratedProtocolMessageType('ListEntitiesBinarySensorResponse', (_message.Message,), dict( + DESCRIPTOR = _LISTENTITIESBINARYSENSORRESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:ListEntitiesBinarySensorResponse) + )) +_sym_db.RegisterMessage(ListEntitiesBinarySensorResponse) + +ListEntitiesCoverResponse = _reflection.GeneratedProtocolMessageType('ListEntitiesCoverResponse', (_message.Message,), dict( + DESCRIPTOR = _LISTENTITIESCOVERRESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:ListEntitiesCoverResponse) + )) +_sym_db.RegisterMessage(ListEntitiesCoverResponse) + +ListEntitiesFanResponse = _reflection.GeneratedProtocolMessageType('ListEntitiesFanResponse', (_message.Message,), dict( + DESCRIPTOR = _LISTENTITIESFANRESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:ListEntitiesFanResponse) + )) +_sym_db.RegisterMessage(ListEntitiesFanResponse) + +ListEntitiesLightResponse = _reflection.GeneratedProtocolMessageType('ListEntitiesLightResponse', (_message.Message,), dict( + DESCRIPTOR = _LISTENTITIESLIGHTRESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:ListEntitiesLightResponse) + )) +_sym_db.RegisterMessage(ListEntitiesLightResponse) + +ListEntitiesSensorResponse = _reflection.GeneratedProtocolMessageType('ListEntitiesSensorResponse', (_message.Message,), dict( + DESCRIPTOR = _LISTENTITIESSENSORRESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:ListEntitiesSensorResponse) + )) +_sym_db.RegisterMessage(ListEntitiesSensorResponse) + +ListEntitiesSwitchResponse = _reflection.GeneratedProtocolMessageType('ListEntitiesSwitchResponse', (_message.Message,), dict( + DESCRIPTOR = _LISTENTITIESSWITCHRESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:ListEntitiesSwitchResponse) + )) +_sym_db.RegisterMessage(ListEntitiesSwitchResponse) + +ListEntitiesTextSensorResponse = _reflection.GeneratedProtocolMessageType('ListEntitiesTextSensorResponse', (_message.Message,), dict( + DESCRIPTOR = _LISTENTITIESTEXTSENSORRESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:ListEntitiesTextSensorResponse) + )) +_sym_db.RegisterMessage(ListEntitiesTextSensorResponse) + +ListEntitiesDoneResponse = _reflection.GeneratedProtocolMessageType('ListEntitiesDoneResponse', (_message.Message,), dict( + DESCRIPTOR = _LISTENTITIESDONERESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:ListEntitiesDoneResponse) + )) +_sym_db.RegisterMessage(ListEntitiesDoneResponse) + +SubscribeStatesRequest = _reflection.GeneratedProtocolMessageType('SubscribeStatesRequest', (_message.Message,), dict( + DESCRIPTOR = _SUBSCRIBESTATESREQUEST, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:SubscribeStatesRequest) + )) +_sym_db.RegisterMessage(SubscribeStatesRequest) + +BinarySensorStateResponse = _reflection.GeneratedProtocolMessageType('BinarySensorStateResponse', (_message.Message,), dict( + DESCRIPTOR = _BINARYSENSORSTATERESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:BinarySensorStateResponse) + )) +_sym_db.RegisterMessage(BinarySensorStateResponse) + +CoverStateResponse = _reflection.GeneratedProtocolMessageType('CoverStateResponse', (_message.Message,), dict( + DESCRIPTOR = _COVERSTATERESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:CoverStateResponse) + )) +_sym_db.RegisterMessage(CoverStateResponse) + +FanStateResponse = _reflection.GeneratedProtocolMessageType('FanStateResponse', (_message.Message,), dict( + DESCRIPTOR = _FANSTATERESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:FanStateResponse) + )) +_sym_db.RegisterMessage(FanStateResponse) + +LightStateResponse = _reflection.GeneratedProtocolMessageType('LightStateResponse', (_message.Message,), dict( + DESCRIPTOR = _LIGHTSTATERESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:LightStateResponse) + )) +_sym_db.RegisterMessage(LightStateResponse) + +SensorStateResponse = _reflection.GeneratedProtocolMessageType('SensorStateResponse', (_message.Message,), dict( + DESCRIPTOR = _SENSORSTATERESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:SensorStateResponse) + )) +_sym_db.RegisterMessage(SensorStateResponse) + +SwitchStateResponse = _reflection.GeneratedProtocolMessageType('SwitchStateResponse', (_message.Message,), dict( + DESCRIPTOR = _SWITCHSTATERESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:SwitchStateResponse) + )) +_sym_db.RegisterMessage(SwitchStateResponse) + +TextSensorStateResponse = _reflection.GeneratedProtocolMessageType('TextSensorStateResponse', (_message.Message,), dict( + DESCRIPTOR = _TEXTSENSORSTATERESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:TextSensorStateResponse) + )) +_sym_db.RegisterMessage(TextSensorStateResponse) + +CoverCommandRequest = _reflection.GeneratedProtocolMessageType('CoverCommandRequest', (_message.Message,), dict( + DESCRIPTOR = _COVERCOMMANDREQUEST, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:CoverCommandRequest) + )) +_sym_db.RegisterMessage(CoverCommandRequest) + +FanCommandRequest = _reflection.GeneratedProtocolMessageType('FanCommandRequest', (_message.Message,), dict( + DESCRIPTOR = _FANCOMMANDREQUEST, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:FanCommandRequest) + )) +_sym_db.RegisterMessage(FanCommandRequest) + +LightCommandRequest = _reflection.GeneratedProtocolMessageType('LightCommandRequest', (_message.Message,), dict( + DESCRIPTOR = _LIGHTCOMMANDREQUEST, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:LightCommandRequest) + )) +_sym_db.RegisterMessage(LightCommandRequest) + +SwitchCommandRequest = _reflection.GeneratedProtocolMessageType('SwitchCommandRequest', (_message.Message,), dict( + DESCRIPTOR = _SWITCHCOMMANDREQUEST, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:SwitchCommandRequest) + )) +_sym_db.RegisterMessage(SwitchCommandRequest) + +SubscribeLogsRequest = _reflection.GeneratedProtocolMessageType('SubscribeLogsRequest', (_message.Message,), dict( + DESCRIPTOR = _SUBSCRIBELOGSREQUEST, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:SubscribeLogsRequest) + )) +_sym_db.RegisterMessage(SubscribeLogsRequest) + +SubscribeLogsResponse = _reflection.GeneratedProtocolMessageType('SubscribeLogsResponse', (_message.Message,), dict( + DESCRIPTOR = _SUBSCRIBELOGSRESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:SubscribeLogsResponse) + )) +_sym_db.RegisterMessage(SubscribeLogsResponse) + +SubscribeServiceCallsRequest = _reflection.GeneratedProtocolMessageType('SubscribeServiceCallsRequest', (_message.Message,), dict( + DESCRIPTOR = _SUBSCRIBESERVICECALLSREQUEST, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:SubscribeServiceCallsRequest) + )) +_sym_db.RegisterMessage(SubscribeServiceCallsRequest) + +ServiceCallResponse = _reflection.GeneratedProtocolMessageType('ServiceCallResponse', (_message.Message,), dict( + + DataEntry = _reflection.GeneratedProtocolMessageType('DataEntry', (_message.Message,), dict( + DESCRIPTOR = _SERVICECALLRESPONSE_DATAENTRY, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:ServiceCallResponse.DataEntry) + )) + , + + DataTemplateEntry = _reflection.GeneratedProtocolMessageType('DataTemplateEntry', (_message.Message,), dict( + DESCRIPTOR = _SERVICECALLRESPONSE_DATATEMPLATEENTRY, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:ServiceCallResponse.DataTemplateEntry) + )) + , + + VariablesEntry = _reflection.GeneratedProtocolMessageType('VariablesEntry', (_message.Message,), dict( + DESCRIPTOR = _SERVICECALLRESPONSE_VARIABLESENTRY, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:ServiceCallResponse.VariablesEntry) + )) + , + DESCRIPTOR = _SERVICECALLRESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:ServiceCallResponse) + )) +_sym_db.RegisterMessage(ServiceCallResponse) +_sym_db.RegisterMessage(ServiceCallResponse.DataEntry) +_sym_db.RegisterMessage(ServiceCallResponse.DataTemplateEntry) +_sym_db.RegisterMessage(ServiceCallResponse.VariablesEntry) + +SubscribeHomeAssistantStateRequest = _reflection.GeneratedProtocolMessageType('SubscribeHomeAssistantStateRequest', (_message.Message,), dict( + DESCRIPTOR = _SUBSCRIBEHOMEASSISTANTSTATEREQUEST, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:SubscribeHomeAssistantStateRequest) + )) +_sym_db.RegisterMessage(SubscribeHomeAssistantStateRequest) + +SubscribeHomeAssistantStateResponse = _reflection.GeneratedProtocolMessageType('SubscribeHomeAssistantStateResponse', (_message.Message,), dict( + DESCRIPTOR = _SUBSCRIBEHOMEASSISTANTSTATERESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:SubscribeHomeAssistantStateResponse) + )) +_sym_db.RegisterMessage(SubscribeHomeAssistantStateResponse) + +GetTimeRequest = _reflection.GeneratedProtocolMessageType('GetTimeRequest', (_message.Message,), dict( + DESCRIPTOR = _GETTIMEREQUEST, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:GetTimeRequest) + )) +_sym_db.RegisterMessage(GetTimeRequest) + +GetTimeResponse = _reflection.GeneratedProtocolMessageType('GetTimeResponse', (_message.Message,), dict( + DESCRIPTOR = _GETTIMERESPONSE, + __module__ = 'api_pb2' + # @@protoc_insertion_point(class_scope:GetTimeResponse) + )) +_sym_db.RegisterMessage(GetTimeResponse) + + +_SERVICECALLRESPONSE_DATAENTRY._options = None +_SERVICECALLRESPONSE_DATATEMPLATEENTRY._options = None +_SERVICECALLRESPONSE_VARIABLESENTRY._options = None +# @@protoc_insertion_point(module_scope) diff --git a/esphomeyaml/api/client.py b/esphomeyaml/api/client.py new file mode 100644 index 0000000000..a3fe23e7ee --- /dev/null +++ b/esphomeyaml/api/client.py @@ -0,0 +1,474 @@ +from datetime import datetime +import functools +import logging +import socket +import threading +import time + +# pylint: disable=unused-import +from typing import Optional # noqa +from google.protobuf import message + +from esphomeyaml import const +import esphomeyaml.api.api_pb2 as pb +from esphomeyaml.const import CONF_PASSWORD, CONF_PORT +from esphomeyaml.core import EsphomeyamlError +from esphomeyaml.helpers import resolve_ip_address +from esphomeyaml.util import safe_print + +_LOGGER = logging.getLogger(__name__) + + +class APIConnectionError(EsphomeyamlError): + pass + + +MESSAGE_TYPE_TO_PROTO = { + 1: pb.HelloRequest, + 2: pb.HelloResponse, + 3: pb.ConnectRequest, + 4: pb.ConnectResponse, + 5: pb.DisconnectRequest, + 6: pb.DisconnectResponse, + 7: pb.PingRequest, + 8: pb.PingResponse, + 9: pb.DeviceInfoRequest, + 10: pb.DeviceInfoResponse, + 11: pb.ListEntitiesRequest, + 12: pb.ListEntitiesBinarySensorResponse, + 13: pb.ListEntitiesCoverResponse, + 14: pb.ListEntitiesFanResponse, + 15: pb.ListEntitiesLightResponse, + 16: pb.ListEntitiesSensorResponse, + 17: pb.ListEntitiesSwitchResponse, + 18: pb.ListEntitiesTextSensorResponse, + 19: pb.ListEntitiesDoneResponse, + 20: pb.SubscribeStatesRequest, + 21: pb.BinarySensorStateResponse, + 22: pb.CoverStateResponse, + 23: pb.FanStateResponse, + 24: pb.LightStateResponse, + 25: pb.SensorStateResponse, + 26: pb.SwitchStateResponse, + 27: pb.TextSensorStateResponse, + 28: pb.SubscribeLogsRequest, + 29: pb.SubscribeLogsResponse, + 30: pb.CoverCommandRequest, + 31: pb.FanCommandRequest, + 32: pb.LightCommandRequest, + 33: pb.SwitchCommandRequest, + 34: pb.SubscribeServiceCallsRequest, + 35: pb.ServiceCallResponse, + 36: pb.GetTimeRequest, + 37: pb.GetTimeResponse, +} + + +def _varuint_to_bytes(value): + if value <= 0x7F: + return chr(value) + + ret = bytes() + while value: + temp = value & 0x7F + value >>= 7 + if value: + ret += chr(temp | 0x80) + else: + ret += chr(temp) + + return ret + + +def _bytes_to_varuint(value): + result = 0 + bitpos = 0 + for c in value: + val = ord(c) + result |= (val & 0x7F) << bitpos + bitpos += 7 + if (val & 0x80) == 0: + return result + return None + + +# pylint: disable=too-many-instance-attributes,not-callable +class APIClient(threading.Thread): + def __init__(self, address, port, password): + threading.Thread.__init__(self) + self._address = address # type: str + self._port = port # type: int + self._password = password # type: Optional[str] + self._socket = None # type: Optional[socket.socket] + self._connected = False + self._authenticated = False + self._message_handlers = [] + self._keepalive = 5 + self._ping_timer = None + self._refresh_ping() + + self.on_disconnect = None + self.on_connect = None + self.on_login = None + self.auto_reconnect = False + self._running = False + self._stop_event = threading.Event() + self._socket_open = False + + @property + def stopped(self): + return self._stop_event.is_set() + + def _refresh_ping(self): + if self._ping_timer is not None: + self._ping_timer.cancel() + self._ping_timer = None + + def func(): + self._ping_timer = None + + if self._connected: + try: + self.ping() + except APIConnectionError: + self._on_error() + self._refresh_ping() + + self._ping_timer = threading.Timer(self._keepalive, func) + self._ping_timer.start() + + def stop(self, force=False): + if self.stopped: + raise ValueError + + if self._connected and not force: + try: + self.disconnect() + except APIConnectionError: + pass + if self._socket is not None: + self._socket.close() + self._socket = None + + self._stop_event.set() + if self._ping_timer is not None: + self._ping_timer.cancel() + self._ping_timer = None + if not force: + self.join() + + def connect(self): + if not self._running: + raise APIConnectionError("You need to call start() first!") + + if self._connected: + raise APIConnectionError("Already connected!") + + self._message_handlers = [] + self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self._socket.settimeout(10.0) + self._socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) + + try: + ip = resolve_ip_address(self._address) + except EsphomeyamlError as err: + _LOGGER.warning("Error resolving IP address of %s. Is it connected to WiFi?", + self._address) + _LOGGER.warning("(If this error persists, please set a static IP address: " + "https://esphomelib.com/esphomeyaml/components/wifi.html#manual-ips)") + raise APIConnectionError(err) + + _LOGGER.info("Connecting to %s:%s (%s)", self._address, self._port, ip) + try: + self._socket.connect((ip, self._port)) + except socket.error as err: + self._on_error() + raise APIConnectionError("Error connecting to {}: {}".format(ip, err)) + self._socket_open = True + + self._socket.settimeout(0.1) + + hello = pb.HelloRequest() + hello.client_info = 'esphomeyaml v{}'.format(const.__version__) + try: + resp = self._send_message_await_response(hello, pb.HelloResponse) + except APIConnectionError as err: + self._on_error() + raise err + _LOGGER.debug("Successfully connected to %s ('%s' API=%s.%s)", self._address, + resp.server_info, resp.api_version_major, resp.api_version_minor) + self._connected = True + if self.on_connect is not None: + self.on_connect() + + def _check_connected(self): + if not self._connected: + self._on_error() + raise APIConnectionError("Must be connected!") + + def login(self): + self._check_connected() + if self._authenticated: + raise APIConnectionError("Already logged in!") + + connect = pb.ConnectRequest() + if self._password is not None: + connect.password = self._password + resp = self._send_message_await_response(connect, pb.ConnectResponse) + if resp.invalid_password: + raise APIConnectionError("Invalid password!") + + self._authenticated = True + if self.on_login is not None: + self.on_login() + + def _on_error(self): + if self._connected and self.on_disconnect is not None: + self.on_disconnect() + + if self._socket is not None: + self._socket.close() + self._socket = None + self._socket_open = False + + self._connected = False + self._authenticated = False + + def _write(self, data): # type: (bytes) -> None + _LOGGER.debug("Write: %s", ' '.join('{:02X}'.format(ord(x)) for x in data)) + try: + self._socket.sendall(data) + except socket.error as err: + self._on_error() + raise APIConnectionError("Error while writing data: {}".format(err)) + + def _send_message(self, msg): + # type: (message.Message) -> None + for message_type, klass in MESSAGE_TYPE_TO_PROTO.iteritems(): + if isinstance(msg, klass): + break + else: + raise ValueError + + encoded = msg.SerializeToString() + _LOGGER.debug("Sending %s: %s", type(message), unicode(message)) + req = chr(0x00) + req += _varuint_to_bytes(len(encoded)) + req += _varuint_to_bytes(message_type) + req += encoded + self._write(req) + self._refresh_ping() + + def _send_message_await_response_complex(self, send_msg, do_append, do_stop, timeout=1): + event = threading.Event() + responses = [] + + def on_message(resp): + if do_append(resp): + responses.append(resp) + if do_stop(resp): + event.set() + + self._message_handlers.append(on_message) + self._send_message(send_msg) + ret = event.wait(timeout) + try: + self._message_handlers.remove(on_message) + except ValueError: + pass + if not ret: + raise APIConnectionError("Timeout while waiting for message response!") + return responses + + def _send_message_await_response(self, send_msg, response_type, timeout=1): + def is_response(msg): + return isinstance(msg, response_type) + + return self._send_message_await_response_complex(send_msg, is_response, is_response, + timeout)[0] + + def device_info(self): + self._check_connected() + return self._send_message_await_response(pb.DeviceInfoRequest(), pb.DeviceInfoResponse) + + def ping(self): + self._check_connected() + return self._send_message_await_response(pb.PingRequest(), pb.PingResponse) + + def disconnect(self): + self._check_connected() + + try: + self._send_message_await_response(pb.DisconnectRequest(), pb.DisconnectResponse) + except APIConnectionError: + pass + if self._socket is not None: + self._socket.close() + self._socket = None + self._socket_open = False + self._connected = False + if self.on_disconnect is not None: + self.on_disconnect() + + def _check_authenticated(self): + if not self._authenticated: + raise APIConnectionError("Must login first!") + + def subscribe_logs(self, on_log, log_level=None, dump_config=False): + self._check_authenticated() + + def on_msg(msg): + if isinstance(msg, pb.SubscribeLogsResponse): + on_log(msg) + + self._message_handlers.append(on_msg) + req = pb.SubscribeLogsRequest(dump_config=dump_config) + if log_level is not None: + req.level = log_level + self._send_message(req) + + def _recv(self, amount): + ret = bytes() + if amount == 0: + return ret + + while len(ret) < amount: + if self.stopped: + raise APIConnectionError("Stopped!") + if self._socket is None or not self._socket_open: + raise APIConnectionError("No socket!") + try: + val = self._socket.recv(amount - len(ret)) + except socket.timeout: + continue + except socket.error as err: + raise APIConnectionError("Error while receiving data: {}".format(err)) + ret += val + return ret + + def _recv_varint(self): + raw = bytes() + while not raw or ord(raw[-1]) & 0x80: + raw += self._recv(1) + return _bytes_to_varuint(raw) + + def _run_once(self): + if self._socket is None or not self._socket_open: + time.sleep(0.1) + return + + # Preamble + if ord(self._recv(1)[0]) != 0x00: + raise APIConnectionError("Invalid preamble") + + length = self._recv_varint() + msg_type = self._recv_varint() + + raw_msg = self._recv(length) + if msg_type not in MESSAGE_TYPE_TO_PROTO: + _LOGGER.debug("Skipping message type %s", msg_type) + return + + msg = MESSAGE_TYPE_TO_PROTO[msg_type]() + msg.ParseFromString(raw_msg) + _LOGGER.debug("Got message of type %s: %s", type(msg), msg) + for msg_handler in self._message_handlers[:]: + msg_handler(msg) + self._handle_internal_messages(msg) + self._refresh_ping() + + def run(self): + self._running = True + while not self.stopped: + try: + self._run_once() + except APIConnectionError as err: + if self.stopped: + break + if self._connected: + _LOGGER.error("Error while reading incoming messages: %s", err) + self._on_error() + self._running = False + + def _handle_internal_messages(self, msg): + if isinstance(msg, pb.DisconnectRequest): + self._send_message(pb.DisconnectResponse()) + if self._socket is not None: + self._socket.close() + self._socket = None + self._connected = False + self._socket_open = False + if self.on_disconnect is not None: + self.on_disconnect() + elif isinstance(msg, pb.PingRequest): + self._send_message(pb.PingResponse()) + elif isinstance(msg, pb.GetTimeRequest): + resp = pb.GetTimeResponse() + resp.epoch_seconds = int(time.time()) + self._send_message(resp) + + +def run_logs(config, address): + conf = config['api'] + port = conf[CONF_PORT] + password = conf[CONF_PASSWORD] + _LOGGER.info("Starting log output from %s using esphomelib API", address) + + cli = APIClient(address, port, password) + stopping = False + retry_timer = [] + + def try_connect(tries=0, is_disconnect=True): + if stopping: + return + + if is_disconnect: + _LOGGER.warning(u"Disconnected from API.") + + while retry_timer: + retry_timer.pop(0).cancel() + + error = None + try: + cli.connect() + cli.login() + except APIConnectionError as error: + pass + + if error is None: + _LOGGER.info("Successfully connected to %s", address) + return + + wait_time = min(2**tries, 300) + _LOGGER.warning(u"Couldn't connect to API. Trying to reconnect in %s seconds", wait_time) + timer = threading.Timer(wait_time, functools.partial(try_connect, tries + 1, is_disconnect)) + timer.start() + retry_timer.append(timer) + + def on_log(msg): + time_ = datetime.now().time().strftime(u'[%H:%M:%S]') + safe_print(time_ + msg.message) + + has_connects = [] + + def on_login(): + try: + cli.subscribe_logs(on_log, dump_config=not has_connects) + has_connects.append(True) + except APIConnectionError: + cli.disconnect() + + cli.on_disconnect = try_connect + cli.on_login = on_login + cli.start() + + try: + try_connect(is_disconnect=False) + while True: + time.sleep(1) + except KeyboardInterrupt: + stopping = True + cli.stop(True) + while retry_timer: + retry_timer.pop(0).cancel() + return 0 diff --git a/esphomeyaml/automation.py b/esphomeyaml/automation.py index 74442d78ce..9e0539fc62 100644 --- a/esphomeyaml/automation.py +++ b/esphomeyaml/automation.py @@ -27,7 +27,7 @@ def maybe_simple_id(*validators): def validate_recursive_condition(value): is_list = isinstance(value, list) - value = cv.ensure_list(value)[:] + value = cv.ensure_list()(value)[:] for i, item in enumerate(value): path = [i] if is_list else [] item = copy.deepcopy(item) @@ -61,7 +61,8 @@ def validate_recursive_condition(value): def validate_recursive_action(value): is_list = isinstance(value, list) - value = cv.ensure_list(value)[:] + if not is_list: + value = [value] for i, item in enumerate(value): path = [i] if is_list else [] item = copy.deepcopy(item) diff --git a/esphomeyaml/components/api.py b/esphomeyaml/components/api.py new file mode 100644 index 0000000000..37b9272cbb --- /dev/null +++ b/esphomeyaml/components/api.py @@ -0,0 +1,85 @@ +import voluptuous as vol + +from esphomeyaml.automation import ACTION_REGISTRY +import esphomeyaml.config_validation as cv +from esphomeyaml.const import CONF_DATA, CONF_DATA_TEMPLATE, CONF_ID, CONF_PASSWORD, CONF_PORT, \ + CONF_SERVICE, CONF_VARIABLES +from esphomeyaml.core import CORE +from esphomeyaml.cpp_generator import ArrayInitializer, Pvariable, add, get_variable, process_lambda +from esphomeyaml.cpp_helpers import setup_component +from esphomeyaml.cpp_types import Action, App, Component, StoringController, esphomelib_ns + +api_ns = esphomelib_ns.namespace('api') +APIServer = api_ns.class_('APIServer', Component, StoringController) +HomeAssistantServiceCallAction = api_ns.class_('HomeAssistantServiceCallAction', Action) +KeyValuePair = api_ns.class_('KeyValuePair') +TemplatableKeyValuePair = api_ns.class_('TemplatableKeyValuePair') + +CONFIG_SCHEMA = vol.Schema({ + cv.GenerateID(): cv.declare_variable_id(APIServer), + vol.Optional(CONF_PORT, default=6053): cv.port, + vol.Optional(CONF_PASSWORD, default=''): cv.string_strict, +}).extend(cv.COMPONENT_SCHEMA.schema) + + +def to_code(config): + rhs = App.init_api_server() + api = Pvariable(config[CONF_ID], rhs) + + if config[CONF_PORT] != 6053: + add(api.set_port(config[CONF_PORT])) + if config.get(CONF_PASSWORD): + add(api.set_password(config[CONF_PASSWORD])) + + setup_component(api, config) + + +BUILD_FLAGS = '-DUSE_API' + + +def lib_deps(config): + if CORE.is_esp32: + return 'AsyncTCP@1.0.1' + elif CORE.is_esp8266: + return 'ESPAsyncTCP@1.1.3' + raise NotImplementedError + + +CONF_HOMEASSISTANT_SERVICE = 'homeassistant.service' +LOGGER_LOG_ACTION_SCHEMA = vol.Schema({ + cv.GenerateID(): cv.use_variable_id(APIServer), + vol.Required(CONF_SERVICE): cv.string, + vol.Optional(CONF_DATA): vol.Schema({ + cv.string: cv.string, + }), + vol.Optional(CONF_DATA_TEMPLATE): vol.Schema({ + cv.string: cv.string, + }), + vol.Optional(CONF_VARIABLES): vol.Schema({ + cv.string: cv.lambda_, + }), +}) + + +@ACTION_REGISTRY.register(CONF_HOMEASSISTANT_SERVICE, LOGGER_LOG_ACTION_SCHEMA) +def homeassistant_service_to_code(config, action_id, arg_type, template_arg): + for var in get_variable(config[CONF_ID]): + yield None + rhs = var.make_home_assistant_service_call_action(template_arg) + type = HomeAssistantServiceCallAction.template(arg_type) + act = Pvariable(action_id, rhs, type=type) + add(act.set_service(config[CONF_SERVICE])) + if CONF_DATA in config: + datas = [KeyValuePair(k, v) for k, v in config[CONF_DATA].items()] + add(act.set_data(ArrayInitializer(*datas))) + if CONF_DATA_TEMPLATE in config: + datas = [KeyValuePair(k, v) for k, v in config[CONF_DATA_TEMPLATE].items()] + add(act.set_data_template(ArrayInitializer(*datas))) + if CONF_VARIABLES in config: + datas = [] + for key, value in config[CONF_VARIABLES].items(): + for value_ in process_lambda(value, []): + yield None + datas.append(TemplatableKeyValuePair(key, value_)) + add(act.set_variables(ArrayInitializer(*datas))) + yield act diff --git a/esphomeyaml/components/binary_sensor/__init__.py b/esphomeyaml/components/binary_sensor/__init__.py index bac36e2f03..a79a396c50 100644 --- a/esphomeyaml/components/binary_sensor/__init__.py +++ b/esphomeyaml/components/binary_sensor/__init__.py @@ -9,7 +9,7 @@ from esphomeyaml.const import CONF_DELAYED_OFF, CONF_DELAYED_ON, CONF_DEVICE_CLA CONF_HEARTBEAT, CONF_ID, CONF_INTERNAL, CONF_INVALID_COOLDOWN, CONF_INVERT, CONF_INVERTED, \ CONF_LAMBDA, CONF_MAX_LENGTH, CONF_MIN_LENGTH, CONF_MQTT_ID, CONF_ON_CLICK, \ CONF_ON_DOUBLE_CLICK, CONF_ON_MULTI_CLICK, CONF_ON_PRESS, CONF_ON_RELEASE, CONF_STATE, \ - CONF_TIMING, CONF_TRIGGER_ID + CONF_TIMING, CONF_TRIGGER_ID, CONF_ON_STATE from esphomeyaml.core import CORE from esphomeyaml.cpp_generator import process_lambda, ArrayInitializer, add, Pvariable, \ StructInitializer, get_variable @@ -38,6 +38,7 @@ ClickTrigger = binary_sensor_ns.class_('ClickTrigger', Trigger.template(NoArg)) DoubleClickTrigger = binary_sensor_ns.class_('DoubleClickTrigger', Trigger.template(NoArg)) MultiClickTrigger = binary_sensor_ns.class_('MultiClickTrigger', Trigger.template(NoArg), Component) MultiClickTriggerEvent = binary_sensor_ns.struct('MultiClickTriggerEvent') +StateTrigger = binary_sensor_ns.class_('StateTrigger', Trigger.template(bool_)) # Condition BinarySensorCondition = binary_sensor_ns.class_('BinarySensorCondition', Condition) @@ -53,13 +54,13 @@ LambdaFilter = binary_sensor_ns.class_('LambdaFilter', Filter) FILTER_KEYS = [CONF_INVERT, CONF_DELAYED_ON, CONF_DELAYED_OFF, CONF_LAMBDA, CONF_HEARTBEAT] -FILTERS_SCHEMA = vol.All(cv.ensure_list, [vol.All({ +FILTERS_SCHEMA = cv.ensure_list({ vol.Optional(CONF_INVERT): None, vol.Optional(CONF_DELAYED_ON): cv.positive_time_period_milliseconds, vol.Optional(CONF_DELAYED_OFF): cv.positive_time_period_milliseconds, vol.Optional(CONF_HEARTBEAT): cv.positive_time_period_milliseconds, vol.Optional(CONF_LAMBDA): cv.lambda_, -}, cv.has_exactly_one_key(*FILTER_KEYS))]) +}, cv.has_exactly_one_key(*FILTER_KEYS)) MULTI_CLICK_TIMING_SCHEMA = vol.Schema({ vol.Optional(CONF_STATE): cv.boolean, @@ -181,6 +182,9 @@ BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({ validate_multi_click_timing), vol.Optional(CONF_INVALID_COOLDOWN): cv.positive_time_period_milliseconds, }), + vol.Optional(CONF_ON_STATE): automation.validate_automation({ + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(StateTrigger), + }), vol.Optional(CONF_INVERTED): cv.invalid( "The inverted binary_sensor property has been replaced by the " @@ -268,6 +272,11 @@ def setup_binary_sensor_core_(binary_sensor_var, mqtt_var, config): add(trigger.set_invalid_cooldown(conf[CONF_INVALID_COOLDOWN])) automation.build_automation(trigger, NoArg, conf) + for conf in config.get(CONF_ON_STATE, []): + rhs = binary_sensor_var.make_state_trigger() + trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs) + automation.build_automation(trigger, bool_, conf) + setup_mqtt_component(mqtt_var, config) diff --git a/esphomeyaml/components/binary_sensor/custom.py b/esphomeyaml/components/binary_sensor/custom.py index 8fc3aa13c1..c170793b99 100644 --- a/esphomeyaml/components/binary_sensor/custom.py +++ b/esphomeyaml/components/binary_sensor/custom.py @@ -13,9 +13,9 @@ PLATFORM_SCHEMA = binary_sensor.PLATFORM_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(CustomBinarySensorConstructor), vol.Required(CONF_LAMBDA): cv.lambda_, vol.Required(CONF_BINARY_SENSORS): - vol.All(cv.ensure_list, [binary_sensor.BINARY_SENSOR_SCHEMA.extend({ + cv.ensure_list(binary_sensor.BINARY_SENSOR_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(binary_sensor.BinarySensor), - })]), + })), }) diff --git a/esphomeyaml/components/binary_sensor/status.py b/esphomeyaml/components/binary_sensor/status.py index 3187de4353..93e11dd24b 100644 --- a/esphomeyaml/components/binary_sensor/status.py +++ b/esphomeyaml/components/binary_sensor/status.py @@ -5,7 +5,6 @@ from esphomeyaml.cpp_generator import variable from esphomeyaml.cpp_helpers import setup_component from esphomeyaml.cpp_types import Application, Component, App -DEPENDENCIES = ['mqtt'] MakeStatusBinarySensor = Application.struct('MakeStatusBinarySensor') StatusBinarySensor = binary_sensor.binary_sensor_ns.class_('StatusBinarySensor', diff --git a/esphomeyaml/components/custom_component.py b/esphomeyaml/components/custom_component.py index abcedf5ca4..da85785fb6 100644 --- a/esphomeyaml/components/custom_component.py +++ b/esphomeyaml/components/custom_component.py @@ -12,9 +12,9 @@ MULTI_CONF = True CONFIG_SCHEMA = vol.Schema({ cv.GenerateID(): cv.declare_variable_id(CustomComponentConstructor), vol.Required(CONF_LAMBDA): cv.lambda_, - vol.Optional(CONF_COMPONENTS): vol.All(cv.ensure_list, [vol.Schema({ + vol.Optional(CONF_COMPONENTS): cv.ensure_list(vol.Schema({ cv.GenerateID(): cv.declare_variable_id(Component) - }).extend(cv.COMPONENT_SCHEMA.schema)]), + }).extend(cv.COMPONENT_SCHEMA.schema)), }) diff --git a/esphomeyaml/components/deep_sleep.py b/esphomeyaml/components/deep_sleep.py index aa600bae8f..7019c4d718 100644 --- a/esphomeyaml/components/deep_sleep.py +++ b/esphomeyaml/components/deep_sleep.py @@ -46,8 +46,7 @@ CONFIG_SCHEMA = vol.Schema({ vol.Optional(CONF_WAKEUP_PIN_MODE): vol.All(cv.only_on_esp32, cv.one_of(*WAKEUP_PIN_MODES), upper=True), vol.Optional(CONF_ESP32_EXT1_WAKEUP): vol.All(cv.only_on_esp32, vol.Schema({ - vol.Required(CONF_PINS): vol.All(cv.ensure_list, [pins.shorthand_input_pin], - [validate_pin_number]), + vol.Required(CONF_PINS): cv.ensure_list(pins.shorthand_input_pin, validate_pin_number), vol.Required(CONF_MODE): cv.one_of(*EXT1_WAKEUP_MODES, upper=True), })), vol.Optional(CONF_RUN_CYCLES): cv.positive_int, diff --git a/esphomeyaml/components/interval.py b/esphomeyaml/components/interval.py new file mode 100644 index 0000000000..591ed6ff29 --- /dev/null +++ b/esphomeyaml/components/interval.py @@ -0,0 +1,23 @@ +import voluptuous as vol + +from esphomeyaml import automation +import esphomeyaml.config_validation as cv +from esphomeyaml.const import CONF_ID +from esphomeyaml.cpp_generator import Pvariable +from esphomeyaml.cpp_helpers import setup_component +from esphomeyaml.cpp_types import App, NoArg, PollingComponent, Trigger, esphomelib_ns + +IntervalTrigger = esphomelib_ns.class_('IntervalTrigger', Trigger.template(NoArg), PollingComponent) + +CONFIG_SCHEMA = automation.validate_automation(vol.Schema({ + vol.Required(CONF_ID): cv.declare_variable_id(IntervalTrigger), +}).extend(cv.COMPONENT_SCHEMA.schema)) + + +def to_code(config): + for conf in config: + rhs = App.register_component(IntervalTrigger.new()) + trigger = Pvariable(conf[CONF_ID], rhs) + setup_component(trigger, conf) + + automation.build_automation(trigger, NoArg, conf) diff --git a/esphomeyaml/components/light/__init__.py b/esphomeyaml/components/light/__init__.py index c4d492bbf4..3bcb63168c 100644 --- a/esphomeyaml/components/light/__init__.py +++ b/esphomeyaml/components/light/__init__.py @@ -100,7 +100,7 @@ EFFECTS_SCHEMA = vol.Schema({ vol.Optional(CONF_STROBE): vol.Schema({ cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(StrobeLightEffect), vol.Optional(CONF_NAME, default="Strobe"): cv.string, - vol.Optional(CONF_COLORS): vol.All(cv.ensure_list, [vol.All(vol.Schema({ + vol.Optional(CONF_COLORS): vol.All(cv.ensure_list(vol.Schema({ vol.Optional(CONF_STATE, default=True): cv.boolean, vol.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, vol.Optional(CONF_RED, default=1.0): cv.percentage, @@ -109,7 +109,7 @@ EFFECTS_SCHEMA = vol.Schema({ vol.Optional(CONF_WHITE, default=1.0): cv.percentage, vol.Required(CONF_DURATION): cv.positive_time_period_milliseconds, }), cv.has_at_least_one_key(CONF_STATE, CONF_BRIGHTNESS, CONF_RED, CONF_GREEN, CONF_BLUE, - CONF_WHITE))], vol.Length(min=2)), + CONF_WHITE)), vol.Length(min=2)), }), vol.Optional(CONF_FLICKER): vol.Schema({ cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(FlickerLightEffect), @@ -131,13 +131,13 @@ EFFECTS_SCHEMA = vol.Schema({ vol.Optional(CONF_FASTLED_COLOR_WIPE): vol.Schema({ cv.GenerateID(CONF_EFFECT_ID): cv.declare_variable_id(FastLEDColorWipeEffect), vol.Optional(CONF_NAME, default="Color Wipe"): cv.string, - vol.Optional(CONF_COLORS): vol.All(cv.ensure_list, [vol.Schema({ + vol.Optional(CONF_COLORS): cv.ensure_list({ vol.Optional(CONF_RED, default=1.0): cv.percentage, vol.Optional(CONF_GREEN, default=1.0): cv.percentage, vol.Optional(CONF_BLUE, default=1.0): cv.percentage, vol.Optional(CONF_RANDOM, default=False): cv.boolean, vol.Required(CONF_NUM_LEDS): vol.All(cv.uint32_t, vol.Range(min=1)), - })]), + }), vol.Optional(CONF_ADD_LED_INTERVAL): cv.positive_time_period_milliseconds, vol.Optional(CONF_REVERSE): cv.boolean, }), @@ -178,7 +178,8 @@ EFFECTS_SCHEMA = vol.Schema({ def validate_effects(allowed_effects): def validator(value): is_list = isinstance(value, list) - value = cv.ensure_list(value) + if not is_list: + value = [value] names = set() ret = [] for i, effect in enumerate(value): @@ -471,10 +472,10 @@ def light_turn_on_to_code(config, action_id, arg_type, template_arg): def core_to_hass_config(data, config, brightness=True, rgb=True, color_temp=True, white_value=True): - ret = mqtt.build_hass_config(data, 'light', config, include_state=True, include_command=True, - platform='mqtt_json') + ret = mqtt.build_hass_config(data, 'light', config, include_state=True, include_command=True) if ret is None: return None + ret['schema'] = 'json' if brightness: ret['brightness'] = True if rgb: diff --git a/esphomeyaml/components/logger.py b/esphomeyaml/components/logger.py index 4c9b399973..33fc6e270a 100644 --- a/esphomeyaml/components/logger.py +++ b/esphomeyaml/components/logger.py @@ -108,7 +108,7 @@ def validate_printf(value): CONF_LOGGER_LOG = 'logger.log' LOGGER_LOG_ACTION_SCHEMA = vol.All(maybe_simple_message({ vol.Required(CONF_FORMAT): cv.string, - vol.Optional(CONF_ARGS, default=list): vol.All(cv.ensure_list, [cv.lambda_]), + vol.Optional(CONF_ARGS, default=list): cv.ensure_list(cv.lambda_), vol.Optional(CONF_LEVEL, default="DEBUG"): cv.one_of(*LOG_LEVEL_TO_ESP_LOG, upper=True), vol.Optional(CONF_TAG, default="main"): cv.string, }), validate_printf) diff --git a/esphomeyaml/components/mqtt.py b/esphomeyaml/components/mqtt.py index 6d20f9324f..28f165c504 100644 --- a/esphomeyaml/components/mqtt.py +++ b/esphomeyaml/components/mqtt.py @@ -85,7 +85,7 @@ CONFIG_SCHEMA = vol.All(vol.Schema({ vol.Optional(CONF_LEVEL): logger.is_log_level, }), validate_message_just_topic), vol.Optional(CONF_SSL_FINGERPRINTS): vol.All(cv.only_on_esp8266, - cv.ensure_list, [validate_fingerprint]), + cv.ensure_list(validate_fingerprint)), vol.Optional(CONF_KEEPALIVE): cv.positive_time_period_seconds, vol.Optional(CONF_REBOOT_TIMEOUT): cv.positive_time_period_milliseconds, vol.Optional(CONF_ON_MESSAGE): automation.validate_automation({ @@ -260,12 +260,11 @@ def get_default_topic_for(data, component_type, name, suffix): sanitized_name, suffix) -def build_hass_config(data, component_type, config, include_state=True, include_command=True, - platform='mqtt'): +def build_hass_config(data, component_type, config, include_state=True, include_command=True): if config.get(CONF_INTERNAL, False): return None ret = OrderedDict() - ret['platform'] = platform + ret['platform'] = 'mqtt' ret['name'] = config[CONF_NAME] if include_state: default = get_default_topic_for(data, component_type, config[CONF_NAME], 'state') diff --git a/esphomeyaml/components/output/custom.py b/esphomeyaml/components/output/custom.py index c4f6068ca2..4744ba16eb 100644 --- a/esphomeyaml/components/output/custom.py +++ b/esphomeyaml/components/output/custom.py @@ -13,18 +13,18 @@ BINARY_SCHEMA = output.PLATFORM_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(CustomBinaryOutputConstructor), vol.Required(CONF_LAMBDA): cv.lambda_, vol.Required(CONF_OUTPUTS): - vol.All(cv.ensure_list, [output.BINARY_OUTPUT_SCHEMA.extend({ + cv.ensure_list(output.BINARY_OUTPUT_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(output.BinaryOutput), - })]), + })), }) FLOAT_SCHEMA = output.PLATFORM_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(CustomFloatOutputConstructor), vol.Required(CONF_LAMBDA): cv.lambda_, vol.Required(CONF_OUTPUTS): - vol.All(cv.ensure_list, [output.FLOAT_OUTPUT_PLATFORM_SCHEMA.extend({ + cv.ensure_list(output.FLOAT_OUTPUT_PLATFORM_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(output.FloatOutput), - })]), + })), }) diff --git a/esphomeyaml/components/remote_receiver.py b/esphomeyaml/components/remote_receiver.py index a9253b5a77..b77ec45bb3 100644 --- a/esphomeyaml/components/remote_receiver.py +++ b/esphomeyaml/components/remote_receiver.py @@ -41,8 +41,7 @@ CONFIG_SCHEMA = vol.Schema({ cv.GenerateID(): cv.declare_variable_id(RemoteReceiverComponent), vol.Required(CONF_PIN): pins.gpio_input_pin_schema, vol.Optional(CONF_DUMP, default=[]): - vol.Any(validate_dumpers_all, - vol.All(cv.ensure_list, [cv.one_of(*DUMPERS, lower=True)])), + vol.Any(validate_dumpers_all, cv.ensure_list(cv.one_of(*DUMPERS, lower=True))), vol.Optional(CONF_TOLERANCE): vol.All(cv.percentage_int, vol.Range(min=0)), vol.Optional(CONF_BUFFER_SIZE): cv.validate_bytes, vol.Optional(CONF_FILTER): cv.positive_time_period_microseconds, diff --git a/esphomeyaml/components/sensor/__init__.py b/esphomeyaml/components/sensor/__init__.py index 433ee63015..10d1fa4ba1 100644 --- a/esphomeyaml/components/sensor/__init__.py +++ b/esphomeyaml/components/sensor/__init__.py @@ -40,7 +40,7 @@ FILTER_KEYS = [CONF_OFFSET, CONF_MULTIPLY, CONF_FILTER_OUT, CONF_FILTER_NAN, CONF_SLIDING_WINDOW_MOVING_AVERAGE, CONF_EXPONENTIAL_MOVING_AVERAGE, CONF_LAMBDA, CONF_THROTTLE, CONF_DELTA, CONF_UNIQUE, CONF_HEARTBEAT, CONF_DEBOUNCE, CONF_OR] -FILTERS_SCHEMA = vol.All(cv.ensure_list, [vol.All({ +FILTERS_SCHEMA = cv.ensure_list({ vol.Optional(CONF_OFFSET): cv.float_, vol.Optional(CONF_MULTIPLY): cv.float_, vol.Optional(CONF_FILTER_OUT): cv.float_, @@ -61,7 +61,7 @@ FILTERS_SCHEMA = vol.All(cv.ensure_list, [vol.All({ vol.Optional(CONF_HEARTBEAT): cv.positive_time_period_milliseconds, vol.Optional(CONF_DEBOUNCE): cv.positive_time_period_milliseconds, vol.Optional(CONF_OR): validate_recursive_filter, -}, cv.has_exactly_one_key(*FILTER_KEYS))]) +}, cv.has_exactly_one_key(*FILTER_KEYS)) # Base sensor_ns = esphomelib_ns.namespace('sensor') diff --git a/esphomeyaml/components/sensor/custom.py b/esphomeyaml/components/sensor/custom.py index 4eac07311f..a87fef6604 100644 --- a/esphomeyaml/components/sensor/custom.py +++ b/esphomeyaml/components/sensor/custom.py @@ -11,9 +11,9 @@ CustomSensorConstructor = sensor.sensor_ns.class_('CustomSensorConstructor') PLATFORM_SCHEMA = sensor.PLATFORM_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(CustomSensorConstructor), vol.Required(CONF_LAMBDA): cv.lambda_, - vol.Required(CONF_SENSORS): vol.All(cv.ensure_list, [sensor.SENSOR_SCHEMA.extend({ + vol.Required(CONF_SENSORS): cv.ensure_list(sensor.SENSOR_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(sensor.Sensor), - })]), + })), }) diff --git a/esphomeyaml/components/sensor/homeassistant.py b/esphomeyaml/components/sensor/homeassistant.py new file mode 100644 index 0000000000..b3b2c1950b --- /dev/null +++ b/esphomeyaml/components/sensor/homeassistant.py @@ -0,0 +1,32 @@ +import voluptuous as vol + +from esphomeyaml.components import sensor +import esphomeyaml.config_validation as cv +from esphomeyaml.const import CONF_ENTITY_ID, CONF_MAKE_ID, CONF_NAME +from esphomeyaml.cpp_generator import variable +from esphomeyaml.cpp_types import App, Application + +DEPENDENCIES = ['api'] + +MakeHomeassistantSensor = Application.struct('MakeHomeassistantSensor') +HomeassistantSensor = sensor.sensor_ns.class_('HomeassistantSensor', sensor.Sensor) + +PLATFORM_SCHEMA = cv.nameable(sensor.SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(HomeassistantSensor), + cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeHomeassistantSensor), + vol.Required(CONF_ENTITY_ID): cv.entity_id, +})) + + +def to_code(config): + rhs = App.make_homeassistant_sensor(config[CONF_NAME], config[CONF_ENTITY_ID]) + make = variable(config[CONF_MAKE_ID], rhs) + subs = make.Psensor + sensor.setup_sensor(subs, make.Pmqtt, config) + + +BUILD_FLAGS = '-DUSE_HOMEASSISTANT_SENSOR' + + +def to_hass_config(data, config): + return sensor.core_to_hass_config(data, config) diff --git a/esphomeyaml/components/switch/custom.py b/esphomeyaml/components/switch/custom.py index 320a8855bf..a763744ea9 100644 --- a/esphomeyaml/components/switch/custom.py +++ b/esphomeyaml/components/switch/custom.py @@ -12,9 +12,9 @@ PLATFORM_SCHEMA = switch.PLATFORM_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(CustomSwitchConstructor), vol.Required(CONF_LAMBDA): cv.lambda_, vol.Required(CONF_SWITCHES): - vol.All(cv.ensure_list, [switch.SWITCH_SCHEMA.extend({ + cv.ensure_list(switch.SWITCH_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(switch.Switch), - })]), + })), }) diff --git a/esphomeyaml/components/text_sensor/custom.py b/esphomeyaml/components/text_sensor/custom.py index f12b3d1672..468e971ef5 100644 --- a/esphomeyaml/components/text_sensor/custom.py +++ b/esphomeyaml/components/text_sensor/custom.py @@ -12,9 +12,9 @@ PLATFORM_SCHEMA = text_sensor.PLATFORM_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(CustomTextSensorConstructor), vol.Required(CONF_LAMBDA): cv.lambda_, vol.Required(CONF_TEXT_SENSORS): - vol.All(cv.ensure_list, [text_sensor.TEXT_SENSOR_SCHEMA.extend({ + cv.ensure_list(text_sensor.TEXT_SENSOR_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(text_sensor.TextSensor), - })]), + })), }) diff --git a/esphomeyaml/components/text_sensor/homeassistant.py b/esphomeyaml/components/text_sensor/homeassistant.py new file mode 100644 index 0000000000..0c6a0d04d2 --- /dev/null +++ b/esphomeyaml/components/text_sensor/homeassistant.py @@ -0,0 +1,33 @@ +import voluptuous as vol + +from esphomeyaml.components import text_sensor +import esphomeyaml.config_validation as cv +from esphomeyaml.const import CONF_ENTITY_ID, CONF_MAKE_ID, CONF_NAME +from esphomeyaml.cpp_generator import variable +from esphomeyaml.cpp_types import App, Application, Component + +DEPENDENCIES = ['api'] + +MakeHomeassistantTextSensor = Application.struct('MakeHomeassistantTextSensor') +HomeassistantTextSensor = text_sensor.text_sensor_ns.class_('HomeassistantTextSensor', + text_sensor.TextSensor, Component) + +PLATFORM_SCHEMA = cv.nameable(text_sensor.TEXT_SENSOR_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(HomeassistantTextSensor), + cv.GenerateID(CONF_MAKE_ID): cv.declare_variable_id(MakeHomeassistantTextSensor), + vol.Required(CONF_ENTITY_ID): cv.entity_id, +})) + + +def to_code(config): + rhs = App.make_homeassistant_text_sensor(config[CONF_NAME], config[CONF_ENTITY_ID]) + make = variable(config[CONF_MAKE_ID], rhs) + sensor_ = make.Psensor + text_sensor.setup_text_sensor(sensor_, make.Pmqtt, config) + + +BUILD_FLAGS = '-DUSE_HOMEASSISTANT_TEXT_SENSOR' + + +def to_hass_config(data, config): + return text_sensor.core_to_hass_config(data, config) diff --git a/esphomeyaml/components/time/homeassistant.py b/esphomeyaml/components/time/homeassistant.py new file mode 100644 index 0000000000..3ebe3ca8d4 --- /dev/null +++ b/esphomeyaml/components/time/homeassistant.py @@ -0,0 +1,25 @@ +from esphomeyaml.components import time as time_ +import esphomeyaml.config_validation as cv +from esphomeyaml.const import CONF_ID +from esphomeyaml.cpp_generator import Pvariable +from esphomeyaml.cpp_helpers import setup_component +from esphomeyaml.cpp_types import App + + +DEPENDENCIES = ['api'] + +HomeAssistantTime = time_.time_ns.class_('HomeAssistantTime', time_.RealTimeClockComponent) + +PLATFORM_SCHEMA = time_.TIME_PLATFORM_SCHEMA.extend({ + cv.GenerateID(): cv.declare_variable_id(HomeAssistantTime), +}).extend(cv.COMPONENT_SCHEMA.schema) + + +def to_code(config): + rhs = App.make_homeassistant_time_component() + ha_time = Pvariable(config[CONF_ID], rhs) + time_.setup_time(ha_time, config) + setup_component(ha_time, config) + + +BUILD_FLAGS = '-DUSE_HOMEASSISTANT_TIME' diff --git a/esphomeyaml/components/time/sntp.py b/esphomeyaml/components/time/sntp.py index 78c1106a6e..15d74f3dfd 100644 --- a/esphomeyaml/components/time/sntp.py +++ b/esphomeyaml/components/time/sntp.py @@ -1,8 +1,8 @@ import voluptuous as vol -import esphomeyaml.config_validation as cv from esphomeyaml.components import time as time_ -from esphomeyaml.const import CONF_ID, CONF_LAMBDA, CONF_SERVERS +import esphomeyaml.config_validation as cv +from esphomeyaml.const import CONF_ID, CONF_SERVERS from esphomeyaml.cpp_generator import Pvariable, add from esphomeyaml.cpp_helpers import setup_component from esphomeyaml.cpp_types import App @@ -11,8 +11,7 @@ SNTPComponent = time_.time_ns.class_('SNTPComponent', time_.RealTimeClockCompone PLATFORM_SCHEMA = time_.TIME_PLATFORM_SCHEMA.extend({ cv.GenerateID(): cv.declare_variable_id(SNTPComponent), - vol.Optional(CONF_SERVERS): vol.All(cv.ensure_list, [cv.domain], vol.Length(min=1, max=3)), - vol.Optional(CONF_LAMBDA): cv.lambda_, + vol.Optional(CONF_SERVERS): vol.All(cv.ensure_list(cv.domain), vol.Length(min=1, max=3)), }).extend(cv.COMPONENT_SCHEMA.schema) diff --git a/esphomeyaml/components/wifi.py b/esphomeyaml/components/wifi.py index 5c1076d756..80e592ddcf 100644 --- a/esphomeyaml/components/wifi.py +++ b/esphomeyaml/components/wifi.py @@ -3,12 +3,25 @@ import voluptuous as vol import esphomeyaml.config_validation as cv from esphomeyaml.const import CONF_AP, CONF_CHANNEL, CONF_DNS1, CONF_DNS2, CONF_DOMAIN, \ CONF_GATEWAY, CONF_HOSTNAME, CONF_ID, CONF_MANUAL_IP, CONF_PASSWORD, CONF_POWER_SAVE_MODE, \ - CONF_REBOOT_TIMEOUT, CONF_SSID, CONF_STATIC_IP, CONF_SUBNET -from esphomeyaml.core import CORE -from esphomeyaml.cpp_generator import Pvariable, StructInitializer, add + CONF_REBOOT_TIMEOUT, CONF_SSID, CONF_STATIC_IP, CONF_SUBNET, CONF_NETWORKS, CONF_BSSID +from esphomeyaml.core import CORE, HexInt +from esphomeyaml.cpp_generator import Pvariable, StructInitializer, add, variable, ArrayInitializer from esphomeyaml.cpp_types import App, Component, esphomelib_ns, global_ns +IPAddress = global_ns.class_('IPAddress') +ManualIP = esphomelib_ns.struct('ManualIP') +WiFiComponent = esphomelib_ns.class_('WiFiComponent', Component) +WiFiAP = esphomelib_ns.struct('WiFiAP') + +WiFiPowerSaveMode = esphomelib_ns.enum('WiFiPowerSaveMode') +WIFI_POWER_SAVE_MODES = { + 'NONE': WiFiPowerSaveMode.WIFI_POWER_SAVE_NONE, + 'LIGHT': WiFiPowerSaveMode.WIFI_POWER_SAVE_LIGHT, + 'HIGH': WiFiPowerSaveMode.WIFI_POWER_SAVE_HIGH, +} + + def validate_password(value): value = cv.string(value) if not value: @@ -41,10 +54,11 @@ STA_MANUAL_IP_SCHEMA = AP_MANUAL_IP_SCHEMA.extend({ }) WIFI_NETWORK_BASE = vol.Schema({ - vol.Required(CONF_SSID): cv.ssid, + cv.GenerateID(): cv.declare_variable_id(WiFiAP), + vol.Optional(CONF_SSID): cv.ssid, vol.Optional(CONF_PASSWORD): validate_password, vol.Optional(CONF_CHANNEL): validate_channel, - vol.Optional(CONF_MANUAL_IP): AP_MANUAL_IP_SCHEMA, + vol.Optional(CONF_MANUAL_IP): STA_MANUAL_IP_SCHEMA, }) WIFI_NETWORK_AP = WIFI_NETWORK_BASE.extend({ @@ -53,35 +67,39 @@ WIFI_NETWORK_AP = WIFI_NETWORK_BASE.extend({ WIFI_NETWORK_STA = WIFI_NETWORK_BASE.extend({ vol.Optional(CONF_MANUAL_IP): STA_MANUAL_IP_SCHEMA, + vol.Optional(CONF_BSSID): cv.mac_address, }) def validate(config): if CONF_PASSWORD in config and CONF_SSID not in config: raise vol.Invalid("Cannot have WiFi password without SSID!") - if (CONF_SSID not in config) and (CONF_AP not in config): + + if CONF_SSID in config: + network = {CONF_SSID: config.pop(CONF_SSID)} + if CONF_PASSWORD in config: + network[CONF_PASSWORD] = config.pop(CONF_PASSWORD) + if CONF_MANUAL_IP in config: + network[CONF_MANUAL_IP] = config.pop(CONF_MANUAL_IP) + if CONF_NETWORKS in config: + raise vol.Invalid("You cannot use the 'ssid:' option together with 'networks:'. Please " + "copy your network into the 'networks:' key") + config[CONF_NETWORKS] = cv.ensure_list(WIFI_NETWORK_STA)(network) + + if (CONF_NETWORKS not in config) and (CONF_AP not in config): raise vol.Invalid("Please specify at least an SSID or an Access Point " "to create.") return config -IPAddress = global_ns.class_('IPAddress') -ManualIP = esphomelib_ns.struct('ManualIP') -WiFiComponent = esphomelib_ns.class_('WiFiComponent', Component) -WiFiAp = esphomelib_ns.struct('WiFiAp') - -WiFiPowerSaveMode = esphomelib_ns.enum('WiFiPowerSaveMode') -WIFI_POWER_SAVE_MODES = { - 'NONE': WiFiPowerSaveMode.WIFI_POWER_SAVE_NONE, - 'LIGHT': WiFiPowerSaveMode.WIFI_POWER_SAVE_LIGHT, - 'HIGH': WiFiPowerSaveMode.WIFI_POWER_SAVE_HIGH, -} - CONFIG_SCHEMA = vol.All(vol.Schema({ cv.GenerateID(): cv.declare_variable_id(WiFiComponent), + vol.Optional(CONF_NETWORKS): cv.ensure_list(WIFI_NETWORK_STA), + vol.Optional(CONF_SSID): cv.ssid, vol.Optional(CONF_PASSWORD): validate_password, vol.Optional(CONF_MANUAL_IP): STA_MANUAL_IP_SCHEMA, + vol.Optional(CONF_AP): WIFI_NETWORK_AP, vol.Optional(CONF_HOSTNAME): cv.hostname, vol.Optional(CONF_DOMAIN, default='.local'): cv.domain_name, @@ -110,21 +128,28 @@ def manual_ip(config): def wifi_network(config): - return StructInitializer( - WiFiAp, - ('ssid', config.get(CONF_SSID, "")), - ('password', config.get(CONF_PASSWORD, "")), - ('channel', config.get(CONF_CHANNEL, -1)), - ('manual_ip', manual_ip(config.get(CONF_MANUAL_IP))), - ) + ap = variable(config[CONF_ID], WiFiAP()) + if CONF_SSID in config: + add(ap.set_ssid(config[CONF_SSID])) + if CONF_PASSWORD in config: + add(ap.set_password(config[CONF_PASSWORD])) + if CONF_BSSID in config: + bssid = [HexInt(i) for i in config[CONF_BSSID].parts] + add(ap.set_bssid(ArrayInitializer(*bssid, multiline=False))) + if CONF_CHANNEL in config: + add(ap.set_channel(config[CONF_CHANNEL])) + if CONF_MANUAL_IP in config: + add(ap.set_manual_ip(manual_ip(config[CONF_MANUAL_IP]))) + + return ap def to_code(config): rhs = App.init_wifi() wifi = Pvariable(config[CONF_ID], rhs) - if CONF_SSID in config: - add(wifi.set_sta(wifi_network(config))) + for network in config.get(CONF_NETWORKS, []): + add(wifi.add_sta(wifi_network(network))) if CONF_AP in config: add(wifi.set_ap(wifi_network(config[CONF_AP]))) diff --git a/esphomeyaml/config_validation.py b/esphomeyaml/config_validation.py index cf6aff6940..0092296d27 100644 --- a/esphomeyaml/config_validation.py +++ b/esphomeyaml/config_validation.py @@ -102,13 +102,25 @@ def boolean(value): return bool(value) -def ensure_list(value): +def ensure_list(*validators): """Wrap value in list if it is not one.""" - if value is None or (isinstance(value, dict) and not value): - return [] - if isinstance(value, list): - return value - return [value] + user = vol.All(*validators) + + def validator(value): + if value is None or (isinstance(value, dict) and not value): + return [] + if not isinstance(value, list): + return [user(value)] + ret = [] + for i, val in enumerate(value): + try: + ret.append(user(val)) + except vol.Invalid as err: + err.prepend(i) + raise err + return ret + + return validator def ensure_list_not_empty(value): @@ -469,16 +481,18 @@ def ssid(value): raise vol.Invalid("SSID must be a string. Did you wrap it in quotes?") if not value: raise vol.Invalid("SSID can't be empty.") - if len(value) > 31: - raise vol.Invalid("SSID can't be longer than 31 characters") + if len(value) > 32: + raise vol.Invalid("SSID can't be longer than 32 characters") return value def ipv4(value): if isinstance(value, list): parts = value - elif isinstance(value, str): + elif isinstance(value, basestring): parts = value.split('.') + elif isinstance(value, IPAddress): + return value else: raise vol.Invalid("IPv4 address must consist of either string or " "integer list") @@ -664,6 +678,16 @@ def file_(value): return value +ENTITY_ID_PATTERN = re.compile(r"^([a-z0-9]+)\.([a-z0-9]+)$") + + +def entity_id(value): + value = string_strict(value).lower() + if ENTITY_ID_PATTERN.match(value) is None: + raise vol.Invalid(u"Invalid entity ID: {}".format(value)) + return value + + class GenerateID(vol.Optional): def __init__(self, key=CONF_ID): super(GenerateID, self).__init__(key, default=lambda: None) diff --git a/esphomeyaml/const.py b/esphomeyaml/const.py index 13e424cc4e..73bee9d37e 100644 --- a/esphomeyaml/const.py +++ b/esphomeyaml/const.py @@ -28,6 +28,7 @@ CONF_BRANCH = 'branch' CONF_LOGGER = 'logger' CONF_WIFI = 'wifi' CONF_SSID = 'ssid' +CONF_BSSID = 'bssid' CONF_PASSWORD = 'password' CONF_MANUAL_IP = 'manual_ip' CONF_STATIC_IP = 'static_ip' @@ -222,6 +223,7 @@ CONF_ACCURACY = 'accuracy' CONF_BOARD_FLASH_MODE = 'board_flash_mode' CONF_ON_PRESS = 'on_press' CONF_ON_RELEASE = 'on_release' +CONF_ON_STATE = 'on_state' CONF_ON_CLICK = 'on_click' CONF_ON_DOUBLE_CLICK = 'on_double_click' CONF_ON_MULTI_CLICK = 'on_multi_click' @@ -386,6 +388,10 @@ CONF_PIN_D = 'pin_d' CONF_SLEEP_WHEN_DONE = 'sleep_when_done' CONF_STEP_MODE = 'step_mode' CONF_COMPONENTS = 'components' +CONF_DATA_TEMPLATE = 'data_template' +CONF_VARIABLES = 'variables' +CONF_SERVICE = 'service' +CONF_ENTITY_ID = 'entity_id' ALLOWED_NAME_CHARS = u'abcdefghijklmnopqrstuvwxyz0123456789_' ARDUINO_VERSION_ESP32_DEV = 'https://github.com/platformio/platform-espressif32.git#feature/stage' diff --git a/esphomeyaml/core.py b/esphomeyaml/core.py index a2a874f98b..eed2d3c188 100644 --- a/esphomeyaml/core.py +++ b/esphomeyaml/core.py @@ -282,6 +282,8 @@ class ID(object): # pylint: disable=too-many-instance-attributes class EsphomeyamlCore(object): def __init__(self): + # True if command is run from dashboard + self.dashboard = False # The name of the node self.name = None # type: str # The relative path to the configuration YAML diff --git a/esphomeyaml/core_config.py b/esphomeyaml/core_config.py index d897f373db..0e566585c2 100644 --- a/esphomeyaml/core_config.py +++ b/esphomeyaml/core_config.py @@ -175,8 +175,8 @@ CONFIG_SCHEMA = vol.Schema({ vol.Optional(CONF_ON_LOOP): automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(LoopTrigger), }), - vol.Optional(CONF_INCLUDES): vol.All(cv.ensure_list, [cv.file_]), - vol.Optional(CONF_LIBRARIES): vol.All(cv.ensure_list, [cv.string_strict]), + vol.Optional(CONF_INCLUDES): cv.ensure_list(cv.file_), + vol.Optional(CONF_LIBRARIES): cv.ensure_list(cv.string_strict), vol.Optional('library_uri'): cv.invalid("The library_uri option has been removed in 1.8.0 and " "was moved into the esphomelib_version option."), diff --git a/esphomeyaml/dashboard/dashboard.py b/esphomeyaml/dashboard/dashboard.py index 45450d35bd..4b6df5d5ad 100644 --- a/esphomeyaml/dashboard/dashboard.py +++ b/esphomeyaml/dashboard/dashboard.py @@ -103,49 +103,49 @@ class EsphomeyamlLogsHandler(EsphomeyamlCommandWebSocket): def build_command(self, message): js = json.loads(message) config_file = CONFIG_DIR + '/' + js['configuration'] - return ["esphomeyaml", config_file, "logs", '--serial-port', js["port"]] + return ["esphomeyaml", "--dashboard", config_file, "logs", '--serial-port', js["port"]] class EsphomeyamlRunHandler(EsphomeyamlCommandWebSocket): def build_command(self, message): js = json.loads(message) config_file = os.path.join(CONFIG_DIR, js['configuration']) - return ["esphomeyaml", config_file, "run", '--upload-port', js["port"]] + return ["esphomeyaml", "--dashboard", config_file, "run", '--upload-port', js["port"]] class EsphomeyamlCompileHandler(EsphomeyamlCommandWebSocket): def build_command(self, message): js = json.loads(message) config_file = os.path.join(CONFIG_DIR, js['configuration']) - return ["esphomeyaml", config_file, "compile"] + return ["esphomeyaml", "--dashboard", config_file, "compile"] class EsphomeyamlValidateHandler(EsphomeyamlCommandWebSocket): def build_command(self, message): js = json.loads(message) config_file = os.path.join(CONFIG_DIR, js['configuration']) - return ["esphomeyaml", config_file, "config"] + return ["esphomeyaml", "--dashboard", config_file, "config"] class EsphomeyamlCleanMqttHandler(EsphomeyamlCommandWebSocket): def build_command(self, message): js = json.loads(message) config_file = os.path.join(CONFIG_DIR, js['configuration']) - return ["esphomeyaml", config_file, "clean-mqtt"] + return ["esphomeyaml", "--dashboard", config_file, "clean-mqtt"] class EsphomeyamlCleanHandler(EsphomeyamlCommandWebSocket): def build_command(self, message): js = json.loads(message) config_file = os.path.join(CONFIG_DIR, js['configuration']) - return ["esphomeyaml", config_file, "clean"] + return ["esphomeyaml", "--dashboard", config_file, "clean"] class EsphomeyamlHassConfigHandler(EsphomeyamlCommandWebSocket): def build_command(self, message): js = json.loads(message) config_file = os.path.join(CONFIG_DIR, js['configuration']) - return ["esphomeyaml", config_file, "hass-config"] + return ["esphomeyaml", "--dashboard", config_file, "hass-config"] class SerialPortRequestHandler(BaseHandler): @@ -294,10 +294,9 @@ class MainRequestHandler(BaseHandler): version = const.__version__ docs_link = 'https://beta.esphomelib.com/esphomeyaml/' if 'b' in version else \ 'https://esphomelib.com/esphomeyaml/' - mqtt_config = get_mqtt_config_lazy() self.render("templates/index.html", entries=entries, - version=version, begin=begin, docs_link=docs_link, mqtt_config=mqtt_config) + version=version, begin=begin, docs_link=docs_link) def _ping_func(filename, address): @@ -497,43 +496,6 @@ def make_app(debug=False): return app -def _get_mqtt_config_impl(): - import requests - - headers = { - 'X-HASSIO-KEY': os.getenv('HASSIO_TOKEN'), - } - - mqtt_config = requests.get('http://hassio/services/mqtt', headers=headers).json()['data'] - info = requests.get('http://hassio/host/info', headers=headers).json()['data'] - host = '{}.local'.format(info['hostname']) - port = mqtt_config['port'] - if port != 1883: - host = '{}:{}'.format(host, port) - - return { - 'ssl': mqtt_config['ssl'], - 'host': host, - 'username': mqtt_config.get('username', ''), - 'password': mqtt_config.get('password', '') - } - - -def get_mqtt_config_lazy(): - global HASSIO_MQTT_CONFIG - - if not ON_HASSIO: - return None - - if HASSIO_MQTT_CONFIG is None: - try: - HASSIO_MQTT_CONFIG = _get_mqtt_config_impl() - except Exception: # pylint: disable=broad-except - pass - - return HASSIO_MQTT_CONFIG - - def start_web_server(args): global CONFIG_DIR global PASSWORD_DIGEST diff --git a/esphomeyaml/dashboard/static/esphomeyaml.js b/esphomeyaml/dashboard/static/esphomeyaml.js index 111e11340e..f3f9b9c1c1 100644 --- a/esphomeyaml/dashboard/static/esphomeyaml.js +++ b/esphomeyaml/dashboard/static/esphomeyaml.js @@ -15,7 +15,7 @@ const initializeColorState = () => { }; const colorReplace = (pre, state, text) => { - const re = /\033(?:\[(.*?)[@-~]|\].*?(?:\007|\033\\))/g; + const re = /(?:\033|\\033)(?:\[(.*?)[@-~]|\].*?(?:\007|\033\\))/g; let i = 0; if (state.carriageReturn) { @@ -176,7 +176,7 @@ const fetchPing = () => { fetch('/ping', {credentials: "same-origin"}).then(res => res.json()) .then(response => { - for (let filename of response) { + for (let filename in response) { let node = document.querySelector(`.status-indicator[data-node="${filename}"]`); if (node === null) continue; diff --git a/esphomeyaml/dashboard/templates/index.html b/esphomeyaml/dashboard/templates/index.html index 0e43a8da96..e92770eca7 100644 --- a/esphomeyaml/dashboard/templates/index.html +++ b/esphomeyaml/dashboard/templates/index.html @@ -2,7 +2,7 @@ - esphomeyaml Dashboard + ESPHome Dashboard @@ -22,7 +22,7 @@