mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Fix some stuff
This commit is contained in:
		| @@ -18,11 +18,7 @@ VOLUME /config | |||||||
| WORKDIR /usr/src/app | WORKDIR /usr/src/app | ||||||
|  |  | ||||||
| COPY docker/platformio.ini /pio/platformio.ini | COPY docker/platformio.ini /pio/platformio.ini | ||||||
| ARG ESPHOMELIB_VERSION="" | RUN platformio run -d /pio; rm -rf /pio | ||||||
| RUN platformio run -d /pio; rm -rf /pio && \ |  | ||||||
|     /bin/bash -c "if [ ! -z '$ESPHOMELIB_VERSION']; then \ |  | ||||||
|         platformio lib -g install '${ESPHOMELIB_VERSION}'; \ |  | ||||||
|     fi" |  | ||||||
|  |  | ||||||
| COPY . . | COPY . . | ||||||
| RUN pip install --no-cache-dir --no-binary :all: -e . && \ | RUN pip install --no-cache-dir --no-binary :all: -e . && \ | ||||||
|   | |||||||
| @@ -10,10 +10,11 @@ import sys | |||||||
|  |  | ||||||
| from esphomeyaml import const, core_config, mqtt, platformio_api, wizard, writer, yaml_util | from esphomeyaml import const, core_config, mqtt, platformio_api, wizard, writer, yaml_util | ||||||
| from esphomeyaml.api.client import run_logs | from esphomeyaml.api.client import run_logs | ||||||
|  | from esphomeyaml.components import wifi | ||||||
| from esphomeyaml.config import get_component, iter_components, read_config, strip_default_ids | from esphomeyaml.config import get_component, iter_components, read_config, strip_default_ids | ||||||
| from esphomeyaml.const import CONF_BAUD_RATE, CONF_DOMAIN, CONF_ESPHOMEYAML, \ | 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, \ |     CONF_HOSTNAME, CONF_LOGGER, CONF_MANUAL_IP, CONF_NAME, CONF_STATIC_IP, CONF_USE_CUSTOM_CODE, \ | ||||||
|     CONF_WIFI |     CONF_WIFI, CONF_BROKER | ||||||
| from esphomeyaml.core import CORE, EsphomeyamlError | from esphomeyaml.core import CORE, EsphomeyamlError | ||||||
| from esphomeyaml.cpp_generator import Expression, RawStatement, add, statement | from esphomeyaml.cpp_generator import Expression, RawStatement, add, statement | ||||||
| from esphomeyaml.helpers import color, indent | from esphomeyaml.helpers import color, indent | ||||||
| @@ -39,31 +40,57 @@ def get_serial_ports(): | |||||||
|     return result |     return result | ||||||
|  |  | ||||||
|  |  | ||||||
| def choose_serial_port(config): | def choose_prompt(options): | ||||||
|     result = get_serial_ports() |     if not options: | ||||||
|  |         raise ValueError | ||||||
|  |  | ||||||
|  |     if len(options) == 1: | ||||||
|  |         return options[0][1] | ||||||
|  |  | ||||||
|  |     safe_print(u"Found multiple options, please choose one:") | ||||||
|  |     for i, (desc, _) in enumerate(options): | ||||||
|  |         safe_print(u"  [{}] {}".format(i + 1, desc)) | ||||||
|  |  | ||||||
|     if not result: |  | ||||||
|         return 'OTA' |  | ||||||
|     safe_print(u"Found multiple serial port options, please choose one:") |  | ||||||
|     for i, (res, desc) in enumerate(result): |  | ||||||
|         safe_print(u"  [{}] {} ({})".format(i, res, desc)) |  | ||||||
|     safe_print(u"  [{}] Over The Air ({})".format(len(result), get_upload_host(config))) |  | ||||||
|     safe_print() |  | ||||||
|     while True: |     while True: | ||||||
|         opt = raw_input('(number): ') |         opt = raw_input('(number): ') | ||||||
|         if opt in result: |         if opt in options: | ||||||
|             opt = result.index(opt) |             opt = options.index(opt) | ||||||
|             break |             break | ||||||
|         try: |         try: | ||||||
|             opt = int(opt) |             opt = int(opt) | ||||||
|             if opt < 0 or opt > len(result): |             if opt < 1 or opt > len(options): | ||||||
|                 raise ValueError |                 raise ValueError | ||||||
|             break |             break | ||||||
|         except ValueError: |         except ValueError: | ||||||
|             safe_print(color('red', u"Invalid option: '{}'".format(opt))) |             safe_print(color('red', u"Invalid option: '{}'".format(opt))) | ||||||
|     if opt == len(result): |     return options[opt - 1][1] | ||||||
|         return 'OTA' |  | ||||||
|     return result[opt][0] |  | ||||||
|  | def choose_upload_log_host(default, check_default, show_ota, show_mqtt, show_api): | ||||||
|  |     options = [] | ||||||
|  |     for res, desc in get_serial_ports(): | ||||||
|  |         options.append((u"{} ({})".format(res, desc), res)) | ||||||
|  |     if (show_ota and 'ota' in CORE.config) or (show_api and 'api' in CORE.config): | ||||||
|  |         options.append((u"Over The Air ({})".format(CORE.address), CORE.address)) | ||||||
|  |         if default == 'OTA': | ||||||
|  |             return CORE.address | ||||||
|  |     if show_mqtt and 'mqtt' in CORE.config: | ||||||
|  |         options.append((u"MQTT ({})".format(CORE.config['mqtt'][CONF_BROKER]), 'MQTT')) | ||||||
|  |         if default == 'OTA': | ||||||
|  |             return 'MQTT' | ||||||
|  |     if default is not None: | ||||||
|  |         return default | ||||||
|  |     if check_default is not None and check_default in [opt[1] for opt in options]: | ||||||
|  |         return check_default | ||||||
|  |     return choose_prompt(options) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def get_port_type(port): | ||||||
|  |     if port.startswith('/') or port.startswith('COM'): | ||||||
|  |         return 'SERIAL' | ||||||
|  |     if port == 'MQTT': | ||||||
|  |         return 'MQTT' | ||||||
|  |     return 'NETWORK' | ||||||
|  |  | ||||||
|  |  | ||||||
| def run_miniterm(config, port): | def run_miniterm(config, port): | ||||||
| @@ -132,16 +159,6 @@ def compile_program(args, config): | |||||||
|     return rc |     return rc | ||||||
|  |  | ||||||
|  |  | ||||||
| def get_upload_host(config): |  | ||||||
|     if CONF_MANUAL_IP in config[CONF_WIFI]: |  | ||||||
|         host = str(config[CONF_WIFI][CONF_MANUAL_IP][CONF_STATIC_IP]) |  | ||||||
|     elif CONF_HOSTNAME in config[CONF_WIFI]: |  | ||||||
|         host = config[CONF_WIFI][CONF_HOSTNAME] + config[CONF_WIFI][CONF_DOMAIN] |  | ||||||
|     else: |  | ||||||
|         host = config[CONF_ESPHOMEYAML][CONF_NAME] + config[CONF_WIFI][CONF_DOMAIN] |  | ||||||
|     return host |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def upload_using_esptool(config, port): | def upload_using_esptool(config, port): | ||||||
|     import esptool |     import esptool | ||||||
|  |  | ||||||
| @@ -152,24 +169,12 @@ def upload_using_esptool(config, port): | |||||||
|     return run_external_command(esptool._main, *cmd) |     return run_external_command(esptool._main, *cmd) | ||||||
|  |  | ||||||
|  |  | ||||||
| def upload_program(config, args, port): | def upload_program(config, args, host): | ||||||
|     # if upload is to a serial port use platformio, otherwise assume ota |     # if upload is to a serial port use platformio, otherwise assume ota | ||||||
|     serial_port = port.startswith('/') or port.startswith('COM') |     if get_port_type(host) == 'SERIAL': | ||||||
|     if port != 'OTA' and serial_port: |  | ||||||
|         if CORE.is_esp8266: |         if CORE.is_esp8266: | ||||||
|             return upload_using_esptool(config, port) |             return upload_using_esptool(config, host) | ||||||
|         return platformio_api.run_upload(config, args.verbose, port) |         return platformio_api.run_upload(config, args.verbose, host) | ||||||
|  |  | ||||||
|     if 'ota' not in config: |  | ||||||
|         _LOGGER.error("No serial port found and OTA not enabled. Can't upload!") |  | ||||||
|         return -1 |  | ||||||
|  |  | ||||||
|     # If hostname/ip is explicitly provided as upload-port argument, use this instead of zeroconf |  | ||||||
|     # hostname. This is to support use cases where zeroconf (hostname.local) does not work. |  | ||||||
|     if port != 'OTA': |  | ||||||
|         host = port |  | ||||||
|     else: |  | ||||||
|         host = get_upload_host(config) |  | ||||||
|  |  | ||||||
|     from esphomeyaml.components import ota |     from esphomeyaml.components import ota | ||||||
|     from esphomeyaml import espota2 |     from esphomeyaml import espota2 | ||||||
| @@ -199,13 +204,15 @@ def upload_program(config, args, port): | |||||||
|  |  | ||||||
|  |  | ||||||
| def show_logs(config, args, port): | def show_logs(config, args, port): | ||||||
|     serial_port = port.startswith('/') or port.startswith('COM') |     if get_port_type(port) == 'SERIAL': | ||||||
|     if port != 'OTA' and serial_port: |  | ||||||
|         run_miniterm(config, port) |         run_miniterm(config, port) | ||||||
|         return 0 |         return 0 | ||||||
|     if 'api' in config: |     elif get_port_type(port) == 'NETWORK': | ||||||
|         return run_logs(config, get_upload_host(config)) |         return run_logs(config, port) | ||||||
|     return mqtt.show_logs(config, args.topic, args.username, args.password, args.client_id) |     elif get_port_type(port) == 'MQTT': | ||||||
|  |         return mqtt.show_logs(config, args.topic, args.username, args.password, args.client_id) | ||||||
|  |  | ||||||
|  |     raise ValueError | ||||||
|  |  | ||||||
|  |  | ||||||
| def clean_mqtt(config, args): | def clean_mqtt(config, args): | ||||||
| @@ -266,7 +273,8 @@ def command_compile(args, config): | |||||||
|  |  | ||||||
|  |  | ||||||
| def command_upload(args, config): | def command_upload(args, config): | ||||||
|     port = args.upload_port or choose_serial_port(config) |     port = choose_upload_log_host(default=args.upload_port, check_default=None, | ||||||
|  |                                   show_ota=True, show_mqtt=False, show_api=False) | ||||||
|     exit_code = upload_program(config, args, port) |     exit_code = upload_program(config, args, port) | ||||||
|     if exit_code != 0: |     if exit_code != 0: | ||||||
|         return exit_code |         return exit_code | ||||||
| @@ -275,7 +283,8 @@ def command_upload(args, config): | |||||||
|  |  | ||||||
|  |  | ||||||
| def command_logs(args, config): | def command_logs(args, config): | ||||||
|     port = args.serial_port or choose_serial_port(config) |     port = choose_upload_log_host(default=args.serial_port, check_default=None, | ||||||
|  |                                   show_ota=False, show_mqtt=True, show_api=True) | ||||||
|     return show_logs(config, args, port) |     return show_logs(config, args, port) | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -287,13 +296,16 @@ def command_run(args, config): | |||||||
|     if exit_code != 0: |     if exit_code != 0: | ||||||
|         return exit_code |         return exit_code | ||||||
|     _LOGGER.info(u"Successfully compiled program.") |     _LOGGER.info(u"Successfully compiled program.") | ||||||
|     port = args.upload_port or choose_serial_port(config) |     port = choose_upload_log_host(default=args.upload_port, check_default=None, | ||||||
|  |                                   show_ota=True, show_mqtt=False, show_api=True) | ||||||
|     exit_code = upload_program(config, args, port) |     exit_code = upload_program(config, args, port) | ||||||
|     if exit_code != 0: |     if exit_code != 0: | ||||||
|         return exit_code |         return exit_code | ||||||
|     _LOGGER.info(u"Successfully uploaded program.") |     _LOGGER.info(u"Successfully uploaded program.") | ||||||
|     if args.no_logs: |     if args.no_logs: | ||||||
|         return 0 |         return 0 | ||||||
|  |     port = choose_upload_log_host(default=args.upload_port, check_default=port, | ||||||
|  |                                   show_ota=False, show_mqtt=True, show_api=True) | ||||||
|     return show_logs(config, args, port) |     return show_logs(config, args, port) | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -290,6 +290,7 @@ message SubscribeLogsResponse { | |||||||
|   LogLevel level = 1; |   LogLevel level = 1; | ||||||
|   string tag = 2; |   string tag = 2; | ||||||
|   string message = 3; |   string message = 3; | ||||||
|  |   bool send_failed = 4; | ||||||
| } | } | ||||||
|  |  | ||||||
| message SubscribeServiceCallsRequest { | message SubscribeServiceCallsRequest { | ||||||
|   | |||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -13,7 +13,7 @@ from esphomeyaml import const | |||||||
| import esphomeyaml.api.api_pb2 as pb | import esphomeyaml.api.api_pb2 as pb | ||||||
| from esphomeyaml.const import CONF_PASSWORD, CONF_PORT | from esphomeyaml.const import CONF_PASSWORD, CONF_PORT | ||||||
| from esphomeyaml.core import EsphomeyamlError | from esphomeyaml.core import EsphomeyamlError | ||||||
| from esphomeyaml.helpers import resolve_ip_address | from esphomeyaml.helpers import resolve_ip_address, indent, color | ||||||
| from esphomeyaml.util import safe_print | from esphomeyaml.util import safe_print | ||||||
|  |  | ||||||
| _LOGGER = logging.getLogger(__name__) | _LOGGER = logging.getLogger(__name__) | ||||||
| @@ -100,6 +100,8 @@ class APIClient(threading.Thread): | |||||||
|         self._port = port  # type: int |         self._port = port  # type: int | ||||||
|         self._password = password  # type: Optional[str] |         self._password = password  # type: Optional[str] | ||||||
|         self._socket = None  # type: Optional[socket.socket] |         self._socket = None  # type: Optional[socket.socket] | ||||||
|  |         self._socket_open_event = threading.Event() | ||||||
|  |         self._socket_write_lock = threading.Lock() | ||||||
|         self._connected = False |         self._connected = False | ||||||
|         self._authenticated = False |         self._authenticated = False | ||||||
|         self._message_handlers = [] |         self._message_handlers = [] | ||||||
| @@ -111,9 +113,8 @@ class APIClient(threading.Thread): | |||||||
|         self.on_connect = None |         self.on_connect = None | ||||||
|         self.on_login = None |         self.on_login = None | ||||||
|         self.auto_reconnect = False |         self.auto_reconnect = False | ||||||
|         self._running = False |         self._running_event = threading.Event() | ||||||
|         self._stop_event = threading.Event() |         self._stop_event = threading.Event() | ||||||
|         self._socket_open = False |  | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def stopped(self): |     def stopped(self): | ||||||
| @@ -131,12 +132,28 @@ class APIClient(threading.Thread): | |||||||
|                 try: |                 try: | ||||||
|                     self.ping() |                     self.ping() | ||||||
|                 except APIConnectionError: |                 except APIConnectionError: | ||||||
|                     self._on_error() |                     self._fatal_error() | ||||||
|             self._refresh_ping() |                 else: | ||||||
|  |                     self._refresh_ping() | ||||||
|  |  | ||||||
|         self._ping_timer = threading.Timer(self._keepalive, func) |         self._ping_timer = threading.Timer(self._keepalive, func) | ||||||
|         self._ping_timer.start() |         self._ping_timer.start() | ||||||
|  |  | ||||||
|  |     def _cancel_ping(self): | ||||||
|  |         if self._ping_timer is not None: | ||||||
|  |             self._ping_timer.cancel() | ||||||
|  |             self._ping_timer = None | ||||||
|  |  | ||||||
|  |     def _close_socket(self): | ||||||
|  |         self._cancel_ping() | ||||||
|  |         if self._socket is not None: | ||||||
|  |             self._socket.close() | ||||||
|  |             self._socket = None | ||||||
|  |         self._socket_open_event.clear() | ||||||
|  |         self._connected = False | ||||||
|  |         self._authenticated = False | ||||||
|  |         self._message_handlers = [] | ||||||
|  |  | ||||||
|     def stop(self, force=False): |     def stop(self, force=False): | ||||||
|         if self.stopped: |         if self.stopped: | ||||||
|             raise ValueError |             raise ValueError | ||||||
| @@ -146,29 +163,19 @@ class APIClient(threading.Thread): | |||||||
|                 self.disconnect() |                 self.disconnect() | ||||||
|             except APIConnectionError: |             except APIConnectionError: | ||||||
|                 pass |                 pass | ||||||
|         if self._socket is not None: |         self._close_socket() | ||||||
|             self._socket.close() |  | ||||||
|             self._socket = None |  | ||||||
|  |  | ||||||
|         self._stop_event.set() |         self._stop_event.set() | ||||||
|         if self._ping_timer is not None: |  | ||||||
|             self._ping_timer.cancel() |  | ||||||
|             self._ping_timer = None |  | ||||||
|         if not force: |         if not force: | ||||||
|             self.join() |             self.join() | ||||||
|  |  | ||||||
|     def connect(self): |     def connect(self): | ||||||
|         if not self._running: |         if not self._running_event.wait(0.1): | ||||||
|             raise APIConnectionError("You need to call start() first!") |             raise APIConnectionError("You need to call start() first!") | ||||||
|  |  | ||||||
|         if self._connected: |         if self._connected: | ||||||
|             raise APIConnectionError("Already 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: |         try: | ||||||
|             ip = resolve_ip_address(self._address) |             ip = resolve_ip_address(self._address) | ||||||
|         except EsphomeyamlError as err: |         except EsphomeyamlError as err: | ||||||
| @@ -179,21 +186,24 @@ class APIClient(threading.Thread): | |||||||
|             raise APIConnectionError(err) |             raise APIConnectionError(err) | ||||||
|  |  | ||||||
|         _LOGGER.info("Connecting to %s:%s (%s)", self._address, self._port, ip) |         _LOGGER.info("Connecting to %s:%s (%s)", self._address, self._port, ip) | ||||||
|  |         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: |         try: | ||||||
|             self._socket.connect((ip, self._port)) |             self._socket.connect((ip, self._port)) | ||||||
|         except socket.error as err: |         except socket.error as err: | ||||||
|             self._on_error() |             self._fatal_error() | ||||||
|             raise APIConnectionError("Error connecting to {}: {}".format(ip, err)) |             raise APIConnectionError("Error connecting to {}: {}".format(ip, err)) | ||||||
|         self._socket_open = True |  | ||||||
|  |  | ||||||
|         self._socket.settimeout(0.1) |         self._socket.settimeout(0.1) | ||||||
|  |  | ||||||
|  |         self._socket_open_event.set() | ||||||
|  |  | ||||||
|         hello = pb.HelloRequest() |         hello = pb.HelloRequest() | ||||||
|         hello.client_info = 'esphomeyaml v{}'.format(const.__version__) |         hello.client_info = 'esphomeyaml v{}'.format(const.__version__) | ||||||
|         try: |         try: | ||||||
|             resp = self._send_message_await_response(hello, pb.HelloResponse) |             resp = self._send_message_await_response(hello, pb.HelloResponse) | ||||||
|         except APIConnectionError as err: |         except APIConnectionError as err: | ||||||
|             self._on_error() |             self._fatal_error() | ||||||
|             raise err |             raise err | ||||||
|         _LOGGER.debug("Successfully connected to %s ('%s' API=%s.%s)", self._address, |         _LOGGER.debug("Successfully connected to %s ('%s' API=%s.%s)", self._address, | ||||||
|                       resp.server_info, resp.api_version_major, resp.api_version_minor) |                       resp.server_info, resp.api_version_major, resp.api_version_minor) | ||||||
| @@ -203,7 +213,7 @@ class APIClient(threading.Thread): | |||||||
|  |  | ||||||
|     def _check_connected(self): |     def _check_connected(self): | ||||||
|         if not self._connected: |         if not self._connected: | ||||||
|             self._on_error() |             self._fatal_error() | ||||||
|             raise APIConnectionError("Must be connected!") |             raise APIConnectionError("Must be connected!") | ||||||
|  |  | ||||||
|     def login(self): |     def login(self): | ||||||
| @@ -222,25 +232,25 @@ class APIClient(threading.Thread): | |||||||
|         if self.on_login is not None: |         if self.on_login is not None: | ||||||
|             self.on_login() |             self.on_login() | ||||||
|  |  | ||||||
|     def _on_error(self): |     def _fatal_error(self): | ||||||
|         if self._connected and self.on_disconnect is not None: |         was_connected = self._connected | ||||||
|  |  | ||||||
|  |         self._close_socket() | ||||||
|  |  | ||||||
|  |         if was_connected and self.on_disconnect is not None: | ||||||
|             self.on_disconnect() |             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 |     def _write(self, data):  # type: (bytes) -> None | ||||||
|  |         if self._socket is None: | ||||||
|  |             raise APIConnectionError("Socket closed") | ||||||
|  |  | ||||||
|         _LOGGER.debug("Write: %s", ' '.join('{:02X}'.format(ord(x)) for x in data)) |         _LOGGER.debug("Write: %s", ' '.join('{:02X}'.format(ord(x)) for x in data)) | ||||||
|         try: |         with self._socket_write_lock: | ||||||
|             self._socket.sendall(data) |             try: | ||||||
|         except socket.error as err: |                 self._socket.sendall(data) | ||||||
|             self._on_error() |             except socket.error as err: | ||||||
|             raise APIConnectionError("Error while writing data: {}".format(err)) |                 self._fatal_error() | ||||||
|  |                 raise APIConnectionError("Error while writing data: {}".format(err)) | ||||||
|  |  | ||||||
|     def _send_message(self, msg): |     def _send_message(self, msg): | ||||||
|         # type: (message.Message) -> None |         # type: (message.Message) -> None | ||||||
| @@ -251,7 +261,7 @@ class APIClient(threading.Thread): | |||||||
|             raise ValueError |             raise ValueError | ||||||
|  |  | ||||||
|         encoded = msg.SerializeToString() |         encoded = msg.SerializeToString() | ||||||
|         _LOGGER.debug("Sending %s: %s", type(message), unicode(message)) |         _LOGGER.debug("Sending %s:\n%s", type(msg), indent(unicode(msg))) | ||||||
|         req = chr(0x00) |         req = chr(0x00) | ||||||
|         req += _varuint_to_bytes(len(encoded)) |         req += _varuint_to_bytes(len(encoded)) | ||||||
|         req += _varuint_to_bytes(message_type) |         req += _varuint_to_bytes(message_type) | ||||||
| @@ -302,11 +312,8 @@ class APIClient(threading.Thread): | |||||||
|             self._send_message_await_response(pb.DisconnectRequest(), pb.DisconnectResponse) |             self._send_message_await_response(pb.DisconnectRequest(), pb.DisconnectResponse) | ||||||
|         except APIConnectionError: |         except APIConnectionError: | ||||||
|             pass |             pass | ||||||
|         if self._socket is not None: |         self._close_socket() | ||||||
|             self._socket.close() |  | ||||||
|             self._socket = None |  | ||||||
|             self._socket_open = False |  | ||||||
|             self._connected = False |  | ||||||
|         if self.on_disconnect is not None: |         if self.on_disconnect is not None: | ||||||
|             self.on_disconnect() |             self.on_disconnect() | ||||||
|  |  | ||||||
| @@ -335,7 +342,7 @@ class APIClient(threading.Thread): | |||||||
|         while len(ret) < amount: |         while len(ret) < amount: | ||||||
|             if self.stopped: |             if self.stopped: | ||||||
|                 raise APIConnectionError("Stopped!") |                 raise APIConnectionError("Stopped!") | ||||||
|             if self._socket is None or not self._socket_open: |             if not self._socket_open_event.is_set(): | ||||||
|                 raise APIConnectionError("No socket!") |                 raise APIConnectionError("No socket!") | ||||||
|             try: |             try: | ||||||
|                 val = self._socket.recv(amount - len(ret)) |                 val = self._socket.recv(amount - len(ret)) | ||||||
| @@ -353,8 +360,7 @@ class APIClient(threading.Thread): | |||||||
|         return _bytes_to_varuint(raw) |         return _bytes_to_varuint(raw) | ||||||
|  |  | ||||||
|     def _run_once(self): |     def _run_once(self): | ||||||
|         if self._socket is None or not self._socket_open: |         if not self._socket_open_event.wait(0.1): | ||||||
|             time.sleep(0.1) |  | ||||||
|             return |             return | ||||||
|  |  | ||||||
|         # Preamble |         # Preamble | ||||||
| @@ -371,14 +377,14 @@ class APIClient(threading.Thread): | |||||||
|  |  | ||||||
|         msg = MESSAGE_TYPE_TO_PROTO[msg_type]() |         msg = MESSAGE_TYPE_TO_PROTO[msg_type]() | ||||||
|         msg.ParseFromString(raw_msg) |         msg.ParseFromString(raw_msg) | ||||||
|         _LOGGER.debug("Got message of type %s: %s", type(msg), msg) |         _LOGGER.debug("Got message: %s:\n%s", type(msg), indent(str(msg))) | ||||||
|         for msg_handler in self._message_handlers[:]: |         for msg_handler in self._message_handlers[:]: | ||||||
|             msg_handler(msg) |             msg_handler(msg) | ||||||
|         self._handle_internal_messages(msg) |         self._handle_internal_messages(msg) | ||||||
|         self._refresh_ping() |         self._refresh_ping() | ||||||
|  |  | ||||||
|     def run(self): |     def run(self): | ||||||
|         self._running = True |         self._running_event.set() | ||||||
|         while not self.stopped: |         while not self.stopped: | ||||||
|             try: |             try: | ||||||
|                 self._run_once() |                 self._run_once() | ||||||
| @@ -387,8 +393,8 @@ class APIClient(threading.Thread): | |||||||
|                     break |                     break | ||||||
|                 if self._connected: |                 if self._connected: | ||||||
|                     _LOGGER.error("Error while reading incoming messages: %s", err) |                     _LOGGER.error("Error while reading incoming messages: %s", err) | ||||||
|                     self._on_error() |                     self._fatal_error() | ||||||
|         self._running = False |         self._running_event.clear() | ||||||
|  |  | ||||||
|     def _handle_internal_messages(self, msg): |     def _handle_internal_messages(self, msg): | ||||||
|         if isinstance(msg, pb.DisconnectRequest): |         if isinstance(msg, pb.DisconnectRequest): | ||||||
| @@ -397,7 +403,6 @@ class APIClient(threading.Thread): | |||||||
|                 self._socket.close() |                 self._socket.close() | ||||||
|                 self._socket = None |                 self._socket = None | ||||||
|             self._connected = False |             self._connected = False | ||||||
|             self._socket_open = False |  | ||||||
|             if self.on_disconnect is not None: |             if self.on_disconnect is not None: | ||||||
|                 self.on_disconnect() |                 self.on_disconnect() | ||||||
|         elif isinstance(msg, pb.PingRequest): |         elif isinstance(msg, pb.PingRequest): | ||||||
| @@ -428,26 +433,29 @@ def run_logs(config, address): | |||||||
|         while retry_timer: |         while retry_timer: | ||||||
|             retry_timer.pop(0).cancel() |             retry_timer.pop(0).cancel() | ||||||
|  |  | ||||||
|         error = None |  | ||||||
|         try: |         try: | ||||||
|             cli.connect() |             cli.connect() | ||||||
|             cli.login() |             cli.login() | ||||||
|         except APIConnectionError as error: |         except APIConnectionError as error: | ||||||
|             pass |             pass | ||||||
|  |         else: | ||||||
|         if error is None: |  | ||||||
|             _LOGGER.info("Successfully connected to %s", address) |             _LOGGER.info("Successfully connected to %s", address) | ||||||
|             return |             return | ||||||
|  |  | ||||||
|         wait_time = min(2**tries, 300) |         wait_time = min(2**tries, 300) | ||||||
|         _LOGGER.warning(u"Couldn't connect to API. Trying to reconnect in %s seconds", wait_time) |         _LOGGER.warning(u"Couldn't connect to API (%s). Trying to reconnect in %s seconds", | ||||||
|  |                         error, wait_time) | ||||||
|         timer = threading.Timer(wait_time, functools.partial(try_connect, tries + 1, is_disconnect)) |         timer = threading.Timer(wait_time, functools.partial(try_connect, tries + 1, is_disconnect)) | ||||||
|         timer.start() |         timer.start() | ||||||
|         retry_timer.append(timer) |         retry_timer.append(timer) | ||||||
|  |  | ||||||
|     def on_log(msg): |     def on_log(msg): | ||||||
|         time_ = datetime.now().time().strftime(u'[%H:%M:%S]') |         time_ = datetime.now().time().strftime(u'[%H:%M:%S]') | ||||||
|         safe_print(time_ + msg.message) |         text = msg.message | ||||||
|  |         if msg.send_failed: | ||||||
|  |             text = color('white', '(Message not received because it was too big to fit in ' | ||||||
|  |                                   'TCP buffer)') | ||||||
|  |         safe_print(time_ + text) | ||||||
|  |  | ||||||
|     has_connects = [] |     has_connects = [] | ||||||
|  |  | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ from esphomeyaml.automation import ACTION_REGISTRY, LambdaAction | |||||||
| import esphomeyaml.config_validation as cv | import esphomeyaml.config_validation as cv | ||||||
| from esphomeyaml.const import CONF_ARGS, CONF_BAUD_RATE, CONF_FORMAT, CONF_ID, CONF_LEVEL, \ | from esphomeyaml.const import CONF_ARGS, CONF_BAUD_RATE, CONF_FORMAT, CONF_ID, CONF_LEVEL, \ | ||||||
|     CONF_LOGS, CONF_TAG, CONF_TX_BUFFER_SIZE |     CONF_LOGS, CONF_TAG, CONF_TX_BUFFER_SIZE | ||||||
| from esphomeyaml.core import EsphomeyamlError, Lambda | from esphomeyaml.core import EsphomeyamlError, Lambda, CORE | ||||||
| from esphomeyaml.cpp_generator import Pvariable, RawExpression, add, process_lambda, statement | from esphomeyaml.cpp_generator import Pvariable, RawExpression, add, process_lambda, statement | ||||||
| from esphomeyaml.cpp_types import App, Component, esphomelib_ns, global_ns | from esphomeyaml.cpp_types import App, Component, esphomelib_ns, global_ns | ||||||
|  |  | ||||||
| @@ -69,9 +69,15 @@ def to_code(config): | |||||||
|  |  | ||||||
|  |  | ||||||
| def required_build_flags(config): | def required_build_flags(config): | ||||||
|  |     flags = [] | ||||||
|     if CONF_LEVEL in config: |     if CONF_LEVEL in config: | ||||||
|         return u'-DESPHOMELIB_LOG_LEVEL={}'.format(str(LOG_LEVELS[config[CONF_LEVEL]])) |         flags.append(u'-DESPHOMELIB_LOG_LEVEL={}'.format(str(LOG_LEVELS[config[CONF_LEVEL]]))) | ||||||
|     return None |         this_severity = LOG_LEVEL_SEVERITY.index(config[CONF_LEVEL]) | ||||||
|  |         verbose_severity = LOG_LEVEL_SEVERITY.index('VERBOSE') | ||||||
|  |         if CORE.is_esp8266 and config.get(CONF_BAUD_RATE) != 0 and \ | ||||||
|  |                 this_severity >= verbose_severity: | ||||||
|  |             flags.append(u"-DDEBUG_ESP_PORT=Serial") | ||||||
|  |     return flags | ||||||
|  |  | ||||||
|  |  | ||||||
| def maybe_simple_message(schema): | def maybe_simple_message(schema): | ||||||
|   | |||||||
| @@ -46,13 +46,13 @@ FILTERS_SCHEMA = cv.ensure_list({ | |||||||
|     vol.Optional(CONF_FILTER_OUT): cv.float_, |     vol.Optional(CONF_FILTER_OUT): cv.float_, | ||||||
|     vol.Optional(CONF_FILTER_NAN): None, |     vol.Optional(CONF_FILTER_NAN): None, | ||||||
|     vol.Optional(CONF_SLIDING_WINDOW_MOVING_AVERAGE): vol.All(vol.Schema({ |     vol.Optional(CONF_SLIDING_WINDOW_MOVING_AVERAGE): vol.All(vol.Schema({ | ||||||
|         vol.Required(CONF_WINDOW_SIZE): cv.positive_not_null_int, |         vol.Optional(CONF_WINDOW_SIZE, default=15): cv.positive_not_null_int, | ||||||
|         vol.Required(CONF_SEND_EVERY): cv.positive_not_null_int, |         vol.Optional(CONF_SEND_EVERY, default=15): cv.positive_not_null_int, | ||||||
|         vol.Optional(CONF_SEND_FIRST_AT): cv.positive_not_null_int, |         vol.Optional(CONF_SEND_FIRST_AT): cv.positive_not_null_int, | ||||||
|     }), validate_send_first_at), |     }), validate_send_first_at), | ||||||
|     vol.Optional(CONF_EXPONENTIAL_MOVING_AVERAGE): vol.Schema({ |     vol.Optional(CONF_EXPONENTIAL_MOVING_AVERAGE): vol.Schema({ | ||||||
|         vol.Required(CONF_ALPHA): cv.positive_float, |         vol.Optional(CONF_ALPHA, default=0.1): cv.positive_float, | ||||||
|         vol.Required(CONF_SEND_EVERY): cv.positive_not_null_int, |         vol.Optional(CONF_SEND_EVERY, default=15): cv.positive_not_null_int, | ||||||
|     }), |     }), | ||||||
|     vol.Optional(CONF_LAMBDA): cv.lambda_, |     vol.Optional(CONF_LAMBDA): cv.lambda_, | ||||||
|     vol.Optional(CONF_THROTTLE): cv.positive_time_period_milliseconds, |     vol.Optional(CONF_THROTTLE): cv.positive_time_period_milliseconds, | ||||||
|   | |||||||
| @@ -62,11 +62,10 @@ WIFI_NETWORK_BASE = vol.Schema({ | |||||||
| }) | }) | ||||||
|  |  | ||||||
| WIFI_NETWORK_AP = WIFI_NETWORK_BASE.extend({ | WIFI_NETWORK_AP = WIFI_NETWORK_BASE.extend({ | ||||||
|     vol.Optional(CONF_MANUAL_IP): AP_MANUAL_IP_SCHEMA, |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| WIFI_NETWORK_STA = 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, |     vol.Optional(CONF_BSSID): cv.mac_address, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| @@ -79,8 +78,6 @@ def validate(config): | |||||||
|         network = {CONF_SSID: config.pop(CONF_SSID)} |         network = {CONF_SSID: config.pop(CONF_SSID)} | ||||||
|         if CONF_PASSWORD in config: |         if CONF_PASSWORD in config: | ||||||
|             network[CONF_PASSWORD] = config.pop(CONF_PASSWORD) |             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: |         if CONF_NETWORKS in config: | ||||||
|             raise vol.Invalid("You cannot use the 'ssid:' option together with 'networks:'. Please " |             raise vol.Invalid("You cannot use the 'ssid:' option together with 'networks:'. Please " | ||||||
|                               "copy your network into the 'networks:' key") |                               "copy your network into the 'networks:' key") | ||||||
| @@ -127,7 +124,7 @@ def manual_ip(config): | |||||||
|     ) |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
| def wifi_network(config): | def wifi_network(config, static_ip): | ||||||
|     ap = variable(config[CONF_ID], WiFiAP()) |     ap = variable(config[CONF_ID], WiFiAP()) | ||||||
|     if CONF_SSID in config: |     if CONF_SSID in config: | ||||||
|         add(ap.set_ssid(config[CONF_SSID])) |         add(ap.set_ssid(config[CONF_SSID])) | ||||||
| @@ -138,21 +135,28 @@ def wifi_network(config): | |||||||
|         add(ap.set_bssid(ArrayInitializer(*bssid, multiline=False))) |         add(ap.set_bssid(ArrayInitializer(*bssid, multiline=False))) | ||||||
|     if CONF_CHANNEL in config: |     if CONF_CHANNEL in config: | ||||||
|         add(ap.set_channel(config[CONF_CHANNEL])) |         add(ap.set_channel(config[CONF_CHANNEL])) | ||||||
|     if CONF_MANUAL_IP in config: |     if static_ip is not None: | ||||||
|         add(ap.set_manual_ip(manual_ip(config[CONF_MANUAL_IP]))) |         add(ap.set_manual_ip(manual_ip(static_ip))) | ||||||
|  |  | ||||||
|     return ap |     return ap | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def get_upload_host(config): | ||||||
|  |     if CONF_MANUAL_IP in config: | ||||||
|  |         return str(config[CONF_MANUAL_IP][CONF_STATIC_IP]) | ||||||
|  |     hostname = config.get(CONF_HOSTNAME) or CORE.name | ||||||
|  |     return hostname + config[CONF_DOMAIN] | ||||||
|  |  | ||||||
|  |  | ||||||
| def to_code(config): | def to_code(config): | ||||||
|     rhs = App.init_wifi() |     rhs = App.init_wifi() | ||||||
|     wifi = Pvariable(config[CONF_ID], rhs) |     wifi = Pvariable(config[CONF_ID], rhs) | ||||||
|  |  | ||||||
|     for network in config.get(CONF_NETWORKS, []): |     for network in config.get(CONF_NETWORKS, []): | ||||||
|         add(wifi.add_sta(wifi_network(network))) |         add(wifi.add_sta(wifi_network(network, config.get(CONF_MANUAL_IP)))) | ||||||
|  |  | ||||||
|     if CONF_AP in config: |     if CONF_AP in config: | ||||||
|         add(wifi.set_ap(wifi_network(config[CONF_AP]))) |         add(wifi.set_ap(wifi_network(config[CONF_AP], config.get(CONF_MANUAL_IP)))) | ||||||
|  |  | ||||||
|     if CONF_HOSTNAME in config: |     if CONF_HOSTNAME in config: | ||||||
|         add(wifi.set_hostname(config[CONF_HOSTNAME])) |         add(wifi.set_hostname(config[CONF_HOSTNAME])) | ||||||
|   | |||||||
| @@ -378,7 +378,10 @@ def validate_config(config): | |||||||
|                     continue |                     continue | ||||||
|                 result[domain][i] = p_validated |                 result[domain][i] = p_validated | ||||||
|  |  | ||||||
|     do_id_pass(result) |     if not result.errors: | ||||||
|  |         # Only parse IDs if no validation error. Otherwise | ||||||
|  |         # user gets confusing messages | ||||||
|  |         do_id_pass(result) | ||||||
|     return result |     return result | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -307,13 +307,9 @@ class EsphomeyamlCore(object): | |||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def address(self):  # type: () -> str |     def address(self):  # type: () -> str | ||||||
|         if CONF_MANUAL_IP in self.config[CONF_WIFI]: |         from esphomeyaml.components import wifi | ||||||
|             return str(self.config[CONF_WIFI][CONF_MANUAL_IP][CONF_STATIC_IP]) |  | ||||||
|         elif CONF_HOSTNAME in self.config[CONF_WIFI]: |         return wifi.get_upload_host(self.config[CONF_WIFI]) | ||||||
|             hostname = self.config[CONF_WIFI][CONF_HOSTNAME] |  | ||||||
|         else: |  | ||||||
|             hostname = self.name |  | ||||||
|         return hostname + self.config[CONF_WIFI][CONF_DOMAIN] |  | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def esphomelib_version(self):  # type: () -> Dict[str, str] |     def esphomelib_version(self):  # type: () -> Dict[str, str] | ||||||
|   | |||||||
| @@ -224,7 +224,7 @@ def perform_ota(sock, password, file_handle, filename): | |||||||
|     _LOGGER.info("OTA successful") |     _LOGGER.info("OTA successful") | ||||||
|  |  | ||||||
|     # Do not connect logs until it is fully on |     # Do not connect logs until it is fully on | ||||||
|     time.sleep(2) |     time.sleep(1) | ||||||
|  |  | ||||||
|  |  | ||||||
| def run_ota_impl_(remote_host, remote_port, password, filename): | def run_ota_impl_(remote_host, remote_port, password, filename): | ||||||
|   | |||||||
| @@ -279,7 +279,7 @@ def gather_lib_deps(): | |||||||
|         # Manual fix for AsyncTCP |         # Manual fix for AsyncTCP | ||||||
|         if CORE.config[CONF_ESPHOMEYAML].get(CONF_ARDUINO_VERSION) == ARDUINO_VERSION_ESP32_DEV: |         if CORE.config[CONF_ESPHOMEYAML].get(CONF_ARDUINO_VERSION) == ARDUINO_VERSION_ESP32_DEV: | ||||||
|             lib_deps.add('https://github.com/me-no-dev/AsyncTCP.git#idf-update') |             lib_deps.add('https://github.com/me-no-dev/AsyncTCP.git#idf-update') | ||||||
|             lib_deps.remove('AsyncTCP@1.0.1') |             lib_deps.discard('AsyncTCP@1.0.1') | ||||||
|     # avoid changing build flags order |     # avoid changing build flags order | ||||||
|     return sorted(x for x in lib_deps if x) |     return sorted(x for x in lib_deps if x) | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user