mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	add-black (#1593)
* Add black Update pre commit Update pre commit add empty line * Format with black
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							2b60b0f1fa
						
					
				
				
					commit
					69879920eb
				
			| @@ -1,11 +1,27 @@ | ||||
| # See https://pre-commit.com for more information | ||||
| # See https://pre-commit.com/hooks.html for more hooks | ||||
| repos: | ||||
| -   repo: https://github.com/pre-commit/pre-commit-hooks | ||||
|     rev: v2.4.0 | ||||
|   - repo: https://github.com/ambv/black | ||||
|     rev: 20.8b1 | ||||
|     hooks: | ||||
|     -   id: trailing-whitespace | ||||
|     -   id: end-of-file-fixer | ||||
|     -   id: check-yaml | ||||
|     -   id: check-added-large-files | ||||
|     -   id: flake8 | ||||
|     - id: black | ||||
|       args: | ||||
|         - --safe | ||||
|         - --quiet | ||||
|       files: ^((esphome|script|tests)/.+)?[^/]+\.py$ | ||||
|   - repo: https://gitlab.com/pycqa/flake8 | ||||
|     rev: 3.8.4 | ||||
|     hooks: | ||||
|       - id: flake8 | ||||
|         additional_dependencies: | ||||
|           - flake8-docstrings==1.5.0 | ||||
|           - pydocstyle==5.1.1 | ||||
|         files: ^(esphome|tests)/.+\.py$ | ||||
|   - repo: https://github.com/pre-commit/pre-commit-hooks | ||||
|     rev: v3.4.0 | ||||
|     hooks: | ||||
|       - id: no-commit-to-branch | ||||
|         args: | ||||
|           - --branch=dev | ||||
|           - --branch=master | ||||
|           - --branch=beta | ||||
|   | ||||
| @@ -8,21 +8,36 @@ from datetime import datetime | ||||
| from esphome import const, writer, yaml_util | ||||
| import esphome.codegen as cg | ||||
| from esphome.config import iter_components, read_config, strip_default_ids | ||||
| from esphome.const import CONF_BAUD_RATE, CONF_BROKER, CONF_LOGGER, CONF_OTA, \ | ||||
|     CONF_PASSWORD, CONF_PORT, CONF_ESPHOME, CONF_PLATFORMIO_OPTIONS | ||||
| from esphome.const import ( | ||||
|     CONF_BAUD_RATE, | ||||
|     CONF_BROKER, | ||||
|     CONF_LOGGER, | ||||
|     CONF_OTA, | ||||
|     CONF_PASSWORD, | ||||
|     CONF_PORT, | ||||
|     CONF_ESPHOME, | ||||
|     CONF_PLATFORMIO_OPTIONS, | ||||
| ) | ||||
| from esphome.core import CORE, EsphomeError, coroutine, coroutine_with_priority | ||||
| from esphome.helpers import color, indent | ||||
| from esphome.util import run_external_command, run_external_process, safe_print, list_yaml_files, \ | ||||
|     get_serial_ports | ||||
| from esphome.util import ( | ||||
|     run_external_command, | ||||
|     run_external_process, | ||||
|     safe_print, | ||||
|     list_yaml_files, | ||||
|     get_serial_ports, | ||||
| ) | ||||
|  | ||||
| _LOGGER = logging.getLogger(__name__) | ||||
|  | ||||
|  | ||||
| def choose_prompt(options): | ||||
|     if not options: | ||||
|         raise EsphomeError("Found no valid options for upload/logging, please make sure relevant " | ||||
|                            "sections (ota, api, mqtt, ...) are in your configuration and/or the " | ||||
|                            "device is plugged in.") | ||||
|         raise EsphomeError( | ||||
|             "Found no valid options for upload/logging, please make sure relevant " | ||||
|             "sections (ota, api, mqtt, ...) are in your configuration and/or the " | ||||
|             "device is plugged in." | ||||
|         ) | ||||
|  | ||||
|     if len(options) == 1: | ||||
|         return options[0][1] | ||||
| @@ -32,7 +47,7 @@ def choose_prompt(options): | ||||
|         safe_print(f"  [{i+1}] {desc}") | ||||
|  | ||||
|     while True: | ||||
|         opt = input('(number): ') | ||||
|         opt = input("(number): ") | ||||
|         if opt in options: | ||||
|             opt = options.index(opt) | ||||
|             break | ||||
| @@ -42,7 +57,7 @@ def choose_prompt(options): | ||||
|                 raise ValueError | ||||
|             break | ||||
|         except ValueError: | ||||
|             safe_print(color('red', f"Invalid option: '{opt}'")) | ||||
|             safe_print(color("red", f"Invalid option: '{opt}'")) | ||||
|     return options[opt - 1][1] | ||||
|  | ||||
|  | ||||
| @@ -50,14 +65,14 @@ def choose_upload_log_host(default, check_default, show_ota, show_mqtt, show_api | ||||
|     options = [] | ||||
|     for port in get_serial_ports(): | ||||
|         options.append((f"{port.path} ({port.description})", port.path)) | ||||
|     if (show_ota and 'ota' in CORE.config) or (show_api and 'api' in CORE.config): | ||||
|     if (show_ota and "ota" in CORE.config) or (show_api and "api" in CORE.config): | ||||
|         options.append((f"Over The Air ({CORE.address})", CORE.address)) | ||||
|         if default == 'OTA': | ||||
|         if default == "OTA": | ||||
|             return CORE.address | ||||
|     if show_mqtt and 'mqtt' in CORE.config: | ||||
|         options.append(("MQTT ({})".format(CORE.config['mqtt'][CONF_BROKER]), 'MQTT')) | ||||
|         if default == 'OTA': | ||||
|             return 'MQTT' | ||||
|     if show_mqtt and "mqtt" in CORE.config: | ||||
|         options.append(("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]: | ||||
| @@ -66,11 +81,11 @@ def choose_upload_log_host(default, check_default, show_ota, show_mqtt, show_api | ||||
|  | ||||
|  | ||||
| def get_port_type(port): | ||||
|     if port.startswith('/') or port.startswith('COM'): | ||||
|         return 'SERIAL' | ||||
|     if port == 'MQTT': | ||||
|         return 'MQTT' | ||||
|     return 'NETWORK' | ||||
|     if port.startswith("/") or port.startswith("COM"): | ||||
|         return "SERIAL" | ||||
|     if port == "MQTT": | ||||
|         return "MQTT" | ||||
|     return "NETWORK" | ||||
|  | ||||
|  | ||||
| def run_miniterm(config, port): | ||||
| @@ -80,7 +95,7 @@ def run_miniterm(config, port): | ||||
|     if CONF_LOGGER not in config: | ||||
|         _LOGGER.info("Logger is not enabled. Not starting UART logs.") | ||||
|         return | ||||
|     baud_rate = config['logger'][CONF_BAUD_RATE] | ||||
|     baud_rate = config["logger"][CONF_BAUD_RATE] | ||||
|     if baud_rate == 0: | ||||
|         _LOGGER.info("UART logging is disabled (baud_rate=0). Not starting UART logs.") | ||||
|     _LOGGER.info("Starting log output from %s with baud rate %s", port, baud_rate) | ||||
| @@ -93,13 +108,18 @@ def run_miniterm(config, port): | ||||
|             except serial.SerialException: | ||||
|                 _LOGGER.error("Serial port closed!") | ||||
|                 return | ||||
|             line = raw.replace(b'\r', b'').replace(b'\n', b'').decode('utf8', 'backslashreplace') | ||||
|             time = datetime.now().time().strftime('[%H:%M:%S]') | ||||
|             line = ( | ||||
|                 raw.replace(b"\r", b"") | ||||
|                 .replace(b"\n", b"") | ||||
|                 .decode("utf8", "backslashreplace") | ||||
|             ) | ||||
|             time = datetime.now().time().strftime("[%H:%M:%S]") | ||||
|             message = time + line | ||||
|             safe_print(message) | ||||
|  | ||||
|             backtrace_state = platformio_api.process_stacktrace( | ||||
|                 config, line, backtrace_state=backtrace_state) | ||||
|                 config, line, backtrace_state=backtrace_state | ||||
|             ) | ||||
|  | ||||
|  | ||||
| def wrap_to_code(name, comp): | ||||
| @@ -111,7 +131,7 @@ def wrap_to_code(name, comp): | ||||
|         cg.add(cg.LineComment(f"{name}:")) | ||||
|         if comp.config_schema is not None: | ||||
|             conf_str = yaml_util.dump(conf) | ||||
|             conf_str = conf_str.replace('//', '') | ||||
|             conf_str = conf_str.replace("//", "") | ||||
|             cg.add(cg.LineComment(indent(conf_str))) | ||||
|         yield coro(conf) | ||||
|  | ||||
| @@ -151,15 +171,31 @@ def compile_program(args, config): | ||||
|  | ||||
| def upload_using_esptool(config, port): | ||||
|     path = CORE.firmware_bin | ||||
|     first_baudrate = config[CONF_ESPHOME][CONF_PLATFORMIO_OPTIONS].get('upload_speed', 460800) | ||||
|     first_baudrate = config[CONF_ESPHOME][CONF_PLATFORMIO_OPTIONS].get( | ||||
|         "upload_speed", 460800 | ||||
|     ) | ||||
|  | ||||
|     def run_esptool(baud_rate): | ||||
|         cmd = ['esptool.py', '--before', 'default_reset', '--after', 'hard_reset', | ||||
|                '--baud', str(baud_rate), | ||||
|                '--chip', 'esp8266', '--port', port, 'write_flash', '0x0', path] | ||||
|         cmd = [ | ||||
|             "esptool.py", | ||||
|             "--before", | ||||
|             "default_reset", | ||||
|             "--after", | ||||
|             "hard_reset", | ||||
|             "--baud", | ||||
|             str(baud_rate), | ||||
|             "--chip", | ||||
|             "esp8266", | ||||
|             "--port", | ||||
|             port, | ||||
|             "write_flash", | ||||
|             "0x0", | ||||
|             path, | ||||
|         ] | ||||
|  | ||||
|         if os.environ.get('ESPHOME_USE_SUBPROCESS') is None: | ||||
|         if os.environ.get("ESPHOME_USE_SUBPROCESS") is None: | ||||
|             import esptool | ||||
|  | ||||
|             # pylint: disable=protected-access | ||||
|             return run_external_command(esptool._main, *cmd) | ||||
|  | ||||
| @@ -169,14 +205,16 @@ def upload_using_esptool(config, port): | ||||
|     if rc == 0 or first_baudrate == 115200: | ||||
|         return rc | ||||
|     # Try with 115200 baud rate, with some serial chips the faster baud rates do not work well | ||||
|     _LOGGER.info("Upload with baud rate %s failed. Trying again with baud rate 115200.", | ||||
|                  first_baudrate) | ||||
|     _LOGGER.info( | ||||
|         "Upload with baud rate %s failed. Trying again with baud rate 115200.", | ||||
|         first_baudrate, | ||||
|     ) | ||||
|     return run_esptool(115200) | ||||
|  | ||||
|  | ||||
| def upload_program(config, args, host): | ||||
|     # if upload is to a serial port use platformio, otherwise assume ota | ||||
|     if get_port_type(host) == 'SERIAL': | ||||
|     if get_port_type(host) == "SERIAL": | ||||
|         from esphome import platformio_api | ||||
|  | ||||
|         if CORE.is_esp8266: | ||||
| @@ -186,8 +224,10 @@ def upload_program(config, args, host): | ||||
|     from esphome import espota2 | ||||
|  | ||||
|     if CONF_OTA not in config: | ||||
|         raise EsphomeError("Cannot upload Over the Air as the config does not include the ota: " | ||||
|                            "component") | ||||
|         raise EsphomeError( | ||||
|             "Cannot upload Over the Air as the config does not include the ota: " | ||||
|             "component" | ||||
|         ) | ||||
|  | ||||
|     ota_conf = config[CONF_OTA] | ||||
|     remote_port = ota_conf[CONF_PORT] | ||||
| @@ -196,19 +236,21 @@ def upload_program(config, args, host): | ||||
|  | ||||
|  | ||||
| def show_logs(config, args, port): | ||||
|     if 'logger' not in config: | ||||
|     if "logger" not in config: | ||||
|         raise EsphomeError("Logger is not configured!") | ||||
|     if get_port_type(port) == 'SERIAL': | ||||
|     if get_port_type(port) == "SERIAL": | ||||
|         run_miniterm(config, port) | ||||
|         return 0 | ||||
|     if get_port_type(port) == 'NETWORK' and 'api' in config: | ||||
|     if get_port_type(port) == "NETWORK" and "api" in config: | ||||
|         from esphome.api.client import run_logs | ||||
|  | ||||
|         return run_logs(config, port) | ||||
|     if get_port_type(port) == 'MQTT' and 'mqtt' in config: | ||||
|     if get_port_type(port) == "MQTT" and "mqtt" in config: | ||||
|         from esphome import mqtt | ||||
|  | ||||
|         return mqtt.show_logs(config, args.topic, args.username, args.password, args.client_id) | ||||
|         return mqtt.show_logs( | ||||
|             config, args.topic, args.username, args.password, args.client_id | ||||
|         ) | ||||
|  | ||||
|     raise EsphomeError("No remote or local logging method configured (api/mqtt/logger)") | ||||
|  | ||||
| @@ -216,7 +258,9 @@ def show_logs(config, args, port): | ||||
| def clean_mqtt(config, args): | ||||
|     from esphome import mqtt | ||||
|  | ||||
|     return mqtt.clear_topic(config, args.topic, args.username, args.password, args.client_id) | ||||
|     return mqtt.clear_topic( | ||||
|         config, args.topic, args.username, args.password, args.client_id | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def setup_log(debug=False, quiet=False): | ||||
| @@ -230,27 +274,31 @@ def setup_log(debug=False, quiet=False): | ||||
|     logging.basicConfig(level=log_level) | ||||
|     fmt = "%(levelname)s %(message)s" | ||||
|     colorfmt = f"%(log_color)s{fmt}%(reset)s" | ||||
|     datefmt = '%H:%M:%S' | ||||
|     datefmt = "%H:%M:%S" | ||||
|  | ||||
|     logging.getLogger('urllib3').setLevel(logging.WARNING) | ||||
|     logging.getLogger("urllib3").setLevel(logging.WARNING) | ||||
|  | ||||
|     try: | ||||
|         import colorama | ||||
|  | ||||
|         colorama.init(strip=True) | ||||
|  | ||||
|         from colorlog import ColoredFormatter | ||||
|         logging.getLogger().handlers[0].setFormatter(ColoredFormatter( | ||||
|             colorfmt, | ||||
|             datefmt=datefmt, | ||||
|             reset=True, | ||||
|             log_colors={ | ||||
|                 'DEBUG': 'cyan', | ||||
|                 'INFO': 'green', | ||||
|                 'WARNING': 'yellow', | ||||
|                 'ERROR': 'red', | ||||
|                 'CRITICAL': 'red', | ||||
|             } | ||||
|         )) | ||||
|  | ||||
|         logging.getLogger().handlers[0].setFormatter( | ||||
|             ColoredFormatter( | ||||
|                 colorfmt, | ||||
|                 datefmt=datefmt, | ||||
|                 reset=True, | ||||
|                 log_colors={ | ||||
|                     "DEBUG": "cyan", | ||||
|                     "INFO": "green", | ||||
|                     "WARNING": "yellow", | ||||
|                     "ERROR": "red", | ||||
|                     "CRITICAL": "red", | ||||
|                 }, | ||||
|             ) | ||||
|         ) | ||||
|     except ImportError: | ||||
|         pass | ||||
|  | ||||
| @@ -291,8 +339,13 @@ def command_compile(args, config): | ||||
|  | ||||
|  | ||||
| def command_upload(args, config): | ||||
|     port = choose_upload_log_host(default=args.upload_port, check_default=None, | ||||
|                                   show_ota=True, show_mqtt=False, show_api=False) | ||||
|     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) | ||||
|     if exit_code != 0: | ||||
|         return exit_code | ||||
| @@ -301,8 +354,13 @@ def command_upload(args, config): | ||||
|  | ||||
|  | ||||
| def command_logs(args, config): | ||||
|     port = choose_upload_log_host(default=args.serial_port, check_default=None, | ||||
|                                   show_ota=False, show_mqtt=True, show_api=True) | ||||
|     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) | ||||
|  | ||||
|  | ||||
| @@ -314,16 +372,26 @@ def command_run(args, config): | ||||
|     if exit_code != 0: | ||||
|         return exit_code | ||||
|     _LOGGER.info("Successfully compiled program.") | ||||
|     port = choose_upload_log_host(default=args.upload_port, check_default=None, | ||||
|                                   show_ota=True, show_mqtt=False, show_api=True) | ||||
|     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) | ||||
|     if exit_code != 0: | ||||
|         return exit_code | ||||
|     _LOGGER.info("Successfully uploaded program.") | ||||
|     if args.no_logs: | ||||
|         return 0 | ||||
|     port = choose_upload_log_host(default=args.upload_port, check_default=port, | ||||
|                                   show_ota=False, show_mqtt=True, show_api=True) | ||||
|     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) | ||||
|  | ||||
|  | ||||
| @@ -372,137 +440,189 @@ def command_update_all(args): | ||||
|         click.echo(f"{half_line}{middle_text}{half_line}") | ||||
|  | ||||
|     for f in files: | ||||
|         print("Updating {}".format(color('cyan', f))) | ||||
|         print('-' * twidth) | ||||
|         print("Updating {}".format(color("cyan", f))) | ||||
|         print("-" * twidth) | ||||
|         print() | ||||
|         rc = run_external_process('esphome', '--dashboard', f, 'run', '--no-logs', '--upload-port', | ||||
|                                   'OTA') | ||||
|         rc = run_external_process( | ||||
|             "esphome", "--dashboard", f, "run", "--no-logs", "--upload-port", "OTA" | ||||
|         ) | ||||
|         if rc == 0: | ||||
|             print_bar("[{}] {}".format(color('bold_green', 'SUCCESS'), f)) | ||||
|             print_bar("[{}] {}".format(color("bold_green", "SUCCESS"), f)) | ||||
|             success[f] = True | ||||
|         else: | ||||
|             print_bar("[{}] {}".format(color('bold_red', 'ERROR'), f)) | ||||
|             print_bar("[{}] {}".format(color("bold_red", "ERROR"), f)) | ||||
|             success[f] = False | ||||
|  | ||||
|         print() | ||||
|         print() | ||||
|         print() | ||||
|  | ||||
|     print_bar('[{}]'.format(color('bold_white', 'SUMMARY'))) | ||||
|     print_bar("[{}]".format(color("bold_white", "SUMMARY"))) | ||||
|     failed = 0 | ||||
|     for f in files: | ||||
|         if success[f]: | ||||
|             print("  - {}: {}".format(f, color('green', 'SUCCESS'))) | ||||
|             print("  - {}: {}".format(f, color("green", "SUCCESS"))) | ||||
|         else: | ||||
|             print("  - {}: {}".format(f, color('bold_red', 'FAILED'))) | ||||
|             print("  - {}: {}".format(f, color("bold_red", "FAILED"))) | ||||
|             failed += 1 | ||||
|     return failed | ||||
|  | ||||
|  | ||||
| PRE_CONFIG_ACTIONS = { | ||||
|     'wizard': command_wizard, | ||||
|     'version': command_version, | ||||
|     'dashboard': command_dashboard, | ||||
|     'vscode': command_vscode, | ||||
|     'update-all': command_update_all, | ||||
|     "wizard": command_wizard, | ||||
|     "version": command_version, | ||||
|     "dashboard": command_dashboard, | ||||
|     "vscode": command_vscode, | ||||
|     "update-all": command_update_all, | ||||
| } | ||||
|  | ||||
| POST_CONFIG_ACTIONS = { | ||||
|     'config': command_config, | ||||
|     'compile': command_compile, | ||||
|     'upload': command_upload, | ||||
|     'logs': command_logs, | ||||
|     'run': command_run, | ||||
|     'clean-mqtt': command_clean_mqtt, | ||||
|     'mqtt-fingerprint': command_mqtt_fingerprint, | ||||
|     'clean': command_clean, | ||||
|     "config": command_config, | ||||
|     "compile": command_compile, | ||||
|     "upload": command_upload, | ||||
|     "logs": command_logs, | ||||
|     "run": command_run, | ||||
|     "clean-mqtt": command_clean_mqtt, | ||||
|     "mqtt-fingerprint": command_mqtt_fingerprint, | ||||
|     "clean": command_clean, | ||||
| } | ||||
|  | ||||
|  | ||||
| def parse_args(argv): | ||||
|     parser = argparse.ArgumentParser(description=f'ESPHome v{const.__version__}') | ||||
|     parser.add_argument('-v', '--verbose', help="Enable verbose esphome logs.", | ||||
|                         action='store_true') | ||||
|     parser.add_argument('-q', '--quiet', help="Disable all esphome logs.", | ||||
|                         action='store_true') | ||||
|     parser.add_argument('--dashboard', help=argparse.SUPPRESS, action='store_true') | ||||
|     parser.add_argument('-s', '--substitution', nargs=2, action='append', | ||||
|                         help='Add a substitution', metavar=('key', 'value')) | ||||
|     parser.add_argument('configuration', help='Your YAML configuration file.', nargs='*') | ||||
|     parser = argparse.ArgumentParser(description=f"ESPHome v{const.__version__}") | ||||
|     parser.add_argument( | ||||
|         "-v", "--verbose", help="Enable verbose esphome logs.", action="store_true" | ||||
|     ) | ||||
|     parser.add_argument( | ||||
|         "-q", "--quiet", help="Disable all esphome logs.", action="store_true" | ||||
|     ) | ||||
|     parser.add_argument("--dashboard", help=argparse.SUPPRESS, action="store_true") | ||||
|     parser.add_argument( | ||||
|         "-s", | ||||
|         "--substitution", | ||||
|         nargs=2, | ||||
|         action="append", | ||||
|         help="Add a substitution", | ||||
|         metavar=("key", "value"), | ||||
|     ) | ||||
|     parser.add_argument( | ||||
|         "configuration", help="Your YAML configuration file.", nargs="*" | ||||
|     ) | ||||
|  | ||||
|     subparsers = parser.add_subparsers(help='Commands', dest='command') | ||||
|     subparsers = parser.add_subparsers(help="Commands", dest="command") | ||||
|     subparsers.required = True | ||||
|     subparsers.add_parser('config', help='Validate the configuration and spit it out.') | ||||
|     subparsers.add_parser("config", help="Validate the configuration and spit it out.") | ||||
|  | ||||
|     parser_compile = subparsers.add_parser('compile', | ||||
|                                            help='Read the configuration and compile a program.') | ||||
|     parser_compile.add_argument('--only-generate', | ||||
|                                 help="Only generate source code, do not compile.", | ||||
|                                 action='store_true') | ||||
|     parser_compile = subparsers.add_parser( | ||||
|         "compile", help="Read the configuration and compile a program." | ||||
|     ) | ||||
|     parser_compile.add_argument( | ||||
|         "--only-generate", | ||||
|         help="Only generate source code, do not compile.", | ||||
|         action="store_true", | ||||
|     ) | ||||
|  | ||||
|     parser_upload = subparsers.add_parser('upload', help='Validate the configuration ' | ||||
|                                                          'and upload the latest binary.') | ||||
|     parser_upload.add_argument('--upload-port', help="Manually specify the upload port to use. " | ||||
|                                                      "For example /dev/cu.SLAB_USBtoUART.") | ||||
|     parser_upload = subparsers.add_parser( | ||||
|         "upload", help="Validate the configuration " "and upload the latest binary." | ||||
|     ) | ||||
|     parser_upload.add_argument( | ||||
|         "--upload-port", | ||||
|         help="Manually specify the upload port to use. " | ||||
|         "For example /dev/cu.SLAB_USBtoUART.", | ||||
|     ) | ||||
|  | ||||
|     parser_logs = subparsers.add_parser('logs', help='Validate the configuration ' | ||||
|                                                      'and show all MQTT logs.') | ||||
|     parser_logs.add_argument('--topic', help='Manually set the topic to subscribe to.') | ||||
|     parser_logs.add_argument('--username', help='Manually set the username.') | ||||
|     parser_logs.add_argument('--password', help='Manually set the password.') | ||||
|     parser_logs.add_argument('--client-id', help='Manually set the client id.') | ||||
|     parser_logs.add_argument('--serial-port', help="Manually specify a serial port to use" | ||||
|                                                    "For example /dev/cu.SLAB_USBtoUART.") | ||||
|     parser_logs = subparsers.add_parser( | ||||
|         "logs", help="Validate the configuration " "and show all MQTT logs." | ||||
|     ) | ||||
|     parser_logs.add_argument("--topic", help="Manually set the topic to subscribe to.") | ||||
|     parser_logs.add_argument("--username", help="Manually set the username.") | ||||
|     parser_logs.add_argument("--password", help="Manually set the password.") | ||||
|     parser_logs.add_argument("--client-id", help="Manually set the client id.") | ||||
|     parser_logs.add_argument( | ||||
|         "--serial-port", | ||||
|         help="Manually specify a serial port to use" | ||||
|         "For example /dev/cu.SLAB_USBtoUART.", | ||||
|     ) | ||||
|  | ||||
|     parser_run = subparsers.add_parser('run', help='Validate the configuration, create a binary, ' | ||||
|                                                    'upload it, and start MQTT logs.') | ||||
|     parser_run.add_argument('--upload-port', help="Manually specify the upload port/ip to use. " | ||||
|                                                   "For example /dev/cu.SLAB_USBtoUART.") | ||||
|     parser_run.add_argument('--no-logs', help='Disable starting MQTT logs.', | ||||
|                             action='store_true') | ||||
|     parser_run.add_argument('--topic', help='Manually set the topic to subscribe to for logs.') | ||||
|     parser_run.add_argument('--username', help='Manually set the MQTT username for logs.') | ||||
|     parser_run.add_argument('--password', help='Manually set the MQTT password for logs.') | ||||
|     parser_run.add_argument('--client-id', help='Manually set the client id for logs.') | ||||
|     parser_run = subparsers.add_parser( | ||||
|         "run", | ||||
|         help="Validate the configuration, create a binary, " | ||||
|         "upload it, and start MQTT logs.", | ||||
|     ) | ||||
|     parser_run.add_argument( | ||||
|         "--upload-port", | ||||
|         help="Manually specify the upload port/ip to use. " | ||||
|         "For example /dev/cu.SLAB_USBtoUART.", | ||||
|     ) | ||||
|     parser_run.add_argument( | ||||
|         "--no-logs", help="Disable starting MQTT logs.", action="store_true" | ||||
|     ) | ||||
|     parser_run.add_argument( | ||||
|         "--topic", help="Manually set the topic to subscribe to for logs." | ||||
|     ) | ||||
|     parser_run.add_argument( | ||||
|         "--username", help="Manually set the MQTT username for logs." | ||||
|     ) | ||||
|     parser_run.add_argument( | ||||
|         "--password", help="Manually set the MQTT password for logs." | ||||
|     ) | ||||
|     parser_run.add_argument("--client-id", help="Manually set the client id for logs.") | ||||
|  | ||||
|     parser_clean = subparsers.add_parser('clean-mqtt', help="Helper to clear an MQTT topic from " | ||||
|                                                             "retain messages.") | ||||
|     parser_clean.add_argument('--topic', help='Manually set the topic to subscribe to.') | ||||
|     parser_clean.add_argument('--username', help='Manually set the username.') | ||||
|     parser_clean.add_argument('--password', help='Manually set the password.') | ||||
|     parser_clean.add_argument('--client-id', help='Manually set the client id.') | ||||
|     parser_clean = subparsers.add_parser( | ||||
|         "clean-mqtt", help="Helper to clear an MQTT topic from " "retain messages." | ||||
|     ) | ||||
|     parser_clean.add_argument("--topic", help="Manually set the topic to subscribe to.") | ||||
|     parser_clean.add_argument("--username", help="Manually set the username.") | ||||
|     parser_clean.add_argument("--password", help="Manually set the password.") | ||||
|     parser_clean.add_argument("--client-id", help="Manually set the client id.") | ||||
|  | ||||
|     subparsers.add_parser('wizard', help="A helpful setup wizard that will guide " | ||||
|                                          "you through setting up esphome.") | ||||
|     subparsers.add_parser( | ||||
|         "wizard", | ||||
|         help="A helpful setup wizard that will guide " | ||||
|         "you through setting up esphome.", | ||||
|     ) | ||||
|  | ||||
|     subparsers.add_parser('mqtt-fingerprint', help="Get the SSL fingerprint from a MQTT broker.") | ||||
|     subparsers.add_parser( | ||||
|         "mqtt-fingerprint", help="Get the SSL fingerprint from a MQTT broker." | ||||
|     ) | ||||
|  | ||||
|     subparsers.add_parser('version', help="Print the esphome version and exit.") | ||||
|     subparsers.add_parser("version", help="Print the esphome version and exit.") | ||||
|  | ||||
|     subparsers.add_parser('clean', help="Delete all temporary build files.") | ||||
|     subparsers.add_parser("clean", help="Delete all temporary build files.") | ||||
|  | ||||
|     dashboard = subparsers.add_parser('dashboard', | ||||
|                                       help="Create a simple web server for a dashboard.") | ||||
|     dashboard.add_argument("--port", help="The HTTP port to open connections on. Defaults to 6052.", | ||||
|                            type=int, default=6052) | ||||
|     dashboard.add_argument("--username", help="The optional username to require " | ||||
|                                               "for authentication.", | ||||
|                            type=str, default='') | ||||
|     dashboard.add_argument("--password", help="The optional password to require " | ||||
|                                               "for authentication.", | ||||
|                            type=str, default='') | ||||
|     dashboard.add_argument("--open-ui", help="Open the dashboard UI in a browser.", | ||||
|                            action='store_true') | ||||
|     dashboard.add_argument("--hassio", | ||||
|                            help=argparse.SUPPRESS, | ||||
|                            action="store_true") | ||||
|     dashboard.add_argument("--socket", | ||||
|                            help="Make the dashboard serve under a unix socket", type=str) | ||||
|     dashboard = subparsers.add_parser( | ||||
|         "dashboard", help="Create a simple web server for a dashboard." | ||||
|     ) | ||||
|     dashboard.add_argument( | ||||
|         "--port", | ||||
|         help="The HTTP port to open connections on. Defaults to 6052.", | ||||
|         type=int, | ||||
|         default=6052, | ||||
|     ) | ||||
|     dashboard.add_argument( | ||||
|         "--username", | ||||
|         help="The optional username to require " "for authentication.", | ||||
|         type=str, | ||||
|         default="", | ||||
|     ) | ||||
|     dashboard.add_argument( | ||||
|         "--password", | ||||
|         help="The optional password to require " "for authentication.", | ||||
|         type=str, | ||||
|         default="", | ||||
|     ) | ||||
|     dashboard.add_argument( | ||||
|         "--open-ui", help="Open the dashboard UI in a browser.", action="store_true" | ||||
|     ) | ||||
|     dashboard.add_argument("--hassio", help=argparse.SUPPRESS, action="store_true") | ||||
|     dashboard.add_argument( | ||||
|         "--socket", help="Make the dashboard serve under a unix socket", type=str | ||||
|     ) | ||||
|  | ||||
|     vscode = subparsers.add_parser('vscode', help=argparse.SUPPRESS) | ||||
|     vscode.add_argument('--ace', action='store_true') | ||||
|     vscode = subparsers.add_parser("vscode", help=argparse.SUPPRESS) | ||||
|     vscode.add_argument("--ace", action="store_true") | ||||
|  | ||||
|     subparsers.add_parser('update-all', help=argparse.SUPPRESS) | ||||
|     subparsers.add_parser("update-all", help=argparse.SUPPRESS) | ||||
|  | ||||
|     return parser.parse_args(argv[1:]) | ||||
|  | ||||
| @@ -512,13 +632,15 @@ def run_esphome(argv): | ||||
|     CORE.dashboard = args.dashboard | ||||
|  | ||||
|     setup_log(args.verbose, args.quiet) | ||||
|     if args.command != 'version' and not args.configuration: | ||||
|     if args.command != "version" and not args.configuration: | ||||
|         _LOGGER.error("Missing configuration parameter, see esphome --help.") | ||||
|         return 1 | ||||
|  | ||||
|     if sys.version_info < (3, 6, 0): | ||||
|         _LOGGER.error("You're running ESPHome with Python <3.6. ESPHome is no longer compatible " | ||||
|                       "with this Python version. Please reinstall ESPHome with Python 3.6+") | ||||
|         _LOGGER.error( | ||||
|             "You're running ESPHome with Python <3.6. ESPHome is no longer compatible " | ||||
|             "with this Python version. Please reinstall ESPHome with Python 3.6+" | ||||
|         ) | ||||
|         return 1 | ||||
|  | ||||
|     if args.command in PRE_CONFIG_ACTIONS: | ||||
|   | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -177,10 +177,14 @@ class APIClient(threading.Thread): | ||||
|         try: | ||||
|             ip = resolve_ip_address(self._address) | ||||
|         except EsphomeError 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://esphome.io/components/wifi.html#manual-ips)") | ||||
|             _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://esphome.io/components/wifi.html#manual-ips)" | ||||
|             ) | ||||
|             raise APIConnectionError(err) from err | ||||
|  | ||||
|         _LOGGER.info("Connecting to %s:%s (%s)", self._address, self._port, ip) | ||||
| @@ -198,14 +202,19 @@ class APIClient(threading.Thread): | ||||
|         self._socket_open_event.set() | ||||
|  | ||||
|         hello = pb.HelloRequest() | ||||
|         hello.client_info = f'ESPHome v{const.__version__}' | ||||
|         hello.client_info = f"ESPHome v{const.__version__}" | ||||
|         try: | ||||
|             resp = self._send_message_await_response(hello, pb.HelloResponse) | ||||
|         except APIConnectionError as err: | ||||
|             self._fatal_error(err) | ||||
|             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) | ||||
|         _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 | ||||
|         self._refresh_ping() | ||||
|         if self.on_connect is not None: | ||||
| @@ -270,7 +279,9 @@ class APIClient(threading.Thread): | ||||
|         req += encoded | ||||
|         self._write(req) | ||||
|  | ||||
|     def _send_message_await_response_complex(self, send_msg, do_append, do_stop, timeout=5): | ||||
|     def _send_message_await_response_complex( | ||||
|         self, send_msg, do_append, do_stop, timeout=5 | ||||
|     ): | ||||
|         event = threading.Event() | ||||
|         responses = [] | ||||
|  | ||||
| @@ -295,12 +306,15 @@ class APIClient(threading.Thread): | ||||
|         def is_response(msg): | ||||
|             return isinstance(msg, response_type) | ||||
|  | ||||
|         return self._send_message_await_response_complex(send_msg, is_response, is_response, | ||||
|                                                          timeout)[0] | ||||
|         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) | ||||
|         return self._send_message_await_response( | ||||
|             pb.DeviceInfoRequest(), pb.DeviceInfoResponse | ||||
|         ) | ||||
|  | ||||
|     def ping(self): | ||||
|         self._check_connected() | ||||
| @@ -310,7 +324,9 @@ class APIClient(threading.Thread): | ||||
|         self._check_connected() | ||||
|  | ||||
|         try: | ||||
|             self._send_message_await_response(pb.DisconnectRequest(), pb.DisconnectResponse) | ||||
|             self._send_message_await_response( | ||||
|                 pb.DisconnectRequest(), pb.DisconnectResponse | ||||
|             ) | ||||
|         except APIConnectionError: | ||||
|             pass | ||||
|         self._close_socket() | ||||
| @@ -415,7 +431,7 @@ class APIClient(threading.Thread): | ||||
|  | ||||
|  | ||||
| def run_logs(config, address): | ||||
|     conf = config['api'] | ||||
|     conf = config["api"] | ||||
|     port = conf[CONF_PORT] | ||||
|     password = conf[CONF_PASSWORD] | ||||
|     _LOGGER.info("Starting log output from %s using esphome API", address) | ||||
| @@ -447,24 +463,35 @@ def run_logs(config, address): | ||||
|             _LOGGER.info("Successfully connected to %s", address) | ||||
|             return | ||||
|  | ||||
|         wait_time = int(min(1.5**min(tries, 100), 30)) | ||||
|         wait_time = int(min(1.5 ** min(tries, 100), 30)) | ||||
|         if not has_connects: | ||||
|             _LOGGER.warning("Initial connection failed. The ESP might not be connected " | ||||
|                             "to WiFi yet (%s). Re-Trying in %s seconds", | ||||
|                             error, wait_time) | ||||
|             _LOGGER.warning( | ||||
|                 "Initial connection failed. The ESP might not be connected " | ||||
|                 "to WiFi yet (%s). Re-Trying in %s seconds", | ||||
|                 error, | ||||
|                 wait_time, | ||||
|             ) | ||||
|         else: | ||||
|             _LOGGER.warning("Couldn't connect to API (%s). Trying to reconnect in %s seconds", | ||||
|                             error, wait_time) | ||||
|         timer = threading.Timer(wait_time, functools.partial(try_connect, None, tries + 1)) | ||||
|             _LOGGER.warning( | ||||
|                 "Couldn't connect to API (%s). Trying to reconnect in %s seconds", | ||||
|                 error, | ||||
|                 wait_time, | ||||
|             ) | ||||
|         timer = threading.Timer( | ||||
|             wait_time, functools.partial(try_connect, None, tries + 1) | ||||
|         ) | ||||
|         timer.start() | ||||
|         retry_timer.append(timer) | ||||
|  | ||||
|     def on_log(msg): | ||||
|         time_ = datetime.now().time().strftime('[%H:%M:%S]') | ||||
|         time_ = datetime.now().time().strftime("[%H:%M:%S]") | ||||
|         text = msg.message | ||||
|         if msg.send_failed: | ||||
|             text = color('white', '(Message skipped because it was too big to fit in ' | ||||
|                                   'TCP buffer - This is only cosmetic)') | ||||
|             text = color( | ||||
|                 "white", | ||||
|                 "(Message skipped because it was too big to fit in " | ||||
|                 "TCP buffer - This is only cosmetic)", | ||||
|             ) | ||||
|         safe_print(time_ + text) | ||||
|  | ||||
|     def on_login(): | ||||
|   | ||||
| @@ -1,7 +1,15 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.const import CONF_AUTOMATION_ID, CONF_CONDITION, CONF_ELSE, CONF_ID, CONF_THEN, \ | ||||
|     CONF_TRIGGER_ID, CONF_TYPE_ID, CONF_TIME | ||||
| from esphome.const import ( | ||||
|     CONF_AUTOMATION_ID, | ||||
|     CONF_CONDITION, | ||||
|     CONF_ELSE, | ||||
|     CONF_ID, | ||||
|     CONF_THEN, | ||||
|     CONF_TRIGGER_ID, | ||||
|     CONF_TYPE_ID, | ||||
|     CONF_TIME, | ||||
| ) | ||||
| from esphome.core import coroutine | ||||
| from esphome.util import Registry | ||||
|  | ||||
| @@ -30,36 +38,34 @@ def register_condition(name, condition_type, schema): | ||||
|     return CONDITION_REGISTRY.register(name, condition_type, schema) | ||||
|  | ||||
|  | ||||
| Action = cg.esphome_ns.class_('Action') | ||||
| Trigger = cg.esphome_ns.class_('Trigger') | ||||
| Action = cg.esphome_ns.class_("Action") | ||||
| Trigger = cg.esphome_ns.class_("Trigger") | ||||
| ACTION_REGISTRY = Registry() | ||||
| Condition = cg.esphome_ns.class_('Condition') | ||||
| Condition = cg.esphome_ns.class_("Condition") | ||||
| CONDITION_REGISTRY = Registry() | ||||
| validate_action = cv.validate_registry_entry('action', ACTION_REGISTRY) | ||||
| validate_action_list = cv.validate_registry('action', ACTION_REGISTRY) | ||||
| validate_condition = cv.validate_registry_entry('condition', CONDITION_REGISTRY) | ||||
| validate_condition_list = cv.validate_registry('condition', CONDITION_REGISTRY) | ||||
| validate_action = cv.validate_registry_entry("action", ACTION_REGISTRY) | ||||
| validate_action_list = cv.validate_registry("action", ACTION_REGISTRY) | ||||
| validate_condition = cv.validate_registry_entry("condition", CONDITION_REGISTRY) | ||||
| validate_condition_list = cv.validate_registry("condition", CONDITION_REGISTRY) | ||||
|  | ||||
|  | ||||
| def validate_potentially_and_condition(value): | ||||
|     if isinstance(value, list): | ||||
|         with cv.remove_prepend_path(['and']): | ||||
|             return validate_condition({ | ||||
|                 'and': value | ||||
|             }) | ||||
|         with cv.remove_prepend_path(["and"]): | ||||
|             return validate_condition({"and": value}) | ||||
|     return validate_condition(value) | ||||
|  | ||||
|  | ||||
| DelayAction = cg.esphome_ns.class_('DelayAction', Action, cg.Component) | ||||
| LambdaAction = cg.esphome_ns.class_('LambdaAction', Action) | ||||
| IfAction = cg.esphome_ns.class_('IfAction', Action) | ||||
| WhileAction = cg.esphome_ns.class_('WhileAction', Action) | ||||
| WaitUntilAction = cg.esphome_ns.class_('WaitUntilAction', Action, cg.Component) | ||||
| UpdateComponentAction = cg.esphome_ns.class_('UpdateComponentAction', Action) | ||||
| Automation = cg.esphome_ns.class_('Automation') | ||||
| DelayAction = cg.esphome_ns.class_("DelayAction", Action, cg.Component) | ||||
| LambdaAction = cg.esphome_ns.class_("LambdaAction", Action) | ||||
| IfAction = cg.esphome_ns.class_("IfAction", Action) | ||||
| WhileAction = cg.esphome_ns.class_("WhileAction", Action) | ||||
| WaitUntilAction = cg.esphome_ns.class_("WaitUntilAction", Action, cg.Component) | ||||
| UpdateComponentAction = cg.esphome_ns.class_("UpdateComponentAction", Action) | ||||
| Automation = cg.esphome_ns.class_("Automation") | ||||
|  | ||||
| LambdaCondition = cg.esphome_ns.class_('LambdaCondition', Condition) | ||||
| ForCondition = cg.esphome_ns.class_('ForCondition', Condition, cg.Component) | ||||
| LambdaCondition = cg.esphome_ns.class_("LambdaCondition", Condition) | ||||
| ForCondition = cg.esphome_ns.class_("ForCondition", Condition, cg.Component) | ||||
|  | ||||
|  | ||||
| def validate_automation(extra_schema=None, extra_validators=None, single=False): | ||||
| @@ -83,10 +89,10 @@ def validate_automation(extra_schema=None, extra_validators=None, single=False): | ||||
|                 try: | ||||
|                     return cv.Schema([schema])(value) | ||||
|                 except cv.Invalid as err2: | ||||
|                     if 'extra keys not allowed' in str(err2) and len(err2.path) == 2: | ||||
|                     if "extra keys not allowed" in str(err2) and len(err2.path) == 2: | ||||
|                         # pylint: disable=raise-missing-from | ||||
|                         raise err | ||||
|                     if 'Unable to find action' in str(err): | ||||
|                     if "Unable to find action" in str(err): | ||||
|                         raise err2 | ||||
|                     raise cv.MultipleInvalid([err, err2]) | ||||
|         elif isinstance(value, dict): | ||||
| @@ -110,47 +116,59 @@ def validate_automation(extra_schema=None, extra_validators=None, single=False): | ||||
|     return validator | ||||
|  | ||||
|  | ||||
| AUTOMATION_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(Trigger), | ||||
|     cv.GenerateID(CONF_AUTOMATION_ID): cv.declare_id(Automation), | ||||
|     cv.Required(CONF_THEN): validate_action_list, | ||||
| }) | ||||
| AUTOMATION_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(Trigger), | ||||
|         cv.GenerateID(CONF_AUTOMATION_ID): cv.declare_id(Automation), | ||||
|         cv.Required(CONF_THEN): validate_action_list, | ||||
|     } | ||||
| ) | ||||
|  | ||||
| AndCondition = cg.esphome_ns.class_('AndCondition', Condition) | ||||
| OrCondition = cg.esphome_ns.class_('OrCondition', Condition) | ||||
| NotCondition = cg.esphome_ns.class_('NotCondition', Condition) | ||||
| AndCondition = cg.esphome_ns.class_("AndCondition", Condition) | ||||
| OrCondition = cg.esphome_ns.class_("OrCondition", Condition) | ||||
| NotCondition = cg.esphome_ns.class_("NotCondition", Condition) | ||||
|  | ||||
|  | ||||
| @register_condition('and', AndCondition, validate_condition_list) | ||||
| @register_condition("and", AndCondition, validate_condition_list) | ||||
| def and_condition_to_code(config, condition_id, template_arg, args): | ||||
|     conditions = yield build_condition_list(config, template_arg, args) | ||||
|     yield cg.new_Pvariable(condition_id, template_arg, conditions) | ||||
|  | ||||
|  | ||||
| @register_condition('or', OrCondition, validate_condition_list) | ||||
| @register_condition("or", OrCondition, validate_condition_list) | ||||
| def or_condition_to_code(config, condition_id, template_arg, args): | ||||
|     conditions = yield build_condition_list(config, template_arg, args) | ||||
|     yield cg.new_Pvariable(condition_id, template_arg, conditions) | ||||
|  | ||||
|  | ||||
| @register_condition('not', NotCondition, validate_potentially_and_condition) | ||||
| @register_condition("not", NotCondition, validate_potentially_and_condition) | ||||
| def not_condition_to_code(config, condition_id, template_arg, args): | ||||
|     condition = yield build_condition(config, template_arg, args) | ||||
|     yield cg.new_Pvariable(condition_id, template_arg, condition) | ||||
|  | ||||
|  | ||||
| @register_condition('lambda', LambdaCondition, cv.lambda_) | ||||
| @register_condition("lambda", LambdaCondition, cv.lambda_) | ||||
| def lambda_condition_to_code(config, condition_id, template_arg, args): | ||||
|     lambda_ = yield cg.process_lambda(config, args, return_type=bool) | ||||
|     yield cg.new_Pvariable(condition_id, template_arg, lambda_) | ||||
|  | ||||
|  | ||||
| @register_condition('for', ForCondition, cv.Schema({ | ||||
|     cv.Required(CONF_TIME): cv.templatable(cv.positive_time_period_milliseconds), | ||||
|     cv.Required(CONF_CONDITION): validate_potentially_and_condition, | ||||
| }).extend(cv.COMPONENT_SCHEMA)) | ||||
| @register_condition( | ||||
|     "for", | ||||
|     ForCondition, | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.Required(CONF_TIME): cv.templatable( | ||||
|                 cv.positive_time_period_milliseconds | ||||
|             ), | ||||
|             cv.Required(CONF_CONDITION): validate_potentially_and_condition, | ||||
|         } | ||||
|     ).extend(cv.COMPONENT_SCHEMA), | ||||
| ) | ||||
| def for_condition_to_code(config, condition_id, template_arg, args): | ||||
|     condition = yield build_condition(config[CONF_CONDITION], cg.TemplateArguments(), []) | ||||
|     condition = yield build_condition( | ||||
|         config[CONF_CONDITION], cg.TemplateArguments(), [] | ||||
|     ) | ||||
|     var = cg.new_Pvariable(condition_id, template_arg, condition) | ||||
|     yield cg.register_component(var, config) | ||||
|     templ = yield cg.templatable(config[CONF_TIME], args, cg.uint32) | ||||
| @@ -158,7 +176,9 @@ def for_condition_to_code(config, condition_id, template_arg, args): | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @register_action('delay', DelayAction, cv.templatable(cv.positive_time_period_milliseconds)) | ||||
| @register_action( | ||||
|     "delay", DelayAction, cv.templatable(cv.positive_time_period_milliseconds) | ||||
| ) | ||||
| def delay_action_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_component(var, {}) | ||||
| @@ -167,11 +187,18 @@ def delay_action_to_code(config, action_id, template_arg, args): | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @register_action('if', IfAction, cv.All({ | ||||
|     cv.Required(CONF_CONDITION): validate_potentially_and_condition, | ||||
|     cv.Optional(CONF_THEN): validate_action_list, | ||||
|     cv.Optional(CONF_ELSE): validate_action_list, | ||||
| }, cv.has_at_least_one_key(CONF_THEN, CONF_ELSE))) | ||||
| @register_action( | ||||
|     "if", | ||||
|     IfAction, | ||||
|     cv.All( | ||||
|         { | ||||
|             cv.Required(CONF_CONDITION): validate_potentially_and_condition, | ||||
|             cv.Optional(CONF_THEN): validate_action_list, | ||||
|             cv.Optional(CONF_ELSE): validate_action_list, | ||||
|         }, | ||||
|         cv.has_at_least_one_key(CONF_THEN, CONF_ELSE), | ||||
|     ), | ||||
| ) | ||||
| def if_action_to_code(config, action_id, template_arg, args): | ||||
|     conditions = yield build_condition(config[CONF_CONDITION], template_arg, args) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, conditions) | ||||
| @@ -184,10 +211,16 @@ def if_action_to_code(config, action_id, template_arg, args): | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @register_action('while', WhileAction, cv.Schema({ | ||||
|     cv.Required(CONF_CONDITION): validate_potentially_and_condition, | ||||
|     cv.Required(CONF_THEN): validate_action_list, | ||||
| })) | ||||
| @register_action( | ||||
|     "while", | ||||
|     WhileAction, | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.Required(CONF_CONDITION): validate_potentially_and_condition, | ||||
|             cv.Required(CONF_THEN): validate_action_list, | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def while_action_to_code(config, action_id, template_arg, args): | ||||
|     conditions = yield build_condition(config[CONF_CONDITION], template_arg, args) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, conditions) | ||||
| @@ -197,15 +230,17 @@ def while_action_to_code(config, action_id, template_arg, args): | ||||
|  | ||||
|  | ||||
| def validate_wait_until(value): | ||||
|     schema = cv.Schema({ | ||||
|         cv.Required(CONF_CONDITION): validate_potentially_and_condition, | ||||
|     }) | ||||
|     schema = cv.Schema( | ||||
|         { | ||||
|             cv.Required(CONF_CONDITION): validate_potentially_and_condition, | ||||
|         } | ||||
|     ) | ||||
|     if isinstance(value, dict) and CONF_CONDITION in value: | ||||
|         return schema(value) | ||||
|     return validate_wait_until({CONF_CONDITION: value}) | ||||
|  | ||||
|  | ||||
| @register_action('wait_until', WaitUntilAction, validate_wait_until) | ||||
| @register_action("wait_until", WaitUntilAction, validate_wait_until) | ||||
| def wait_until_action_to_code(config, action_id, template_arg, args): | ||||
|     conditions = yield build_condition(config[CONF_CONDITION], template_arg, args) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, conditions) | ||||
| @@ -213,15 +248,21 @@ def wait_until_action_to_code(config, action_id, template_arg, args): | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @register_action('lambda', LambdaAction, cv.lambda_) | ||||
| @register_action("lambda", LambdaAction, cv.lambda_) | ||||
| def lambda_action_to_code(config, action_id, template_arg, args): | ||||
|     lambda_ = yield cg.process_lambda(config, args, return_type=cg.void) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, lambda_) | ||||
|  | ||||
|  | ||||
| @register_action('component.update', UpdateComponentAction, maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.use_id(cg.PollingComponent), | ||||
| })) | ||||
| @register_action( | ||||
|     "component.update", | ||||
|     UpdateComponentAction, | ||||
|     maybe_simple_id( | ||||
|         { | ||||
|             cv.Required(CONF_ID): cv.use_id(cg.PollingComponent), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def component_update_action_to_code(config, action_id, template_arg, args): | ||||
|     comp = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, comp) | ||||
| @@ -229,7 +270,9 @@ def component_update_action_to_code(config, action_id, template_arg, args): | ||||
|  | ||||
| @coroutine | ||||
| def build_action(full_config, template_arg, args): | ||||
|     registry_entry, config = cg.extract_registry_entry_config(ACTION_REGISTRY, full_config) | ||||
|     registry_entry, config = cg.extract_registry_entry_config( | ||||
|         ACTION_REGISTRY, full_config | ||||
|     ) | ||||
|     action_id = full_config[CONF_TYPE_ID] | ||||
|     builder = registry_entry.coroutine_fun | ||||
|     yield builder(config, action_id, template_arg, args) | ||||
| @@ -246,7 +289,9 @@ def build_action_list(config, templ, arg_type): | ||||
|  | ||||
| @coroutine | ||||
| def build_condition(full_config, template_arg, args): | ||||
|     registry_entry, config = cg.extract_registry_entry_config(CONDITION_REGISTRY, full_config) | ||||
|     registry_entry, config = cg.extract_registry_entry_config( | ||||
|         CONDITION_REGISTRY, full_config | ||||
|     ) | ||||
|     action_id = full_config[CONF_TYPE_ID] | ||||
|     builder = registry_entry.coroutine_fun | ||||
|     yield builder(config, action_id, template_arg, args) | ||||
|   | ||||
| @@ -9,18 +9,70 @@ | ||||
|  | ||||
| # pylint: disable=unused-import | ||||
| from esphome.cpp_generator import (  # noqa | ||||
|     Expression, RawExpression, RawStatement, TemplateArguments, | ||||
|     StructInitializer, ArrayInitializer, safe_exp, Statement, LineComment, | ||||
|     progmem_array, statement, variable, Pvariable, new_Pvariable, | ||||
|     add, add_global, add_library, add_build_flag, add_define, | ||||
|     get_variable, get_variable_with_full_id, process_lambda, is_template, templatable, MockObj, | ||||
|     MockObjClass) | ||||
|     Expression, | ||||
|     RawExpression, | ||||
|     RawStatement, | ||||
|     TemplateArguments, | ||||
|     StructInitializer, | ||||
|     ArrayInitializer, | ||||
|     safe_exp, | ||||
|     Statement, | ||||
|     LineComment, | ||||
|     progmem_array, | ||||
|     statement, | ||||
|     variable, | ||||
|     Pvariable, | ||||
|     new_Pvariable, | ||||
|     add, | ||||
|     add_global, | ||||
|     add_library, | ||||
|     add_build_flag, | ||||
|     add_define, | ||||
|     get_variable, | ||||
|     get_variable_with_full_id, | ||||
|     process_lambda, | ||||
|     is_template, | ||||
|     templatable, | ||||
|     MockObj, | ||||
|     MockObjClass, | ||||
| ) | ||||
| from esphome.cpp_helpers import (  # noqa | ||||
|     gpio_pin_expression, register_component, build_registry_entry, | ||||
|     build_registry_list, extract_registry_entry_config, register_parented) | ||||
|     gpio_pin_expression, | ||||
|     register_component, | ||||
|     build_registry_entry, | ||||
|     build_registry_list, | ||||
|     extract_registry_entry_config, | ||||
|     register_parented, | ||||
| ) | ||||
| from esphome.cpp_types import (  # noqa | ||||
|     global_ns, void, nullptr, float_, double, bool_, int_, std_ns, std_string, | ||||
|     std_vector, uint8, uint16, uint32, int32, const_char_ptr, NAN, | ||||
|     esphome_ns, App, Nameable, Component, ComponentPtr, | ||||
|     PollingComponent, Application, optional, arduino_json_ns, JsonObject, | ||||
|     JsonObjectRef, JsonObjectConstRef, Controller, GPIOPin) | ||||
|     global_ns, | ||||
|     void, | ||||
|     nullptr, | ||||
|     float_, | ||||
|     double, | ||||
|     bool_, | ||||
|     int_, | ||||
|     std_ns, | ||||
|     std_string, | ||||
|     std_vector, | ||||
|     uint8, | ||||
|     uint16, | ||||
|     uint32, | ||||
|     int32, | ||||
|     const_char_ptr, | ||||
|     NAN, | ||||
|     esphome_ns, | ||||
|     App, | ||||
|     Nameable, | ||||
|     Component, | ||||
|     ComponentPtr, | ||||
|     PollingComponent, | ||||
|     Application, | ||||
|     optional, | ||||
|     arduino_json_ns, | ||||
|     JsonObject, | ||||
|     JsonObjectRef, | ||||
|     JsonObjectConstRef, | ||||
|     Controller, | ||||
|     GPIOPin, | ||||
| ) | ||||
|   | ||||
| @@ -5,15 +5,17 @@ import esphome.codegen as cg | ||||
| from esphome.const import CONF_DIR_PIN, CONF_ID, CONF_SLEEP_PIN, CONF_STEP_PIN | ||||
|  | ||||
|  | ||||
| a4988_ns = cg.esphome_ns.namespace('a4988') | ||||
| A4988 = a4988_ns.class_('A4988', stepper.Stepper, cg.Component) | ||||
| a4988_ns = cg.esphome_ns.namespace("a4988") | ||||
| A4988 = a4988_ns.class_("A4988", stepper.Stepper, cg.Component) | ||||
|  | ||||
| CONFIG_SCHEMA = stepper.STEPPER_SCHEMA.extend({ | ||||
|     cv.Required(CONF_ID): cv.declare_id(A4988), | ||||
|     cv.Required(CONF_STEP_PIN): pins.gpio_output_pin_schema, | ||||
|     cv.Required(CONF_DIR_PIN): pins.gpio_output_pin_schema, | ||||
|     cv.Optional(CONF_SLEEP_PIN): pins.gpio_output_pin_schema, | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| CONFIG_SCHEMA = stepper.STEPPER_SCHEMA.extend( | ||||
|     { | ||||
|         cv.Required(CONF_ID): cv.declare_id(A4988), | ||||
|         cv.Required(CONF_STEP_PIN): pins.gpio_output_pin_schema, | ||||
|         cv.Required(CONF_DIR_PIN): pins.gpio_output_pin_schema, | ||||
|         cv.Optional(CONF_SLEEP_PIN): pins.gpio_output_pin_schema, | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -4,28 +4,32 @@ from esphome import pins | ||||
| from esphome.components import output | ||||
| from esphome.const import CONF_ID, CONF_MIN_POWER, CONF_METHOD | ||||
|  | ||||
| CODEOWNERS = ['@glmnet'] | ||||
| CODEOWNERS = ["@glmnet"] | ||||
|  | ||||
| ac_dimmer_ns = cg.esphome_ns.namespace('ac_dimmer') | ||||
| AcDimmer = ac_dimmer_ns.class_('AcDimmer', output.FloatOutput, cg.Component) | ||||
| ac_dimmer_ns = cg.esphome_ns.namespace("ac_dimmer") | ||||
| AcDimmer = ac_dimmer_ns.class_("AcDimmer", output.FloatOutput, cg.Component) | ||||
|  | ||||
| DimMethod = ac_dimmer_ns.enum('DimMethod') | ||||
| DimMethod = ac_dimmer_ns.enum("DimMethod") | ||||
| DIM_METHODS = { | ||||
|     'LEADING_PULSE': DimMethod.DIM_METHOD_LEADING_PULSE, | ||||
|     'LEADING': DimMethod.DIM_METHOD_LEADING, | ||||
|     'TRAILING': DimMethod.DIM_METHOD_TRAILING, | ||||
|     "LEADING_PULSE": DimMethod.DIM_METHOD_LEADING_PULSE, | ||||
|     "LEADING": DimMethod.DIM_METHOD_LEADING, | ||||
|     "TRAILING": DimMethod.DIM_METHOD_TRAILING, | ||||
| } | ||||
|  | ||||
| CONF_GATE_PIN = 'gate_pin' | ||||
| CONF_ZERO_CROSS_PIN = 'zero_cross_pin' | ||||
| CONF_INIT_WITH_HALF_CYCLE = 'init_with_half_cycle' | ||||
| CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend({ | ||||
|     cv.Required(CONF_ID): cv.declare_id(AcDimmer), | ||||
|     cv.Required(CONF_GATE_PIN): pins.internal_gpio_output_pin_schema, | ||||
|     cv.Required(CONF_ZERO_CROSS_PIN): pins.internal_gpio_input_pin_schema, | ||||
|     cv.Optional(CONF_INIT_WITH_HALF_CYCLE, default=True): cv.boolean, | ||||
|     cv.Optional(CONF_METHOD, default='leading pulse'): cv.enum(DIM_METHODS, upper=True, space='_'), | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| CONF_GATE_PIN = "gate_pin" | ||||
| CONF_ZERO_CROSS_PIN = "zero_cross_pin" | ||||
| CONF_INIT_WITH_HALF_CYCLE = "init_with_half_cycle" | ||||
| CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( | ||||
|     { | ||||
|         cv.Required(CONF_ID): cv.declare_id(AcDimmer), | ||||
|         cv.Required(CONF_GATE_PIN): pins.internal_gpio_output_pin_schema, | ||||
|         cv.Required(CONF_ZERO_CROSS_PIN): pins.internal_gpio_input_pin_schema, | ||||
|         cv.Optional(CONF_INIT_WITH_HALF_CYCLE, default=True): cv.boolean, | ||||
|         cv.Optional(CONF_METHOD, default="leading pulse"): cv.enum( | ||||
|             DIM_METHODS, upper=True, space="_" | ||||
|         ), | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -5,18 +5,22 @@ from esphome.components.light.types import AddressableLightEffect | ||||
| from esphome.components.light.effects import register_addressable_effect | ||||
| from esphome.const import CONF_NAME, CONF_UART_ID | ||||
|  | ||||
| DEPENDENCIES = ['uart'] | ||||
| DEPENDENCIES = ["uart"] | ||||
|  | ||||
| adalight_ns = cg.esphome_ns.namespace('adalight') | ||||
| adalight_ns = cg.esphome_ns.namespace("adalight") | ||||
| AdalightLightEffect = adalight_ns.class_( | ||||
|     'AdalightLightEffect', uart.UARTDevice, AddressableLightEffect) | ||||
|     "AdalightLightEffect", uart.UARTDevice, AddressableLightEffect | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({}) | ||||
|  | ||||
|  | ||||
| @register_addressable_effect('adalight', AdalightLightEffect, "Adalight", { | ||||
|     cv.GenerateID(CONF_UART_ID): cv.use_id(uart.UARTComponent) | ||||
| }) | ||||
| @register_addressable_effect( | ||||
|     "adalight", | ||||
|     AdalightLightEffect, | ||||
|     "Adalight", | ||||
|     {cv.GenerateID(CONF_UART_ID): cv.use_id(uart.UARTComponent)}, | ||||
| ) | ||||
| def adalight_light_effect_to_code(config, effect_id): | ||||
|     effect = cg.new_Pvariable(effect_id, config[CONF_NAME]) | ||||
|     yield uart.register_uart_device(effect, config) | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| CODEOWNERS = ['@esphome/core'] | ||||
| CODEOWNERS = ["@esphome/core"] | ||||
|   | ||||
| @@ -2,37 +2,51 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.components import sensor, voltage_sampler | ||||
| from esphome.const import CONF_ATTENUATION, CONF_ID, CONF_PIN, DEVICE_CLASS_VOLTAGE, ICON_EMPTY, \ | ||||
|     UNIT_VOLT | ||||
| from esphome.const import ( | ||||
|     CONF_ATTENUATION, | ||||
|     CONF_ID, | ||||
|     CONF_PIN, | ||||
|     DEVICE_CLASS_VOLTAGE, | ||||
|     ICON_EMPTY, | ||||
|     UNIT_VOLT, | ||||
| ) | ||||
|  | ||||
|  | ||||
| AUTO_LOAD = ['voltage_sampler'] | ||||
| AUTO_LOAD = ["voltage_sampler"] | ||||
|  | ||||
| ATTENUATION_MODES = { | ||||
|     '0db': cg.global_ns.ADC_0db, | ||||
|     '2.5db': cg.global_ns.ADC_2_5db, | ||||
|     '6db': cg.global_ns.ADC_6db, | ||||
|     '11db': cg.global_ns.ADC_11db, | ||||
|     "0db": cg.global_ns.ADC_0db, | ||||
|     "2.5db": cg.global_ns.ADC_2_5db, | ||||
|     "6db": cg.global_ns.ADC_6db, | ||||
|     "11db": cg.global_ns.ADC_11db, | ||||
| } | ||||
|  | ||||
|  | ||||
| def validate_adc_pin(value): | ||||
|     vcc = str(value).upper() | ||||
|     if vcc == 'VCC': | ||||
|     if vcc == "VCC": | ||||
|         return cv.only_on_esp8266(vcc) | ||||
|     return pins.analog_pin(value) | ||||
|  | ||||
|  | ||||
| adc_ns = cg.esphome_ns.namespace('adc') | ||||
| ADCSensor = adc_ns.class_('ADCSensor', sensor.Sensor, cg.PollingComponent, | ||||
|                           voltage_sampler.VoltageSampler) | ||||
| adc_ns = cg.esphome_ns.namespace("adc") | ||||
| ADCSensor = adc_ns.class_( | ||||
|     "ADCSensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = sensor.sensor_schema(UNIT_VOLT, ICON_EMPTY, 2, DEVICE_CLASS_VOLTAGE).extend({ | ||||
|     cv.GenerateID(): cv.declare_id(ADCSensor), | ||||
|     cv.Required(CONF_PIN): validate_adc_pin, | ||||
|     cv.SplitDefault(CONF_ATTENUATION, esp32='0db'): | ||||
|         cv.All(cv.only_on_esp32, cv.enum(ATTENUATION_MODES, lower=True)), | ||||
| }).extend(cv.polling_component_schema('60s')) | ||||
| CONFIG_SCHEMA = ( | ||||
|     sensor.sensor_schema(UNIT_VOLT, ICON_EMPTY, 2, DEVICE_CLASS_VOLTAGE) | ||||
|     .extend( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(ADCSensor), | ||||
|             cv.Required(CONF_PIN): validate_adc_pin, | ||||
|             cv.SplitDefault(CONF_ATTENUATION, esp32="0db"): cv.All( | ||||
|                 cv.only_on_esp32, cv.enum(ATTENUATION_MODES, lower=True) | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
| @@ -40,8 +54,8 @@ def to_code(config): | ||||
|     yield cg.register_component(var, config) | ||||
|     yield sensor.register_sensor(var, config) | ||||
|  | ||||
|     if config[CONF_PIN] == 'VCC': | ||||
|         cg.add_define('USE_ADC_SENSOR_VCC') | ||||
|     if config[CONF_PIN] == "VCC": | ||||
|         cg.add_define("USE_ADC_SENSOR_VCC") | ||||
|     else: | ||||
|         cg.add(var.set_pin(config[CONF_PIN])) | ||||
|  | ||||
|   | ||||
| @@ -2,33 +2,54 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor, i2c | ||||
| from esphome import pins | ||||
| from esphome.const import CONF_ID, CONF_VOLTAGE, DEVICE_CLASS_CURRENT, DEVICE_CLASS_POWER, \ | ||||
|     DEVICE_CLASS_VOLTAGE, ICON_EMPTY, UNIT_VOLT, UNIT_AMPERE, UNIT_WATT | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     CONF_VOLTAGE, | ||||
|     DEVICE_CLASS_CURRENT, | ||||
|     DEVICE_CLASS_POWER, | ||||
|     DEVICE_CLASS_VOLTAGE, | ||||
|     ICON_EMPTY, | ||||
|     UNIT_VOLT, | ||||
|     UNIT_AMPERE, | ||||
|     UNIT_WATT, | ||||
| ) | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| DEPENDENCIES = ["i2c"] | ||||
|  | ||||
| ade7953_ns = cg.esphome_ns.namespace('ade7953') | ||||
| ADE7953 = ade7953_ns.class_('ADE7953', cg.PollingComponent, i2c.I2CDevice) | ||||
| ade7953_ns = cg.esphome_ns.namespace("ade7953") | ||||
| ADE7953 = ade7953_ns.class_("ADE7953", cg.PollingComponent, i2c.I2CDevice) | ||||
|  | ||||
| CONF_IRQ_PIN = 'irq_pin' | ||||
| CONF_CURRENT_A = 'current_a' | ||||
| CONF_CURRENT_B = 'current_b' | ||||
| CONF_ACTIVE_POWER_A = 'active_power_a' | ||||
| CONF_ACTIVE_POWER_B = 'active_power_b' | ||||
| CONF_IRQ_PIN = "irq_pin" | ||||
| CONF_CURRENT_A = "current_a" | ||||
| CONF_CURRENT_B = "current_b" | ||||
| CONF_ACTIVE_POWER_A = "active_power_a" | ||||
| CONF_ACTIVE_POWER_B = "active_power_b" | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(ADE7953), | ||||
|     cv.Optional(CONF_IRQ_PIN): pins.input_pin, | ||||
|     cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(UNIT_VOLT, ICON_EMPTY, 1, DEVICE_CLASS_VOLTAGE), | ||||
|     cv.Optional(CONF_CURRENT_A): sensor.sensor_schema(UNIT_AMPERE, ICON_EMPTY, 2, | ||||
|                                                       DEVICE_CLASS_CURRENT), | ||||
|     cv.Optional(CONF_CURRENT_B): sensor.sensor_schema(UNIT_AMPERE, ICON_EMPTY, 2, | ||||
|                                                       DEVICE_CLASS_CURRENT), | ||||
|     cv.Optional(CONF_ACTIVE_POWER_A): sensor.sensor_schema(UNIT_WATT, ICON_EMPTY, 1, | ||||
|                                                            DEVICE_CLASS_POWER), | ||||
|     cv.Optional(CONF_ACTIVE_POWER_B): sensor.sensor_schema(UNIT_WATT, ICON_EMPTY, 1, | ||||
|                                                            DEVICE_CLASS_POWER), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x38)) | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(ADE7953), | ||||
|             cv.Optional(CONF_IRQ_PIN): pins.input_pin, | ||||
|             cv.Optional(CONF_VOLTAGE): sensor.sensor_schema( | ||||
|                 UNIT_VOLT, ICON_EMPTY, 1, DEVICE_CLASS_VOLTAGE | ||||
|             ), | ||||
|             cv.Optional(CONF_CURRENT_A): sensor.sensor_schema( | ||||
|                 UNIT_AMPERE, ICON_EMPTY, 2, DEVICE_CLASS_CURRENT | ||||
|             ), | ||||
|             cv.Optional(CONF_CURRENT_B): sensor.sensor_schema( | ||||
|                 UNIT_AMPERE, ICON_EMPTY, 2, DEVICE_CLASS_CURRENT | ||||
|             ), | ||||
|             cv.Optional(CONF_ACTIVE_POWER_A): sensor.sensor_schema( | ||||
|                 UNIT_WATT, ICON_EMPTY, 1, DEVICE_CLASS_POWER | ||||
|             ), | ||||
|             cv.Optional(CONF_ACTIVE_POWER_B): sensor.sensor_schema( | ||||
|                 UNIT_WATT, ICON_EMPTY, 1, DEVICE_CLASS_POWER | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
|     .extend(i2c.i2c_device_schema(0x38)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
| @@ -39,10 +60,15 @@ def to_code(config): | ||||
|     if CONF_IRQ_PIN in config: | ||||
|         cg.add(var.set_irq_pin(config[CONF_IRQ_PIN])) | ||||
|  | ||||
|     for key in [CONF_VOLTAGE, CONF_CURRENT_A, CONF_CURRENT_B, CONF_ACTIVE_POWER_A, | ||||
|                 CONF_ACTIVE_POWER_B]: | ||||
|     for key in [ | ||||
|         CONF_VOLTAGE, | ||||
|         CONF_CURRENT_A, | ||||
|         CONF_CURRENT_B, | ||||
|         CONF_ACTIVE_POWER_A, | ||||
|         CONF_ACTIVE_POWER_B, | ||||
|     ]: | ||||
|         if key not in config: | ||||
|             continue | ||||
|         conf = config[key] | ||||
|         sens = yield sensor.new_sensor(conf) | ||||
|         cg.add(getattr(var, f'set_{key}_sensor')(sens)) | ||||
|         cg.add(getattr(var, f"set_{key}_sensor")(sens)) | ||||
|   | ||||
| @@ -3,18 +3,24 @@ import esphome.config_validation as cv | ||||
| from esphome.components import i2c | ||||
| from esphome.const import CONF_ID | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| AUTO_LOAD = ['sensor', 'voltage_sampler'] | ||||
| DEPENDENCIES = ["i2c"] | ||||
| AUTO_LOAD = ["sensor", "voltage_sampler"] | ||||
| MULTI_CONF = True | ||||
|  | ||||
| ads1115_ns = cg.esphome_ns.namespace('ads1115') | ||||
| ADS1115Component = ads1115_ns.class_('ADS1115Component', cg.Component, i2c.I2CDevice) | ||||
| ads1115_ns = cg.esphome_ns.namespace("ads1115") | ||||
| ADS1115Component = ads1115_ns.class_("ADS1115Component", cg.Component, i2c.I2CDevice) | ||||
|  | ||||
| CONF_CONTINUOUS_MODE = 'continuous_mode' | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(ADS1115Component), | ||||
|     cv.Optional(CONF_CONTINUOUS_MODE, default=False): cv.boolean, | ||||
| }).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(None)) | ||||
| CONF_CONTINUOUS_MODE = "continuous_mode" | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(ADS1115Component), | ||||
|             cv.Optional(CONF_CONTINUOUS_MODE, default=False): cv.boolean, | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.COMPONENT_SCHEMA) | ||||
|     .extend(i2c.i2c_device_schema(None)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,54 +1,67 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor, voltage_sampler | ||||
| from esphome.const import CONF_GAIN, CONF_MULTIPLEXER, DEVICE_CLASS_VOLTAGE, ICON_EMPTY, \ | ||||
|     UNIT_VOLT, CONF_ID | ||||
| from esphome.const import ( | ||||
|     CONF_GAIN, | ||||
|     CONF_MULTIPLEXER, | ||||
|     DEVICE_CLASS_VOLTAGE, | ||||
|     ICON_EMPTY, | ||||
|     UNIT_VOLT, | ||||
|     CONF_ID, | ||||
| ) | ||||
| from . import ads1115_ns, ADS1115Component | ||||
|  | ||||
| DEPENDENCIES = ['ads1115'] | ||||
| DEPENDENCIES = ["ads1115"] | ||||
|  | ||||
| ADS1115Multiplexer = ads1115_ns.enum('ADS1115Multiplexer') | ||||
| ADS1115Multiplexer = ads1115_ns.enum("ADS1115Multiplexer") | ||||
| MUX = { | ||||
|     'A0_A1': ADS1115Multiplexer.ADS1115_MULTIPLEXER_P0_N1, | ||||
|     'A0_A3': ADS1115Multiplexer.ADS1115_MULTIPLEXER_P0_N3, | ||||
|     'A1_A3': ADS1115Multiplexer.ADS1115_MULTIPLEXER_P1_N3, | ||||
|     'A2_A3': ADS1115Multiplexer.ADS1115_MULTIPLEXER_P2_N3, | ||||
|     'A0_GND': ADS1115Multiplexer.ADS1115_MULTIPLEXER_P0_NG, | ||||
|     'A1_GND': ADS1115Multiplexer.ADS1115_MULTIPLEXER_P1_NG, | ||||
|     'A2_GND': ADS1115Multiplexer.ADS1115_MULTIPLEXER_P2_NG, | ||||
|     'A3_GND': ADS1115Multiplexer.ADS1115_MULTIPLEXER_P3_NG, | ||||
|     "A0_A1": ADS1115Multiplexer.ADS1115_MULTIPLEXER_P0_N1, | ||||
|     "A0_A3": ADS1115Multiplexer.ADS1115_MULTIPLEXER_P0_N3, | ||||
|     "A1_A3": ADS1115Multiplexer.ADS1115_MULTIPLEXER_P1_N3, | ||||
|     "A2_A3": ADS1115Multiplexer.ADS1115_MULTIPLEXER_P2_N3, | ||||
|     "A0_GND": ADS1115Multiplexer.ADS1115_MULTIPLEXER_P0_NG, | ||||
|     "A1_GND": ADS1115Multiplexer.ADS1115_MULTIPLEXER_P1_NG, | ||||
|     "A2_GND": ADS1115Multiplexer.ADS1115_MULTIPLEXER_P2_NG, | ||||
|     "A3_GND": ADS1115Multiplexer.ADS1115_MULTIPLEXER_P3_NG, | ||||
| } | ||||
|  | ||||
| ADS1115Gain = ads1115_ns.enum('ADS1115Gain') | ||||
| ADS1115Gain = ads1115_ns.enum("ADS1115Gain") | ||||
| GAIN = { | ||||
|     '6.144': ADS1115Gain.ADS1115_GAIN_6P144, | ||||
|     '4.096': ADS1115Gain.ADS1115_GAIN_4P096, | ||||
|     '2.048': ADS1115Gain.ADS1115_GAIN_2P048, | ||||
|     '1.024': ADS1115Gain.ADS1115_GAIN_1P024, | ||||
|     '0.512': ADS1115Gain.ADS1115_GAIN_0P512, | ||||
|     '0.256': ADS1115Gain.ADS1115_GAIN_0P256, | ||||
|     "6.144": ADS1115Gain.ADS1115_GAIN_6P144, | ||||
|     "4.096": ADS1115Gain.ADS1115_GAIN_4P096, | ||||
|     "2.048": ADS1115Gain.ADS1115_GAIN_2P048, | ||||
|     "1.024": ADS1115Gain.ADS1115_GAIN_1P024, | ||||
|     "0.512": ADS1115Gain.ADS1115_GAIN_0P512, | ||||
|     "0.256": ADS1115Gain.ADS1115_GAIN_0P256, | ||||
| } | ||||
|  | ||||
|  | ||||
| def validate_gain(value): | ||||
|     if isinstance(value, float): | ||||
|         value = f'{value:0.03f}' | ||||
|         value = f"{value:0.03f}" | ||||
|     elif not isinstance(value, str): | ||||
|         raise cv.Invalid(f'invalid gain "{value}"') | ||||
|  | ||||
|     return cv.enum(GAIN)(value) | ||||
|  | ||||
|  | ||||
| ADS1115Sensor = ads1115_ns.class_('ADS1115Sensor', sensor.Sensor, cg.PollingComponent, | ||||
|                                   voltage_sampler.VoltageSampler) | ||||
| ADS1115Sensor = ads1115_ns.class_( | ||||
|     "ADS1115Sensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler | ||||
| ) | ||||
|  | ||||
| CONF_ADS1115_ID = 'ads1115_id' | ||||
| CONFIG_SCHEMA = sensor.sensor_schema(UNIT_VOLT, ICON_EMPTY, 3, DEVICE_CLASS_VOLTAGE).extend({ | ||||
|     cv.GenerateID(): cv.declare_id(ADS1115Sensor), | ||||
|     cv.GenerateID(CONF_ADS1115_ID): cv.use_id(ADS1115Component), | ||||
|     cv.Required(CONF_MULTIPLEXER): cv.enum(MUX, upper=True, space='_'), | ||||
|     cv.Required(CONF_GAIN): validate_gain, | ||||
| }).extend(cv.polling_component_schema('60s')) | ||||
| CONF_ADS1115_ID = "ads1115_id" | ||||
| CONFIG_SCHEMA = ( | ||||
|     sensor.sensor_schema(UNIT_VOLT, ICON_EMPTY, 3, DEVICE_CLASS_VOLTAGE) | ||||
|     .extend( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(ADS1115Sensor), | ||||
|             cv.GenerateID(CONF_ADS1115_ID): cv.use_id(ADS1115Component), | ||||
|             cv.Required(CONF_MULTIPLEXER): cv.enum(MUX, upper=True, space="_"), | ||||
|             cv.Required(CONF_GAIN): validate_gain, | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,21 +1,37 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.const import CONF_HUMIDITY, CONF_ID, CONF_TEMPERATURE, DEVICE_CLASS_HUMIDITY, \ | ||||
|     DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, UNIT_CELSIUS, UNIT_PERCENT | ||||
| from esphome.const import ( | ||||
|     CONF_HUMIDITY, | ||||
|     CONF_ID, | ||||
|     CONF_TEMPERATURE, | ||||
|     DEVICE_CLASS_HUMIDITY, | ||||
|     DEVICE_CLASS_TEMPERATURE, | ||||
|     ICON_EMPTY, | ||||
|     UNIT_CELSIUS, | ||||
|     UNIT_PERCENT, | ||||
| ) | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| DEPENDENCIES = ["i2c"] | ||||
|  | ||||
| aht10_ns = cg.esphome_ns.namespace('aht10') | ||||
| AHT10Component = aht10_ns.class_('AHT10Component', cg.PollingComponent, i2c.I2CDevice) | ||||
| aht10_ns = cg.esphome_ns.namespace("aht10") | ||||
| AHT10Component = aht10_ns.class_("AHT10Component", cg.PollingComponent, i2c.I2CDevice) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(AHT10Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 2, | ||||
|                                                         DEVICE_CLASS_TEMPERATURE), | ||||
|     cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 2, | ||||
|                                                      DEVICE_CLASS_HUMIDITY), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x38)) | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(AHT10Component), | ||||
|             cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( | ||||
|                 UNIT_CELSIUS, ICON_EMPTY, 2, DEVICE_CLASS_TEMPERATURE | ||||
|             ), | ||||
|             cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( | ||||
|                 UNIT_PERCENT, ICON_EMPTY, 2, DEVICE_CLASS_HUMIDITY | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
|     .extend(i2c.i2c_device_schema(0x38)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,21 +1,39 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.const import CONF_HUMIDITY, CONF_ID, CONF_TEMPERATURE, DEVICE_CLASS_HUMIDITY, \ | ||||
|     DEVICE_CLASS_TEMPERATURE, UNIT_CELSIUS, ICON_EMPTY, UNIT_PERCENT | ||||
| from esphome.const import ( | ||||
|     CONF_HUMIDITY, | ||||
|     CONF_ID, | ||||
|     CONF_TEMPERATURE, | ||||
|     DEVICE_CLASS_HUMIDITY, | ||||
|     DEVICE_CLASS_TEMPERATURE, | ||||
|     UNIT_CELSIUS, | ||||
|     ICON_EMPTY, | ||||
|     UNIT_PERCENT, | ||||
| ) | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| DEPENDENCIES = ["i2c"] | ||||
|  | ||||
| am2320_ns = cg.esphome_ns.namespace('am2320') | ||||
| AM2320Component = am2320_ns.class_('AM2320Component', cg.PollingComponent, i2c.I2CDevice) | ||||
| am2320_ns = cg.esphome_ns.namespace("am2320") | ||||
| AM2320Component = am2320_ns.class_( | ||||
|     "AM2320Component", cg.PollingComponent, i2c.I2CDevice | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(AM2320Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, | ||||
|                                                         DEVICE_CLASS_TEMPERATURE), | ||||
|     cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 1, | ||||
|                                                      DEVICE_CLASS_HUMIDITY), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x5C)) | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(AM2320Component), | ||||
|             cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( | ||||
|                 UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE | ||||
|             ), | ||||
|             cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( | ||||
|                 UNIT_PERCENT, ICON_EMPTY, 1, DEVICE_CLASS_HUMIDITY | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
|     .extend(i2c.i2c_device_schema(0x5C)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -10,24 +10,28 @@ from esphome.core import CORE, HexInt | ||||
|  | ||||
| _LOGGER = logging.getLogger(__name__) | ||||
|  | ||||
| DEPENDENCIES = ['display'] | ||||
| DEPENDENCIES = ["display"] | ||||
| MULTI_CONF = True | ||||
|  | ||||
| Animation_ = display.display_ns.class_('Animation') | ||||
| Animation_ = display.display_ns.class_("Animation") | ||||
|  | ||||
| CONF_RAW_DATA_ID = 'raw_data_id' | ||||
| CONF_RAW_DATA_ID = "raw_data_id" | ||||
|  | ||||
| ANIMATION_SCHEMA = cv.Schema({ | ||||
|     cv.Required(CONF_ID): cv.declare_id(Animation_), | ||||
|     cv.Required(CONF_FILE): cv.file_, | ||||
|     cv.Optional(CONF_RESIZE): cv.dimensions, | ||||
|     cv.Optional(CONF_TYPE, default='BINARY'): cv.enum(espImage.IMAGE_TYPE, upper=True), | ||||
|     cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8), | ||||
| }) | ||||
| ANIMATION_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.Required(CONF_ID): cv.declare_id(Animation_), | ||||
|         cv.Required(CONF_FILE): cv.file_, | ||||
|         cv.Optional(CONF_RESIZE): cv.dimensions, | ||||
|         cv.Optional(CONF_TYPE, default="BINARY"): cv.enum( | ||||
|             espImage.IMAGE_TYPE, upper=True | ||||
|         ), | ||||
|         cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8), | ||||
|     } | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All(font.validate_pillow_installed, ANIMATION_SCHEMA) | ||||
|  | ||||
| CODEOWNERS = ['@syndlex'] | ||||
| CODEOWNERS = ["@syndlex"] | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
| @@ -46,26 +50,28 @@ def to_code(config): | ||||
|         width, height = image.size | ||||
|     else: | ||||
|         if width > 500 or height > 500: | ||||
|             _LOGGER.warning("The image you requested is very big. Please consider using" | ||||
|                             " the resize parameter.") | ||||
|             _LOGGER.warning( | ||||
|                 "The image you requested is very big. Please consider using" | ||||
|                 " the resize parameter." | ||||
|             ) | ||||
|  | ||||
|     if config[CONF_TYPE] == 'GRAYSCALE': | ||||
|     if config[CONF_TYPE] == "GRAYSCALE": | ||||
|         data = [0 for _ in range(height * width * frames)] | ||||
|         pos = 0 | ||||
|         for frameIndex in range(frames): | ||||
|             image.seek(frameIndex) | ||||
|             frame = image.convert('L', dither=Image.NONE) | ||||
|             frame = image.convert("L", dither=Image.NONE) | ||||
|             pixels = list(frame.getdata()) | ||||
|             for pix in pixels: | ||||
|                 data[pos] = pix | ||||
|                 pos += 1 | ||||
|  | ||||
|     elif config[CONF_TYPE] == 'RGB24': | ||||
|     elif config[CONF_TYPE] == "RGB24": | ||||
|         data = [0 for _ in range(height * width * 3 * frames)] | ||||
|         pos = 0 | ||||
|         for frameIndex in range(frames): | ||||
|             image.seek(frameIndex) | ||||
|             frame = image.convert('RGB') | ||||
|             frame = image.convert("RGB") | ||||
|             pixels = list(frame.getdata()) | ||||
|             for pix in pixels: | ||||
|                 data[pos] = pix[0] | ||||
| @@ -75,12 +81,12 @@ def to_code(config): | ||||
|                 data[pos] = pix[2] | ||||
|                 pos += 1 | ||||
|  | ||||
|     elif config[CONF_TYPE] == 'BINARY': | ||||
|     elif config[CONF_TYPE] == "BINARY": | ||||
|         width8 = ((width + 7) // 8) * 8 | ||||
|         data = [0 for _ in range((height * width8 // 8) * frames)] | ||||
|         for frameIndex in range(frames): | ||||
|             image.seek(frameIndex) | ||||
|             frame = image.convert('1', dither=Image.NONE) | ||||
|             frame = image.convert("1", dither=Image.NONE) | ||||
|             for y in range(height): | ||||
|                 for x in range(width): | ||||
|                     if frame.getpixel((x, y)): | ||||
| @@ -90,5 +96,11 @@ def to_code(config): | ||||
|  | ||||
|     rhs = [HexInt(x) for x in data] | ||||
|     prog_arr = cg.progmem_array(config[CONF_RAW_DATA_ID], rhs) | ||||
|     cg.new_Pvariable(config[CONF_ID], prog_arr, width, height, frames, | ||||
|                      espImage.IMAGE_TYPE[config[CONF_TYPE]]) | ||||
|     cg.new_Pvariable( | ||||
|         config[CONF_ID], | ||||
|         prog_arr, | ||||
|         width, | ||||
|         height, | ||||
|         frames, | ||||
|         espImage.IMAGE_TYPE[config[CONF_TYPE]], | ||||
|     ) | ||||
|   | ||||
| @@ -3,18 +3,24 @@ import esphome.config_validation as cv | ||||
| from esphome.components import i2c | ||||
| from esphome.const import CONF_ID | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| AUTO_LOAD = ['sensor', 'binary_sensor'] | ||||
| DEPENDENCIES = ["i2c"] | ||||
| AUTO_LOAD = ["sensor", "binary_sensor"] | ||||
| MULTI_CONF = True | ||||
|  | ||||
| CONF_APDS9960_ID = 'apds9960_id' | ||||
| CONF_APDS9960_ID = "apds9960_id" | ||||
|  | ||||
| apds9960_nds = cg.esphome_ns.namespace('apds9960') | ||||
| APDS9960 = apds9960_nds.class_('APDS9960', cg.PollingComponent, i2c.I2CDevice) | ||||
| apds9960_nds = cg.esphome_ns.namespace("apds9960") | ||||
| APDS9960 = apds9960_nds.class_("APDS9960", cg.PollingComponent, i2c.I2CDevice) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(APDS9960), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x39)) | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(APDS9960), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
|     .extend(i2c.i2c_device_schema(0x39)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -4,20 +4,24 @@ from esphome.components import binary_sensor | ||||
| from esphome.const import CONF_DIRECTION, CONF_DEVICE_CLASS, DEVICE_CLASS_MOVING | ||||
| from . import APDS9960, CONF_APDS9960_ID | ||||
|  | ||||
| DEPENDENCIES = ['apds9960'] | ||||
| DEPENDENCIES = ["apds9960"] | ||||
|  | ||||
| DIRECTIONS = { | ||||
|     'UP': 'set_up_direction', | ||||
|     'DOWN': 'set_down_direction', | ||||
|     'LEFT': 'set_left_direction', | ||||
|     'RIGHT': 'set_right_direction', | ||||
|     "UP": "set_up_direction", | ||||
|     "DOWN": "set_down_direction", | ||||
|     "LEFT": "set_left_direction", | ||||
|     "RIGHT": "set_right_direction", | ||||
| } | ||||
|  | ||||
| CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ | ||||
|     cv.Required(CONF_DIRECTION): cv.one_of(*DIRECTIONS, upper=True), | ||||
|     cv.GenerateID(CONF_APDS9960_ID): cv.use_id(APDS9960), | ||||
|     cv.Optional(CONF_DEVICE_CLASS, default=DEVICE_CLASS_MOVING): binary_sensor.device_class, | ||||
| }) | ||||
| CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( | ||||
|     { | ||||
|         cv.Required(CONF_DIRECTION): cv.one_of(*DIRECTIONS, upper=True), | ||||
|         cv.GenerateID(CONF_APDS9960_ID): cv.use_id(APDS9960), | ||||
|         cv.Optional( | ||||
|             CONF_DEVICE_CLASS, default=DEVICE_CLASS_MOVING | ||||
|         ): binary_sensor.device_class, | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -4,20 +4,24 @@ from esphome.components import sensor | ||||
| from esphome.const import CONF_TYPE, DEVICE_CLASS_EMPTY, UNIT_PERCENT, ICON_LIGHTBULB | ||||
| from . import APDS9960, CONF_APDS9960_ID | ||||
|  | ||||
| DEPENDENCIES = ['apds9960'] | ||||
| DEPENDENCIES = ["apds9960"] | ||||
|  | ||||
| TYPES = { | ||||
|     'CLEAR': 'set_clear_channel', | ||||
|     'RED': 'set_red_channel', | ||||
|     'GREEN': 'set_green_channel', | ||||
|     'BLUE': 'set_blue_channel', | ||||
|     'PROXIMITY': 'set_proximity', | ||||
|     "CLEAR": "set_clear_channel", | ||||
|     "RED": "set_red_channel", | ||||
|     "GREEN": "set_green_channel", | ||||
|     "BLUE": "set_blue_channel", | ||||
|     "PROXIMITY": "set_proximity", | ||||
| } | ||||
|  | ||||
| CONFIG_SCHEMA = sensor.sensor_schema(UNIT_PERCENT, ICON_LIGHTBULB, 1, DEVICE_CLASS_EMPTY).extend({ | ||||
|     cv.Required(CONF_TYPE): cv.one_of(*TYPES, upper=True), | ||||
|     cv.GenerateID(CONF_APDS9960_ID): cv.use_id(APDS9960), | ||||
| }) | ||||
| CONFIG_SCHEMA = sensor.sensor_schema( | ||||
|     UNIT_PERCENT, ICON_LIGHTBULB, 1, DEVICE_CLASS_EMPTY | ||||
| ).extend( | ||||
|     { | ||||
|         cv.Required(CONF_TYPE): cv.one_of(*TYPES, upper=True), | ||||
|         cv.GenerateID(CONF_APDS9960_ID): cv.use_id(APDS9960), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -2,46 +2,69 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import automation | ||||
| from esphome.automation import Condition | ||||
| from esphome.const import CONF_DATA, CONF_DATA_TEMPLATE, CONF_ID, CONF_PASSWORD, CONF_PORT, \ | ||||
|     CONF_REBOOT_TIMEOUT, CONF_SERVICE, CONF_VARIABLES, CONF_SERVICES, CONF_TRIGGER_ID, CONF_EVENT, \ | ||||
|     CONF_TAG | ||||
| from esphome.const import ( | ||||
|     CONF_DATA, | ||||
|     CONF_DATA_TEMPLATE, | ||||
|     CONF_ID, | ||||
|     CONF_PASSWORD, | ||||
|     CONF_PORT, | ||||
|     CONF_REBOOT_TIMEOUT, | ||||
|     CONF_SERVICE, | ||||
|     CONF_VARIABLES, | ||||
|     CONF_SERVICES, | ||||
|     CONF_TRIGGER_ID, | ||||
|     CONF_EVENT, | ||||
|     CONF_TAG, | ||||
| ) | ||||
| from esphome.core import coroutine_with_priority | ||||
|  | ||||
| DEPENDENCIES = ['network'] | ||||
| AUTO_LOAD = ['async_tcp'] | ||||
| CODEOWNERS = ['@OttoWinter'] | ||||
| DEPENDENCIES = ["network"] | ||||
| AUTO_LOAD = ["async_tcp"] | ||||
| CODEOWNERS = ["@OttoWinter"] | ||||
|  | ||||
| api_ns = cg.esphome_ns.namespace('api') | ||||
| APIServer = api_ns.class_('APIServer', cg.Component, cg.Controller) | ||||
| HomeAssistantServiceCallAction = api_ns.class_('HomeAssistantServiceCallAction', automation.Action) | ||||
| APIConnectedCondition = api_ns.class_('APIConnectedCondition', Condition) | ||||
| api_ns = cg.esphome_ns.namespace("api") | ||||
| APIServer = api_ns.class_("APIServer", cg.Component, cg.Controller) | ||||
| HomeAssistantServiceCallAction = api_ns.class_( | ||||
|     "HomeAssistantServiceCallAction", automation.Action | ||||
| ) | ||||
| APIConnectedCondition = api_ns.class_("APIConnectedCondition", Condition) | ||||
|  | ||||
| UserServiceTrigger = api_ns.class_('UserServiceTrigger', automation.Trigger) | ||||
| ListEntitiesServicesArgument = api_ns.class_('ListEntitiesServicesArgument') | ||||
| UserServiceTrigger = api_ns.class_("UserServiceTrigger", automation.Trigger) | ||||
| ListEntitiesServicesArgument = api_ns.class_("ListEntitiesServicesArgument") | ||||
| SERVICE_ARG_NATIVE_TYPES = { | ||||
|     'bool': bool, | ||||
|     'int': cg.int32, | ||||
|     'float': float, | ||||
|     'string': cg.std_string, | ||||
|     'bool[]': cg.std_vector.template(bool), | ||||
|     'int[]': cg.std_vector.template(cg.int32), | ||||
|     'float[]': cg.std_vector.template(float), | ||||
|     'string[]': cg.std_vector.template(cg.std_string), | ||||
|     "bool": bool, | ||||
|     "int": cg.int32, | ||||
|     "float": float, | ||||
|     "string": cg.std_string, | ||||
|     "bool[]": cg.std_vector.template(bool), | ||||
|     "int[]": cg.std_vector.template(cg.int32), | ||||
|     "float[]": cg.std_vector.template(float), | ||||
|     "string[]": cg.std_vector.template(cg.std_string), | ||||
| } | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(APIServer), | ||||
|     cv.Optional(CONF_PORT, default=6053): cv.port, | ||||
|     cv.Optional(CONF_PASSWORD, default=''): cv.string_strict, | ||||
|     cv.Optional(CONF_REBOOT_TIMEOUT, default='15min'): cv.positive_time_period_milliseconds, | ||||
|     cv.Optional(CONF_SERVICES): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(UserServiceTrigger), | ||||
|         cv.Required(CONF_SERVICE): cv.valid_name, | ||||
|         cv.Optional(CONF_VARIABLES, default={}): cv.Schema({ | ||||
|             cv.validate_id_name: cv.one_of(*SERVICE_ARG_NATIVE_TYPES, lower=True), | ||||
|         }), | ||||
|     }), | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(APIServer), | ||||
|         cv.Optional(CONF_PORT, default=6053): cv.port, | ||||
|         cv.Optional(CONF_PASSWORD, default=""): cv.string_strict, | ||||
|         cv.Optional( | ||||
|             CONF_REBOOT_TIMEOUT, default="15min" | ||||
|         ): cv.positive_time_period_milliseconds, | ||||
|         cv.Optional(CONF_SERVICES): automation.validate_automation( | ||||
|             { | ||||
|                 cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(UserServiceTrigger), | ||||
|                 cv.Required(CONF_SERVICE): cv.valid_name, | ||||
|                 cv.Optional(CONF_VARIABLES, default={}): cv.Schema( | ||||
|                     { | ||||
|                         cv.validate_id_name: cv.one_of( | ||||
|                             *SERVICE_ARG_NATIVE_TYPES, lower=True | ||||
|                         ), | ||||
|                     } | ||||
|                 ), | ||||
|             } | ||||
|         ), | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| @coroutine_with_priority(40.0) | ||||
| @@ -63,28 +86,36 @@ def to_code(config): | ||||
|             func_args.append((native, name)) | ||||
|             service_arg_names.append(name) | ||||
|         templ = cg.TemplateArguments(*template_args) | ||||
|         trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], templ, | ||||
|                                    conf[CONF_SERVICE], service_arg_names) | ||||
|         trigger = cg.new_Pvariable( | ||||
|             conf[CONF_TRIGGER_ID], templ, conf[CONF_SERVICE], service_arg_names | ||||
|         ) | ||||
|         cg.add(var.register_user_service(trigger)) | ||||
|         yield automation.build_automation(trigger, func_args, conf) | ||||
|  | ||||
|     cg.add_define('USE_API') | ||||
|     cg.add_define("USE_API") | ||||
|     cg.add_global(api_ns.using) | ||||
|  | ||||
|  | ||||
| KEY_VALUE_SCHEMA = cv.Schema({cv.string: cv.templatable(cv.string_strict)}) | ||||
|  | ||||
| HOMEASSISTANT_SERVICE_ACTION_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.use_id(APIServer), | ||||
|     cv.Required(CONF_SERVICE): cv.templatable(cv.string), | ||||
|     cv.Optional(CONF_DATA, default={}): KEY_VALUE_SCHEMA, | ||||
|     cv.Optional(CONF_DATA_TEMPLATE, default={}): KEY_VALUE_SCHEMA, | ||||
|     cv.Optional(CONF_VARIABLES, default={}): cv.Schema({cv.string: cv.returning_lambda}), | ||||
| }) | ||||
| HOMEASSISTANT_SERVICE_ACTION_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.use_id(APIServer), | ||||
|         cv.Required(CONF_SERVICE): cv.templatable(cv.string), | ||||
|         cv.Optional(CONF_DATA, default={}): KEY_VALUE_SCHEMA, | ||||
|         cv.Optional(CONF_DATA_TEMPLATE, default={}): KEY_VALUE_SCHEMA, | ||||
|         cv.Optional(CONF_VARIABLES, default={}): cv.Schema( | ||||
|             {cv.string: cv.returning_lambda} | ||||
|         ), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @automation.register_action('homeassistant.service', HomeAssistantServiceCallAction, | ||||
|                             HOMEASSISTANT_SERVICE_ACTION_SCHEMA) | ||||
| @automation.register_action( | ||||
|     "homeassistant.service", | ||||
|     HomeAssistantServiceCallAction, | ||||
|     HOMEASSISTANT_SERVICE_ACTION_SCHEMA, | ||||
| ) | ||||
| def homeassistant_service_to_code(config, action_id, template_arg, args): | ||||
|     serv = yield cg.get_variable(config[CONF_ID]) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, serv, False) | ||||
| @@ -104,23 +135,30 @@ def homeassistant_service_to_code(config, action_id, template_arg, args): | ||||
|  | ||||
| def validate_homeassistant_event(value): | ||||
|     value = cv.string(value) | ||||
|     if not value.startswith('esphome.'): | ||||
|         raise cv.Invalid("ESPHome can only generate Home Assistant events that begin with " | ||||
|                          "esphome. For example 'esphome.xyz'") | ||||
|     if not value.startswith("esphome."): | ||||
|         raise cv.Invalid( | ||||
|             "ESPHome can only generate Home Assistant events that begin with " | ||||
|             "esphome. For example 'esphome.xyz'" | ||||
|         ) | ||||
|     return value | ||||
|  | ||||
|  | ||||
| HOMEASSISTANT_EVENT_ACTION_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.use_id(APIServer), | ||||
|     cv.Required(CONF_EVENT): validate_homeassistant_event, | ||||
|     cv.Optional(CONF_DATA, default={}): KEY_VALUE_SCHEMA, | ||||
|     cv.Optional(CONF_DATA_TEMPLATE, default={}): KEY_VALUE_SCHEMA, | ||||
|     cv.Optional(CONF_VARIABLES, default={}): KEY_VALUE_SCHEMA, | ||||
| }) | ||||
| HOMEASSISTANT_EVENT_ACTION_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.use_id(APIServer), | ||||
|         cv.Required(CONF_EVENT): validate_homeassistant_event, | ||||
|         cv.Optional(CONF_DATA, default={}): KEY_VALUE_SCHEMA, | ||||
|         cv.Optional(CONF_DATA_TEMPLATE, default={}): KEY_VALUE_SCHEMA, | ||||
|         cv.Optional(CONF_VARIABLES, default={}): KEY_VALUE_SCHEMA, | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @automation.register_action('homeassistant.event', HomeAssistantServiceCallAction, | ||||
|                             HOMEASSISTANT_EVENT_ACTION_SCHEMA) | ||||
| @automation.register_action( | ||||
|     "homeassistant.event", | ||||
|     HomeAssistantServiceCallAction, | ||||
|     HOMEASSISTANT_EVENT_ACTION_SCHEMA, | ||||
| ) | ||||
| def homeassistant_event_to_code(config, action_id, template_arg, args): | ||||
|     serv = yield cg.get_variable(config[CONF_ID]) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, serv, True) | ||||
| @@ -138,23 +176,29 @@ def homeassistant_event_to_code(config, action_id, template_arg, args): | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| HOMEASSISTANT_TAG_SCANNED_ACTION_SCHEMA = cv.maybe_simple_value({ | ||||
|     cv.GenerateID(): cv.use_id(APIServer), | ||||
|     cv.Required(CONF_TAG): cv.templatable(cv.string_strict), | ||||
| }, key=CONF_TAG) | ||||
| HOMEASSISTANT_TAG_SCANNED_ACTION_SCHEMA = cv.maybe_simple_value( | ||||
|     { | ||||
|         cv.GenerateID(): cv.use_id(APIServer), | ||||
|         cv.Required(CONF_TAG): cv.templatable(cv.string_strict), | ||||
|     }, | ||||
|     key=CONF_TAG, | ||||
| ) | ||||
|  | ||||
|  | ||||
| @automation.register_action('homeassistant.tag_scanned', HomeAssistantServiceCallAction, | ||||
|                             HOMEASSISTANT_TAG_SCANNED_ACTION_SCHEMA) | ||||
| @automation.register_action( | ||||
|     "homeassistant.tag_scanned", | ||||
|     HomeAssistantServiceCallAction, | ||||
|     HOMEASSISTANT_TAG_SCANNED_ACTION_SCHEMA, | ||||
| ) | ||||
| def homeassistant_tag_scanned_to_code(config, action_id, template_arg, args): | ||||
|     serv = yield cg.get_variable(config[CONF_ID]) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, serv, True) | ||||
|     cg.add(var.set_service('esphome.tag_scanned')) | ||||
|     cg.add(var.set_service("esphome.tag_scanned")) | ||||
|     templ = yield cg.templatable(config[CONF_TAG], args, cg.std_string) | ||||
|     cg.add(var.add_data('tag_id', templ)) | ||||
|     cg.add(var.add_data("tag_id", templ)) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_condition('api.connected', APIConnectedCondition, {}) | ||||
| @automation.register_condition("api.connected", APIConnectedCondition, {}) | ||||
| def api_connected_to_code(config, condition_id, template_arg, args): | ||||
|     yield cg.new_Pvariable(condition_id, template_arg) | ||||
|   | ||||
| @@ -1,33 +1,43 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.const import CONF_INDOOR, CONF_WATCHDOG_THRESHOLD, \ | ||||
|     CONF_NOISE_LEVEL, CONF_SPIKE_REJECTION, CONF_LIGHTNING_THRESHOLD, \ | ||||
|     CONF_MASK_DISTURBER, CONF_DIV_RATIO, CONF_CAPACITANCE | ||||
| from esphome.const import ( | ||||
|     CONF_INDOOR, | ||||
|     CONF_WATCHDOG_THRESHOLD, | ||||
|     CONF_NOISE_LEVEL, | ||||
|     CONF_SPIKE_REJECTION, | ||||
|     CONF_LIGHTNING_THRESHOLD, | ||||
|     CONF_MASK_DISTURBER, | ||||
|     CONF_DIV_RATIO, | ||||
|     CONF_CAPACITANCE, | ||||
| ) | ||||
| from esphome.core import coroutine | ||||
|  | ||||
| AUTO_LOAD = ['sensor', 'binary_sensor'] | ||||
| AUTO_LOAD = ["sensor", "binary_sensor"] | ||||
| MULTI_CONF = True | ||||
|  | ||||
| CONF_AS3935_ID = 'as3935_id' | ||||
| CONF_AS3935_ID = "as3935_id" | ||||
|  | ||||
| as3935_ns = cg.esphome_ns.namespace('as3935') | ||||
| AS3935 = as3935_ns.class_('AS3935Component', cg.Component) | ||||
| as3935_ns = cg.esphome_ns.namespace("as3935") | ||||
| AS3935 = as3935_ns.class_("AS3935Component", cg.Component) | ||||
|  | ||||
| CONF_IRQ_PIN = 'irq_pin' | ||||
| AS3935_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(AS3935), | ||||
|     cv.Required(CONF_IRQ_PIN): pins.gpio_input_pin_schema, | ||||
|  | ||||
|     cv.Optional(CONF_INDOOR, default=True): cv.boolean, | ||||
|     cv.Optional(CONF_NOISE_LEVEL, default=2): cv.int_range(min=1, max=7), | ||||
|     cv.Optional(CONF_WATCHDOG_THRESHOLD, default=2): cv.int_range(min=1, max=10), | ||||
|     cv.Optional(CONF_SPIKE_REJECTION, default=2): cv.int_range(min=1, max=11), | ||||
|     cv.Optional(CONF_LIGHTNING_THRESHOLD, default=1): cv.one_of(1, 5, 9, 16, int=True), | ||||
|     cv.Optional(CONF_MASK_DISTURBER, default=False): cv.boolean, | ||||
|     cv.Optional(CONF_DIV_RATIO, default=0): cv.one_of(0, 16, 32, 64, 128, int=True), | ||||
|     cv.Optional(CONF_CAPACITANCE, default=0): cv.int_range(min=0, max=15), | ||||
| }) | ||||
| CONF_IRQ_PIN = "irq_pin" | ||||
| AS3935_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(AS3935), | ||||
|         cv.Required(CONF_IRQ_PIN): pins.gpio_input_pin_schema, | ||||
|         cv.Optional(CONF_INDOOR, default=True): cv.boolean, | ||||
|         cv.Optional(CONF_NOISE_LEVEL, default=2): cv.int_range(min=1, max=7), | ||||
|         cv.Optional(CONF_WATCHDOG_THRESHOLD, default=2): cv.int_range(min=1, max=10), | ||||
|         cv.Optional(CONF_SPIKE_REJECTION, default=2): cv.int_range(min=1, max=11), | ||||
|         cv.Optional(CONF_LIGHTNING_THRESHOLD, default=1): cv.one_of( | ||||
|             1, 5, 9, 16, int=True | ||||
|         ), | ||||
|         cv.Optional(CONF_MASK_DISTURBER, default=False): cv.boolean, | ||||
|         cv.Optional(CONF_DIV_RATIO, default=0): cv.one_of(0, 16, 32, 64, 128, int=True), | ||||
|         cv.Optional(CONF_CAPACITANCE, default=0): cv.int_range(min=0, max=15), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
|   | ||||
| @@ -3,11 +3,13 @@ import esphome.config_validation as cv | ||||
| from esphome.components import binary_sensor | ||||
| from . import AS3935, CONF_AS3935_ID | ||||
|  | ||||
| DEPENDENCIES = ['as3935'] | ||||
| DEPENDENCIES = ["as3935"] | ||||
|  | ||||
| CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ | ||||
|     cv.GenerateID(CONF_AS3935_ID): cv.use_id(AS3935), | ||||
| }) | ||||
| CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(CONF_AS3935_ID): cv.use_id(AS3935), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,19 +1,30 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor | ||||
| from esphome.const import CONF_DISTANCE, CONF_LIGHTNING_ENERGY, DEVICE_CLASS_EMPTY, \ | ||||
|     UNIT_KILOMETER, UNIT_EMPTY, ICON_SIGNAL_DISTANCE_VARIANT, ICON_FLASH | ||||
| from esphome.const import ( | ||||
|     CONF_DISTANCE, | ||||
|     CONF_LIGHTNING_ENERGY, | ||||
|     DEVICE_CLASS_EMPTY, | ||||
|     UNIT_KILOMETER, | ||||
|     UNIT_EMPTY, | ||||
|     ICON_SIGNAL_DISTANCE_VARIANT, | ||||
|     ICON_FLASH, | ||||
| ) | ||||
| from . import AS3935, CONF_AS3935_ID | ||||
|  | ||||
| DEPENDENCIES = ['as3935'] | ||||
| DEPENDENCIES = ["as3935"] | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(CONF_AS3935_ID): cv.use_id(AS3935), | ||||
|     cv.Optional(CONF_DISTANCE): | ||||
|         sensor.sensor_schema(UNIT_KILOMETER, ICON_SIGNAL_DISTANCE_VARIANT, 1, DEVICE_CLASS_EMPTY), | ||||
|     cv.Optional(CONF_LIGHTNING_ENERGY): | ||||
|         sensor.sensor_schema(UNIT_EMPTY, ICON_FLASH, 1, DEVICE_CLASS_EMPTY), | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(CONF_AS3935_ID): cv.use_id(AS3935), | ||||
|         cv.Optional(CONF_DISTANCE): sensor.sensor_schema( | ||||
|             UNIT_KILOMETER, ICON_SIGNAL_DISTANCE_VARIANT, 1, DEVICE_CLASS_EMPTY | ||||
|         ), | ||||
|         cv.Optional(CONF_LIGHTNING_ENERGY): sensor.sensor_schema( | ||||
|             UNIT_EMPTY, ICON_FLASH, 1, DEVICE_CLASS_EMPTY | ||||
|         ), | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -3,15 +3,21 @@ import esphome.config_validation as cv | ||||
| from esphome.components import as3935, i2c | ||||
| from esphome.const import CONF_ID | ||||
|  | ||||
| AUTO_LOAD = ['as3935'] | ||||
| DEPENDENCIES = ['i2c'] | ||||
| AUTO_LOAD = ["as3935"] | ||||
| DEPENDENCIES = ["i2c"] | ||||
|  | ||||
| as3935_i2c_ns = cg.esphome_ns.namespace('as3935_i2c') | ||||
| I2CAS3935 = as3935_i2c_ns.class_('I2CAS3935Component', as3935.AS3935, i2c.I2CDevice) | ||||
| as3935_i2c_ns = cg.esphome_ns.namespace("as3935_i2c") | ||||
| I2CAS3935 = as3935_i2c_ns.class_("I2CAS3935Component", as3935.AS3935, i2c.I2CDevice) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All(as3935.AS3935_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(I2CAS3935), | ||||
| }).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x03))) | ||||
| CONFIG_SCHEMA = cv.All( | ||||
|     as3935.AS3935_SCHEMA.extend( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(I2CAS3935), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.COMPONENT_SCHEMA) | ||||
|     .extend(i2c.i2c_device_schema(0x03)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -3,15 +3,21 @@ import esphome.config_validation as cv | ||||
| from esphome.components import as3935, spi | ||||
| from esphome.const import CONF_ID | ||||
|  | ||||
| AUTO_LOAD = ['as3935'] | ||||
| DEPENDENCIES = ['spi'] | ||||
| AUTO_LOAD = ["as3935"] | ||||
| DEPENDENCIES = ["spi"] | ||||
|  | ||||
| as3935_spi_ns = cg.esphome_ns.namespace('as3935_spi') | ||||
| SPIAS3935 = as3935_spi_ns.class_('SPIAS3935Component', as3935.AS3935, spi.SPIDevice) | ||||
| as3935_spi_ns = cg.esphome_ns.namespace("as3935_spi") | ||||
| SPIAS3935 = as3935_spi_ns.class_("SPIAS3935Component", as3935.AS3935, spi.SPIDevice) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All(as3935.AS3935_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(SPIAS3935), | ||||
| }).extend(cv.COMPONENT_SCHEMA).extend(spi.spi_device_schema(cs_pin_required=True))) | ||||
| CONFIG_SCHEMA = cv.All( | ||||
|     as3935.AS3935_SCHEMA.extend( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(SPIAS3935), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.COMPONENT_SCHEMA) | ||||
|     .extend(spi.spi_device_schema(cs_pin_required=True)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -2,14 +2,14 @@ | ||||
| import esphome.codegen as cg | ||||
| from esphome.core import CORE, coroutine_with_priority | ||||
|  | ||||
| CODEOWNERS = ['@OttoWinter'] | ||||
| CODEOWNERS = ["@OttoWinter"] | ||||
|  | ||||
|  | ||||
| @coroutine_with_priority(200.0) | ||||
| def to_code(config): | ||||
|     if CORE.is_esp32: | ||||
|         # https://github.com/OttoWinter/AsyncTCP/blob/master/library.json | ||||
|         cg.add_library('AsyncTCP-esphome', '1.1.1') | ||||
|         cg.add_library("AsyncTCP-esphome", "1.1.1") | ||||
|     elif CORE.is_esp8266: | ||||
|         # https://github.com/OttoWinter/ESPAsyncTCP | ||||
|         cg.add_library('ESPAsyncTCP-esphome', '1.2.3') | ||||
|         cg.add_library("ESPAsyncTCP-esphome", "1.2.3") | ||||
|   | ||||
| @@ -1,32 +1,54 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor, esp32_ble_tracker | ||||
| from esphome.const import CONF_BATTERY_LEVEL, CONF_BATTERY_VOLTAGE, CONF_MAC_ADDRESS, \ | ||||
|     CONF_HUMIDITY, CONF_TEMPERATURE, CONF_ID, DEVICE_CLASS_BATTERY, DEVICE_CLASS_HUMIDITY, \ | ||||
|     DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_VOLTAGE, ICON_EMPTY, UNIT_CELSIUS, UNIT_PERCENT, \ | ||||
|     UNIT_VOLT | ||||
| from esphome.const import ( | ||||
|     CONF_BATTERY_LEVEL, | ||||
|     CONF_BATTERY_VOLTAGE, | ||||
|     CONF_MAC_ADDRESS, | ||||
|     CONF_HUMIDITY, | ||||
|     CONF_TEMPERATURE, | ||||
|     CONF_ID, | ||||
|     DEVICE_CLASS_BATTERY, | ||||
|     DEVICE_CLASS_HUMIDITY, | ||||
|     DEVICE_CLASS_TEMPERATURE, | ||||
|     DEVICE_CLASS_VOLTAGE, | ||||
|     ICON_EMPTY, | ||||
|     UNIT_CELSIUS, | ||||
|     UNIT_PERCENT, | ||||
|     UNIT_VOLT, | ||||
| ) | ||||
|  | ||||
| CODEOWNERS = ['@ahpohl'] | ||||
| CODEOWNERS = ["@ahpohl"] | ||||
|  | ||||
| DEPENDENCIES = ['esp32_ble_tracker'] | ||||
| DEPENDENCIES = ["esp32_ble_tracker"] | ||||
|  | ||||
| atc_mithermometer_ns = cg.esphome_ns.namespace('atc_mithermometer') | ||||
| ATCMiThermometer = atc_mithermometer_ns.class_('ATCMiThermometer', | ||||
|                                                esp32_ble_tracker.ESPBTDeviceListener, | ||||
|                                                cg.Component) | ||||
| atc_mithermometer_ns = cg.esphome_ns.namespace("atc_mithermometer") | ||||
| ATCMiThermometer = atc_mithermometer_ns.class_( | ||||
|     "ATCMiThermometer", esp32_ble_tracker.ESPBTDeviceListener, cg.Component | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(ATCMiThermometer), | ||||
|     cv.Required(CONF_MAC_ADDRESS): cv.mac_address, | ||||
|     cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, | ||||
|                                                         DEVICE_CLASS_TEMPERATURE), | ||||
|     cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 0, | ||||
|                                                      DEVICE_CLASS_HUMIDITY), | ||||
|     cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 0, | ||||
|                                                           DEVICE_CLASS_BATTERY), | ||||
|     cv.Optional(CONF_BATTERY_VOLTAGE): sensor.sensor_schema(UNIT_VOLT, ICON_EMPTY, 3, | ||||
|                                                             DEVICE_CLASS_VOLTAGE), | ||||
| }).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(ATCMiThermometer), | ||||
|             cv.Required(CONF_MAC_ADDRESS): cv.mac_address, | ||||
|             cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( | ||||
|                 UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE | ||||
|             ), | ||||
|             cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( | ||||
|                 UNIT_PERCENT, ICON_EMPTY, 0, DEVICE_CLASS_HUMIDITY | ||||
|             ), | ||||
|             cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema( | ||||
|                 UNIT_PERCENT, ICON_EMPTY, 0, DEVICE_CLASS_BATTERY | ||||
|             ), | ||||
|             cv.Optional(CONF_BATTERY_VOLTAGE): sensor.sensor_schema( | ||||
|                 UNIT_VOLT, ICON_EMPTY, 3, DEVICE_CLASS_VOLTAGE | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) | ||||
|     .extend(cv.COMPONENT_SCHEMA) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,66 +1,106 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor, spi | ||||
| from esphome.const import \ | ||||
|     CONF_ID, CONF_VOLTAGE, CONF_CURRENT, CONF_POWER, CONF_POWER_FACTOR, CONF_FREQUENCY, \ | ||||
|     DEVICE_CLASS_CURRENT, DEVICE_CLASS_EMPTY, DEVICE_CLASS_POWER, DEVICE_CLASS_POWER_FACTOR, \ | ||||
|     DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_VOLTAGE, ICON_EMPTY, ICON_LIGHTBULB, ICON_CURRENT_AC, \ | ||||
|     UNIT_HERTZ, UNIT_VOLT, UNIT_AMPERE, UNIT_WATT, UNIT_EMPTY, UNIT_CELSIUS, UNIT_VOLT_AMPS_REACTIVE | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     CONF_VOLTAGE, | ||||
|     CONF_CURRENT, | ||||
|     CONF_POWER, | ||||
|     CONF_POWER_FACTOR, | ||||
|     CONF_FREQUENCY, | ||||
|     DEVICE_CLASS_CURRENT, | ||||
|     DEVICE_CLASS_EMPTY, | ||||
|     DEVICE_CLASS_POWER, | ||||
|     DEVICE_CLASS_POWER_FACTOR, | ||||
|     DEVICE_CLASS_TEMPERATURE, | ||||
|     DEVICE_CLASS_VOLTAGE, | ||||
|     ICON_EMPTY, | ||||
|     ICON_LIGHTBULB, | ||||
|     ICON_CURRENT_AC, | ||||
|     UNIT_HERTZ, | ||||
|     UNIT_VOLT, | ||||
|     UNIT_AMPERE, | ||||
|     UNIT_WATT, | ||||
|     UNIT_EMPTY, | ||||
|     UNIT_CELSIUS, | ||||
|     UNIT_VOLT_AMPS_REACTIVE, | ||||
| ) | ||||
|  | ||||
| CONF_PHASE_A = 'phase_a' | ||||
| CONF_PHASE_B = 'phase_b' | ||||
| CONF_PHASE_C = 'phase_c' | ||||
| CONF_PHASE_A = "phase_a" | ||||
| CONF_PHASE_B = "phase_b" | ||||
| CONF_PHASE_C = "phase_c" | ||||
|  | ||||
| CONF_REACTIVE_POWER = 'reactive_power' | ||||
| CONF_LINE_FREQUENCY = 'line_frequency' | ||||
| CONF_CHIP_TEMPERATURE = 'chip_temperature' | ||||
| CONF_GAIN_PGA = 'gain_pga' | ||||
| CONF_CURRENT_PHASES = 'current_phases' | ||||
| CONF_GAIN_VOLTAGE = 'gain_voltage' | ||||
| CONF_GAIN_CT = 'gain_ct' | ||||
| CONF_REACTIVE_POWER = "reactive_power" | ||||
| CONF_LINE_FREQUENCY = "line_frequency" | ||||
| CONF_CHIP_TEMPERATURE = "chip_temperature" | ||||
| CONF_GAIN_PGA = "gain_pga" | ||||
| CONF_CURRENT_PHASES = "current_phases" | ||||
| CONF_GAIN_VOLTAGE = "gain_voltage" | ||||
| CONF_GAIN_CT = "gain_ct" | ||||
| LINE_FREQS = { | ||||
|     '50HZ': 50, | ||||
|     '60HZ': 60, | ||||
|     "50HZ": 50, | ||||
|     "60HZ": 60, | ||||
| } | ||||
| CURRENT_PHASES = { | ||||
|     '2': 2, | ||||
|     '3': 3, | ||||
|     "2": 2, | ||||
|     "3": 3, | ||||
| } | ||||
| PGA_GAINS = { | ||||
|     '1X': 0x0, | ||||
|     '2X': 0x15, | ||||
|     '4X': 0x2A, | ||||
|     "1X": 0x0, | ||||
|     "2X": 0x15, | ||||
|     "4X": 0x2A, | ||||
| } | ||||
|  | ||||
| atm90e32_ns = cg.esphome_ns.namespace('atm90e32') | ||||
| ATM90E32Component = atm90e32_ns.class_('ATM90E32Component', cg.PollingComponent, spi.SPIDevice) | ||||
| atm90e32_ns = cg.esphome_ns.namespace("atm90e32") | ||||
| ATM90E32Component = atm90e32_ns.class_( | ||||
|     "ATM90E32Component", cg.PollingComponent, spi.SPIDevice | ||||
| ) | ||||
|  | ||||
| ATM90E32_PHASE_SCHEMA = cv.Schema({ | ||||
|     cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(UNIT_VOLT, ICON_EMPTY, 2, DEVICE_CLASS_VOLTAGE), | ||||
|     cv.Optional(CONF_CURRENT): sensor.sensor_schema(UNIT_AMPERE, ICON_EMPTY, 2, | ||||
|                                                     DEVICE_CLASS_CURRENT), | ||||
|     cv.Optional(CONF_POWER): sensor.sensor_schema(UNIT_WATT, ICON_EMPTY, 2, DEVICE_CLASS_POWER), | ||||
|     cv.Optional(CONF_REACTIVE_POWER): sensor.sensor_schema(UNIT_VOLT_AMPS_REACTIVE, | ||||
|                                                            ICON_LIGHTBULB, 2, DEVICE_CLASS_EMPTY), | ||||
|     cv.Optional(CONF_POWER_FACTOR): sensor.sensor_schema(UNIT_EMPTY, ICON_EMPTY, 2, | ||||
|                                                          DEVICE_CLASS_POWER_FACTOR), | ||||
|     cv.Optional(CONF_GAIN_VOLTAGE, default=7305): cv.uint16_t, | ||||
|     cv.Optional(CONF_GAIN_CT, default=27961): cv.uint16_t, | ||||
| }) | ||||
| ATM90E32_PHASE_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.Optional(CONF_VOLTAGE): sensor.sensor_schema( | ||||
|             UNIT_VOLT, ICON_EMPTY, 2, DEVICE_CLASS_VOLTAGE | ||||
|         ), | ||||
|         cv.Optional(CONF_CURRENT): sensor.sensor_schema( | ||||
|             UNIT_AMPERE, ICON_EMPTY, 2, DEVICE_CLASS_CURRENT | ||||
|         ), | ||||
|         cv.Optional(CONF_POWER): sensor.sensor_schema( | ||||
|             UNIT_WATT, ICON_EMPTY, 2, DEVICE_CLASS_POWER | ||||
|         ), | ||||
|         cv.Optional(CONF_REACTIVE_POWER): sensor.sensor_schema( | ||||
|             UNIT_VOLT_AMPS_REACTIVE, ICON_LIGHTBULB, 2, DEVICE_CLASS_EMPTY | ||||
|         ), | ||||
|         cv.Optional(CONF_POWER_FACTOR): sensor.sensor_schema( | ||||
|             UNIT_EMPTY, ICON_EMPTY, 2, DEVICE_CLASS_POWER_FACTOR | ||||
|         ), | ||||
|         cv.Optional(CONF_GAIN_VOLTAGE, default=7305): cv.uint16_t, | ||||
|         cv.Optional(CONF_GAIN_CT, default=27961): cv.uint16_t, | ||||
|     } | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(ATM90E32Component), | ||||
|     cv.Optional(CONF_PHASE_A): ATM90E32_PHASE_SCHEMA, | ||||
|     cv.Optional(CONF_PHASE_B): ATM90E32_PHASE_SCHEMA, | ||||
|     cv.Optional(CONF_PHASE_C): ATM90E32_PHASE_SCHEMA, | ||||
|     cv.Optional(CONF_FREQUENCY): sensor.sensor_schema(UNIT_HERTZ, ICON_CURRENT_AC, 1, | ||||
|                                                       DEVICE_CLASS_EMPTY), | ||||
|     cv.Optional(CONF_CHIP_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, | ||||
|                                                              DEVICE_CLASS_TEMPERATURE), | ||||
|     cv.Required(CONF_LINE_FREQUENCY): cv.enum(LINE_FREQS, upper=True), | ||||
|     cv.Optional(CONF_CURRENT_PHASES, default='3'): cv.enum(CURRENT_PHASES, upper=True), | ||||
|     cv.Optional(CONF_GAIN_PGA, default='2X'): cv.enum(PGA_GAINS, upper=True), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(spi.spi_device_schema()) | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(ATM90E32Component), | ||||
|             cv.Optional(CONF_PHASE_A): ATM90E32_PHASE_SCHEMA, | ||||
|             cv.Optional(CONF_PHASE_B): ATM90E32_PHASE_SCHEMA, | ||||
|             cv.Optional(CONF_PHASE_C): ATM90E32_PHASE_SCHEMA, | ||||
|             cv.Optional(CONF_FREQUENCY): sensor.sensor_schema( | ||||
|                 UNIT_HERTZ, ICON_CURRENT_AC, 1, DEVICE_CLASS_EMPTY | ||||
|             ), | ||||
|             cv.Optional(CONF_CHIP_TEMPERATURE): sensor.sensor_schema( | ||||
|                 UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE | ||||
|             ), | ||||
|             cv.Required(CONF_LINE_FREQUENCY): cv.enum(LINE_FREQS, upper=True), | ||||
|             cv.Optional(CONF_CURRENT_PHASES, default="3"): cv.enum( | ||||
|                 CURRENT_PHASES, upper=True | ||||
|             ), | ||||
|             cv.Optional(CONF_GAIN_PGA, default="2X"): cv.enum(PGA_GAINS, upper=True), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
|     .extend(spi.spi_device_schema()) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| CODEOWNERS = ['@OttoWinter'] | ||||
| CODEOWNERS = ["@OttoWinter"] | ||||
|   | ||||
| @@ -2,27 +2,41 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import automation | ||||
| from esphome.components import climate, sensor | ||||
| from esphome.const import CONF_AWAY_CONFIG, CONF_COOL_ACTION, \ | ||||
|     CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION, \ | ||||
|     CONF_ID, CONF_IDLE_ACTION, CONF_SENSOR | ||||
| from esphome.const import ( | ||||
|     CONF_AWAY_CONFIG, | ||||
|     CONF_COOL_ACTION, | ||||
|     CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, | ||||
|     CONF_DEFAULT_TARGET_TEMPERATURE_LOW, | ||||
|     CONF_HEAT_ACTION, | ||||
|     CONF_ID, | ||||
|     CONF_IDLE_ACTION, | ||||
|     CONF_SENSOR, | ||||
| ) | ||||
|  | ||||
| bang_bang_ns = cg.esphome_ns.namespace('bang_bang') | ||||
| BangBangClimate = bang_bang_ns.class_('BangBangClimate', climate.Climate, cg.Component) | ||||
| BangBangClimateTargetTempConfig = bang_bang_ns.struct('BangBangClimateTargetTempConfig') | ||||
| bang_bang_ns = cg.esphome_ns.namespace("bang_bang") | ||||
| BangBangClimate = bang_bang_ns.class_("BangBangClimate", climate.Climate, cg.Component) | ||||
| BangBangClimateTargetTempConfig = bang_bang_ns.struct("BangBangClimateTargetTempConfig") | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All(climate.CLIMATE_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(BangBangClimate), | ||||
|     cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor), | ||||
|     cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, | ||||
|     cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature, | ||||
|     cv.Required(CONF_IDLE_ACTION): automation.validate_automation(single=True), | ||||
|     cv.Optional(CONF_COOL_ACTION): automation.validate_automation(single=True), | ||||
|     cv.Optional(CONF_HEAT_ACTION): automation.validate_automation(single=True), | ||||
|     cv.Optional(CONF_AWAY_CONFIG): cv.Schema({ | ||||
|         cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, | ||||
|         cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature, | ||||
|     }), | ||||
| }).extend(cv.COMPONENT_SCHEMA), cv.has_at_least_one_key(CONF_COOL_ACTION, CONF_HEAT_ACTION)) | ||||
| CONFIG_SCHEMA = cv.All( | ||||
|     climate.CLIMATE_SCHEMA.extend( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(BangBangClimate), | ||||
|             cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor), | ||||
|             cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, | ||||
|             cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature, | ||||
|             cv.Required(CONF_IDLE_ACTION): automation.validate_automation(single=True), | ||||
|             cv.Optional(CONF_COOL_ACTION): automation.validate_automation(single=True), | ||||
|             cv.Optional(CONF_HEAT_ACTION): automation.validate_automation(single=True), | ||||
|             cv.Optional(CONF_AWAY_CONFIG): cv.Schema( | ||||
|                 { | ||||
|                     cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, | ||||
|                     cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature, | ||||
|                 } | ||||
|             ), | ||||
|         } | ||||
|     ).extend(cv.COMPONENT_SCHEMA), | ||||
|     cv.has_at_least_one_key(CONF_COOL_ACTION, CONF_HEAT_ACTION), | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
| @@ -35,23 +49,29 @@ def to_code(config): | ||||
|  | ||||
|     normal_config = BangBangClimateTargetTempConfig( | ||||
|         config[CONF_DEFAULT_TARGET_TEMPERATURE_LOW], | ||||
|         config[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH] | ||||
|         config[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH], | ||||
|     ) | ||||
|     cg.add(var.set_normal_config(normal_config)) | ||||
|  | ||||
|     yield automation.build_automation(var.get_idle_trigger(), [], config[CONF_IDLE_ACTION]) | ||||
|     yield automation.build_automation( | ||||
|         var.get_idle_trigger(), [], config[CONF_IDLE_ACTION] | ||||
|     ) | ||||
|  | ||||
|     if CONF_COOL_ACTION in config: | ||||
|         yield automation.build_automation(var.get_cool_trigger(), [], config[CONF_COOL_ACTION]) | ||||
|         yield automation.build_automation( | ||||
|             var.get_cool_trigger(), [], config[CONF_COOL_ACTION] | ||||
|         ) | ||||
|         cg.add(var.set_supports_cool(True)) | ||||
|     if CONF_HEAT_ACTION in config: | ||||
|         yield automation.build_automation(var.get_heat_trigger(), [], config[CONF_HEAT_ACTION]) | ||||
|         yield automation.build_automation( | ||||
|             var.get_heat_trigger(), [], config[CONF_HEAT_ACTION] | ||||
|         ) | ||||
|         cg.add(var.set_supports_heat(True)) | ||||
|  | ||||
|     if CONF_AWAY_CONFIG in config: | ||||
|         away = config[CONF_AWAY_CONFIG] | ||||
|         away_config = BangBangClimateTargetTempConfig( | ||||
|             away[CONF_DEFAULT_TARGET_TEMPERATURE_LOW], | ||||
|             away[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH] | ||||
|             away[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH], | ||||
|         ) | ||||
|         cg.add(var.set_away_config(away_config)) | ||||
|   | ||||
| @@ -1,26 +1,45 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.const import CONF_ID, CONF_RESOLUTION, DEVICE_CLASS_ILLUMINANCE, ICON_EMPTY, UNIT_LUX | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     CONF_RESOLUTION, | ||||
|     DEVICE_CLASS_ILLUMINANCE, | ||||
|     ICON_EMPTY, | ||||
|     UNIT_LUX, | ||||
| ) | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| DEPENDENCIES = ["i2c"] | ||||
|  | ||||
| bh1750_ns = cg.esphome_ns.namespace('bh1750') | ||||
| BH1750Resolution = bh1750_ns.enum('BH1750Resolution') | ||||
| bh1750_ns = cg.esphome_ns.namespace("bh1750") | ||||
| BH1750Resolution = bh1750_ns.enum("BH1750Resolution") | ||||
| BH1750_RESOLUTIONS = { | ||||
|     4.0: BH1750Resolution.BH1750_RESOLUTION_4P0_LX, | ||||
|     1.0: BH1750Resolution.BH1750_RESOLUTION_1P0_LX, | ||||
|     0.5: BH1750Resolution.BH1750_RESOLUTION_0P5_LX, | ||||
| } | ||||
|  | ||||
| BH1750Sensor = bh1750_ns.class_('BH1750Sensor', sensor.Sensor, cg.PollingComponent, i2c.I2CDevice) | ||||
| BH1750Sensor = bh1750_ns.class_( | ||||
|     "BH1750Sensor", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice | ||||
| ) | ||||
|  | ||||
| CONF_MEASUREMENT_TIME = 'measurement_time' | ||||
| CONFIG_SCHEMA = sensor.sensor_schema(UNIT_LUX, ICON_EMPTY, 1, DEVICE_CLASS_ILLUMINANCE).extend({ | ||||
|     cv.GenerateID(): cv.declare_id(BH1750Sensor), | ||||
|     cv.Optional(CONF_RESOLUTION, default=0.5): cv.enum(BH1750_RESOLUTIONS, float=True), | ||||
|     cv.Optional(CONF_MEASUREMENT_TIME, default=69): cv.int_range(min=31, max=254), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x23)) | ||||
| CONF_MEASUREMENT_TIME = "measurement_time" | ||||
| CONFIG_SCHEMA = ( | ||||
|     sensor.sensor_schema(UNIT_LUX, ICON_EMPTY, 1, DEVICE_CLASS_ILLUMINANCE) | ||||
|     .extend( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(BH1750Sensor), | ||||
|             cv.Optional(CONF_RESOLUTION, default=0.5): cv.enum( | ||||
|                 BH1750_RESOLUTIONS, float=True | ||||
|             ), | ||||
|             cv.Optional(CONF_MEASUREMENT_TIME, default=69): cv.int_range( | ||||
|                 min=31, max=254 | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
|     .extend(i2c.i2c_device_schema(0x23)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,3 +1,3 @@ | ||||
| import esphome.codegen as cg | ||||
|  | ||||
| binary_ns = cg.esphome_ns.namespace('binary') | ||||
| binary_ns = cg.esphome_ns.namespace("binary") | ||||
|   | ||||
| @@ -1,18 +1,24 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import fan, output | ||||
| from esphome.const import CONF_DIRECTION_OUTPUT, CONF_OSCILLATION_OUTPUT, \ | ||||
|     CONF_OUTPUT, CONF_OUTPUT_ID | ||||
| from esphome.const import ( | ||||
|     CONF_DIRECTION_OUTPUT, | ||||
|     CONF_OSCILLATION_OUTPUT, | ||||
|     CONF_OUTPUT, | ||||
|     CONF_OUTPUT_ID, | ||||
| ) | ||||
| from .. import binary_ns | ||||
|  | ||||
| BinaryFan = binary_ns.class_('BinaryFan', cg.Component) | ||||
| BinaryFan = binary_ns.class_("BinaryFan", cg.Component) | ||||
|  | ||||
| CONFIG_SCHEMA = fan.FAN_SCHEMA.extend({ | ||||
|     cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(BinaryFan), | ||||
|     cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput), | ||||
|     cv.Optional(CONF_DIRECTION_OUTPUT): cv.use_id(output.BinaryOutput), | ||||
|     cv.Optional(CONF_OSCILLATION_OUTPUT): cv.use_id(output.BinaryOutput), | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| CONFIG_SCHEMA = fan.FAN_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(BinaryFan), | ||||
|         cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput), | ||||
|         cv.Optional(CONF_DIRECTION_OUTPUT): cv.use_id(output.BinaryOutput), | ||||
|         cv.Optional(CONF_OSCILLATION_OUTPUT): cv.use_id(output.BinaryOutput), | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -4,12 +4,14 @@ from esphome.components import light, output | ||||
| from esphome.const import CONF_OUTPUT_ID, CONF_OUTPUT | ||||
| from .. import binary_ns | ||||
|  | ||||
| BinaryLightOutput = binary_ns.class_('BinaryLightOutput', light.LightOutput) | ||||
| BinaryLightOutput = binary_ns.class_("BinaryLightOutput", light.LightOutput) | ||||
|  | ||||
| CONFIG_SCHEMA = light.BINARY_LIGHT_SCHEMA.extend({ | ||||
|     cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(BinaryLightOutput), | ||||
|     cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput), | ||||
| }) | ||||
| CONFIG_SCHEMA = light.BINARY_LIGHT_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(BinaryLightOutput), | ||||
|         cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -3,141 +3,214 @@ import esphome.config_validation as cv | ||||
| from esphome import automation, core | ||||
| from esphome.automation import Condition, maybe_simple_id | ||||
| from esphome.components import mqtt | ||||
| from esphome.const import CONF_DEVICE_CLASS, CONF_FILTERS, \ | ||||
|     CONF_ID, CONF_INTERNAL, CONF_INVALID_COOLDOWN, CONF_INVERTED, \ | ||||
|     CONF_MAX_LENGTH, CONF_MIN_LENGTH, CONF_ON_CLICK, \ | ||||
|     CONF_ON_DOUBLE_CLICK, CONF_ON_MULTI_CLICK, CONF_ON_PRESS, CONF_ON_RELEASE, CONF_ON_STATE, \ | ||||
|     CONF_STATE, CONF_TIMING, CONF_TRIGGER_ID, CONF_FOR, CONF_NAME, CONF_MQTT_ID, \ | ||||
|     DEVICE_CLASS_EMPTY, DEVICE_CLASS_BATTERY, DEVICE_CLASS_BATTERY_CHARGING, DEVICE_CLASS_COLD, \ | ||||
|     DEVICE_CLASS_CONNECTIVITY, DEVICE_CLASS_DOOR, DEVICE_CLASS_GARAGE_DOOR, DEVICE_CLASS_GAS, \ | ||||
|     DEVICE_CLASS_HEAT, DEVICE_CLASS_LIGHT, DEVICE_CLASS_LOCK, DEVICE_CLASS_MOISTURE, \ | ||||
|     DEVICE_CLASS_MOTION, DEVICE_CLASS_MOVING, DEVICE_CLASS_OCCUPANCY, DEVICE_CLASS_OPENING, \ | ||||
|     DEVICE_CLASS_PLUG, DEVICE_CLASS_POWER, DEVICE_CLASS_PRESENCE, DEVICE_CLASS_PROBLEM, \ | ||||
|     DEVICE_CLASS_SAFETY, DEVICE_CLASS_SMOKE, DEVICE_CLASS_SOUND, DEVICE_CLASS_VIBRATION, \ | ||||
|     DEVICE_CLASS_WINDOW | ||||
| from esphome.const import ( | ||||
|     CONF_DEVICE_CLASS, | ||||
|     CONF_FILTERS, | ||||
|     CONF_ID, | ||||
|     CONF_INTERNAL, | ||||
|     CONF_INVALID_COOLDOWN, | ||||
|     CONF_INVERTED, | ||||
|     CONF_MAX_LENGTH, | ||||
|     CONF_MIN_LENGTH, | ||||
|     CONF_ON_CLICK, | ||||
|     CONF_ON_DOUBLE_CLICK, | ||||
|     CONF_ON_MULTI_CLICK, | ||||
|     CONF_ON_PRESS, | ||||
|     CONF_ON_RELEASE, | ||||
|     CONF_ON_STATE, | ||||
|     CONF_STATE, | ||||
|     CONF_TIMING, | ||||
|     CONF_TRIGGER_ID, | ||||
|     CONF_FOR, | ||||
|     CONF_NAME, | ||||
|     CONF_MQTT_ID, | ||||
|     DEVICE_CLASS_EMPTY, | ||||
|     DEVICE_CLASS_BATTERY, | ||||
|     DEVICE_CLASS_BATTERY_CHARGING, | ||||
|     DEVICE_CLASS_COLD, | ||||
|     DEVICE_CLASS_CONNECTIVITY, | ||||
|     DEVICE_CLASS_DOOR, | ||||
|     DEVICE_CLASS_GARAGE_DOOR, | ||||
|     DEVICE_CLASS_GAS, | ||||
|     DEVICE_CLASS_HEAT, | ||||
|     DEVICE_CLASS_LIGHT, | ||||
|     DEVICE_CLASS_LOCK, | ||||
|     DEVICE_CLASS_MOISTURE, | ||||
|     DEVICE_CLASS_MOTION, | ||||
|     DEVICE_CLASS_MOVING, | ||||
|     DEVICE_CLASS_OCCUPANCY, | ||||
|     DEVICE_CLASS_OPENING, | ||||
|     DEVICE_CLASS_PLUG, | ||||
|     DEVICE_CLASS_POWER, | ||||
|     DEVICE_CLASS_PRESENCE, | ||||
|     DEVICE_CLASS_PROBLEM, | ||||
|     DEVICE_CLASS_SAFETY, | ||||
|     DEVICE_CLASS_SMOKE, | ||||
|     DEVICE_CLASS_SOUND, | ||||
|     DEVICE_CLASS_VIBRATION, | ||||
|     DEVICE_CLASS_WINDOW, | ||||
| ) | ||||
| from esphome.core import CORE, coroutine, coroutine_with_priority | ||||
| from esphome.util import Registry | ||||
|  | ||||
| CODEOWNERS = ['@esphome/core'] | ||||
| CODEOWNERS = ["@esphome/core"] | ||||
| DEVICE_CLASSES = [ | ||||
|    DEVICE_CLASS_EMPTY, DEVICE_CLASS_BATTERY, DEVICE_CLASS_BATTERY_CHARGING, DEVICE_CLASS_COLD, | ||||
|    DEVICE_CLASS_CONNECTIVITY, DEVICE_CLASS_DOOR, DEVICE_CLASS_GARAGE_DOOR, DEVICE_CLASS_GAS, | ||||
|    DEVICE_CLASS_HEAT, DEVICE_CLASS_LIGHT, DEVICE_CLASS_LOCK, DEVICE_CLASS_MOISTURE, | ||||
|    DEVICE_CLASS_MOTION, DEVICE_CLASS_MOVING, DEVICE_CLASS_OCCUPANCY, DEVICE_CLASS_OPENING, | ||||
|    DEVICE_CLASS_PLUG, DEVICE_CLASS_POWER, DEVICE_CLASS_PRESENCE, DEVICE_CLASS_PROBLEM, | ||||
|    DEVICE_CLASS_SAFETY, DEVICE_CLASS_SMOKE, DEVICE_CLASS_SOUND, DEVICE_CLASS_VIBRATION, | ||||
|    DEVICE_CLASS_WINDOW | ||||
|     DEVICE_CLASS_EMPTY, | ||||
|     DEVICE_CLASS_BATTERY, | ||||
|     DEVICE_CLASS_BATTERY_CHARGING, | ||||
|     DEVICE_CLASS_COLD, | ||||
|     DEVICE_CLASS_CONNECTIVITY, | ||||
|     DEVICE_CLASS_DOOR, | ||||
|     DEVICE_CLASS_GARAGE_DOOR, | ||||
|     DEVICE_CLASS_GAS, | ||||
|     DEVICE_CLASS_HEAT, | ||||
|     DEVICE_CLASS_LIGHT, | ||||
|     DEVICE_CLASS_LOCK, | ||||
|     DEVICE_CLASS_MOISTURE, | ||||
|     DEVICE_CLASS_MOTION, | ||||
|     DEVICE_CLASS_MOVING, | ||||
|     DEVICE_CLASS_OCCUPANCY, | ||||
|     DEVICE_CLASS_OPENING, | ||||
|     DEVICE_CLASS_PLUG, | ||||
|     DEVICE_CLASS_POWER, | ||||
|     DEVICE_CLASS_PRESENCE, | ||||
|     DEVICE_CLASS_PROBLEM, | ||||
|     DEVICE_CLASS_SAFETY, | ||||
|     DEVICE_CLASS_SMOKE, | ||||
|     DEVICE_CLASS_SOUND, | ||||
|     DEVICE_CLASS_VIBRATION, | ||||
|     DEVICE_CLASS_WINDOW, | ||||
| ] | ||||
|  | ||||
| IS_PLATFORM_COMPONENT = True | ||||
|  | ||||
| binary_sensor_ns = cg.esphome_ns.namespace('binary_sensor') | ||||
| BinarySensor = binary_sensor_ns.class_('BinarySensor', cg.Nameable) | ||||
| BinarySensorInitiallyOff = binary_sensor_ns.class_('BinarySensorInitiallyOff', BinarySensor) | ||||
| BinarySensorPtr = BinarySensor.operator('ptr') | ||||
| binary_sensor_ns = cg.esphome_ns.namespace("binary_sensor") | ||||
| BinarySensor = binary_sensor_ns.class_("BinarySensor", cg.Nameable) | ||||
| BinarySensorInitiallyOff = binary_sensor_ns.class_( | ||||
|     "BinarySensorInitiallyOff", BinarySensor | ||||
| ) | ||||
| BinarySensorPtr = BinarySensor.operator("ptr") | ||||
|  | ||||
| # Triggers | ||||
| PressTrigger = binary_sensor_ns.class_('PressTrigger', automation.Trigger.template()) | ||||
| ReleaseTrigger = binary_sensor_ns.class_('ReleaseTrigger', automation.Trigger.template()) | ||||
| ClickTrigger = binary_sensor_ns.class_('ClickTrigger', automation.Trigger.template()) | ||||
| DoubleClickTrigger = binary_sensor_ns.class_('DoubleClickTrigger', automation.Trigger.template()) | ||||
| MultiClickTrigger = binary_sensor_ns.class_('MultiClickTrigger', automation.Trigger.template(), | ||||
|                                             cg.Component) | ||||
| MultiClickTriggerEvent = binary_sensor_ns.struct('MultiClickTriggerEvent') | ||||
| StateTrigger = binary_sensor_ns.class_('StateTrigger', automation.Trigger.template(bool)) | ||||
| BinarySensorPublishAction = binary_sensor_ns.class_('BinarySensorPublishAction', automation.Action) | ||||
| PressTrigger = binary_sensor_ns.class_("PressTrigger", automation.Trigger.template()) | ||||
| ReleaseTrigger = binary_sensor_ns.class_( | ||||
|     "ReleaseTrigger", automation.Trigger.template() | ||||
| ) | ||||
| ClickTrigger = binary_sensor_ns.class_("ClickTrigger", automation.Trigger.template()) | ||||
| DoubleClickTrigger = binary_sensor_ns.class_( | ||||
|     "DoubleClickTrigger", automation.Trigger.template() | ||||
| ) | ||||
| MultiClickTrigger = binary_sensor_ns.class_( | ||||
|     "MultiClickTrigger", automation.Trigger.template(), cg.Component | ||||
| ) | ||||
| MultiClickTriggerEvent = binary_sensor_ns.struct("MultiClickTriggerEvent") | ||||
| StateTrigger = binary_sensor_ns.class_( | ||||
|     "StateTrigger", automation.Trigger.template(bool) | ||||
| ) | ||||
| BinarySensorPublishAction = binary_sensor_ns.class_( | ||||
|     "BinarySensorPublishAction", automation.Action | ||||
| ) | ||||
|  | ||||
| # Condition | ||||
| BinarySensorCondition = binary_sensor_ns.class_('BinarySensorCondition', Condition) | ||||
| BinarySensorCondition = binary_sensor_ns.class_("BinarySensorCondition", Condition) | ||||
|  | ||||
| # Filters | ||||
| Filter = binary_sensor_ns.class_('Filter') | ||||
| DelayedOnOffFilter = binary_sensor_ns.class_('DelayedOnOffFilter', Filter, cg.Component) | ||||
| DelayedOnFilter = binary_sensor_ns.class_('DelayedOnFilter', Filter, cg.Component) | ||||
| DelayedOffFilter = binary_sensor_ns.class_('DelayedOffFilter', Filter, cg.Component) | ||||
| InvertFilter = binary_sensor_ns.class_('InvertFilter', Filter) | ||||
| LambdaFilter = binary_sensor_ns.class_('LambdaFilter', Filter) | ||||
| Filter = binary_sensor_ns.class_("Filter") | ||||
| DelayedOnOffFilter = binary_sensor_ns.class_("DelayedOnOffFilter", Filter, cg.Component) | ||||
| DelayedOnFilter = binary_sensor_ns.class_("DelayedOnFilter", Filter, cg.Component) | ||||
| DelayedOffFilter = binary_sensor_ns.class_("DelayedOffFilter", Filter, cg.Component) | ||||
| InvertFilter = binary_sensor_ns.class_("InvertFilter", Filter) | ||||
| LambdaFilter = binary_sensor_ns.class_("LambdaFilter", Filter) | ||||
|  | ||||
| FILTER_REGISTRY = Registry() | ||||
| validate_filters = cv.validate_registry('filter', FILTER_REGISTRY) | ||||
| validate_filters = cv.validate_registry("filter", FILTER_REGISTRY) | ||||
|  | ||||
|  | ||||
| @FILTER_REGISTRY.register('invert', InvertFilter, {}) | ||||
| @FILTER_REGISTRY.register("invert", InvertFilter, {}) | ||||
| def invert_filter_to_code(config, filter_id): | ||||
|     yield cg.new_Pvariable(filter_id) | ||||
|  | ||||
|  | ||||
| @FILTER_REGISTRY.register('delayed_on_off', DelayedOnOffFilter, | ||||
|                           cv.positive_time_period_milliseconds) | ||||
| @FILTER_REGISTRY.register( | ||||
|     "delayed_on_off", DelayedOnOffFilter, cv.positive_time_period_milliseconds | ||||
| ) | ||||
| def delayed_on_off_filter_to_code(config, filter_id): | ||||
|     var = cg.new_Pvariable(filter_id, config) | ||||
|     yield cg.register_component(var, {}) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @FILTER_REGISTRY.register('delayed_on', DelayedOnFilter, | ||||
|                           cv.positive_time_period_milliseconds) | ||||
| @FILTER_REGISTRY.register( | ||||
|     "delayed_on", DelayedOnFilter, cv.positive_time_period_milliseconds | ||||
| ) | ||||
| def delayed_on_filter_to_code(config, filter_id): | ||||
|     var = cg.new_Pvariable(filter_id, config) | ||||
|     yield cg.register_component(var, {}) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @FILTER_REGISTRY.register('delayed_off', DelayedOffFilter, cv.positive_time_period_milliseconds) | ||||
| @FILTER_REGISTRY.register( | ||||
|     "delayed_off", DelayedOffFilter, cv.positive_time_period_milliseconds | ||||
| ) | ||||
| def delayed_off_filter_to_code(config, filter_id): | ||||
|     var = cg.new_Pvariable(filter_id, config) | ||||
|     yield cg.register_component(var, {}) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @FILTER_REGISTRY.register('lambda', LambdaFilter, cv.returning_lambda) | ||||
| @FILTER_REGISTRY.register("lambda", LambdaFilter, cv.returning_lambda) | ||||
| def lambda_filter_to_code(config, filter_id): | ||||
|     lambda_ = yield cg.process_lambda(config, [(bool, 'x')], return_type=cg.optional.template(bool)) | ||||
|     lambda_ = yield cg.process_lambda( | ||||
|         config, [(bool, "x")], return_type=cg.optional.template(bool) | ||||
|     ) | ||||
|     yield cg.new_Pvariable(filter_id, lambda_) | ||||
|  | ||||
|  | ||||
| MULTI_CLICK_TIMING_SCHEMA = cv.Schema({ | ||||
|     cv.Optional(CONF_STATE): cv.boolean, | ||||
|     cv.Optional(CONF_MIN_LENGTH): cv.positive_time_period_milliseconds, | ||||
|     cv.Optional(CONF_MAX_LENGTH): cv.positive_time_period_milliseconds, | ||||
| }) | ||||
| MULTI_CLICK_TIMING_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.Optional(CONF_STATE): cv.boolean, | ||||
|         cv.Optional(CONF_MIN_LENGTH): cv.positive_time_period_milliseconds, | ||||
|         cv.Optional(CONF_MAX_LENGTH): cv.positive_time_period_milliseconds, | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def parse_multi_click_timing_str(value): | ||||
|     if not isinstance(value, str): | ||||
|         return value | ||||
|  | ||||
|     parts = value.lower().split(' ') | ||||
|     parts = value.lower().split(" ") | ||||
|     if len(parts) != 5: | ||||
|         raise cv.Invalid("Multi click timing grammar consists of exactly 5 words, not {}" | ||||
|                          "".format(len(parts))) | ||||
|         raise cv.Invalid( | ||||
|             "Multi click timing grammar consists of exactly 5 words, not {}" | ||||
|             "".format(len(parts)) | ||||
|         ) | ||||
|     try: | ||||
|         state = cv.boolean(parts[0]) | ||||
|     except cv.Invalid: | ||||
|         # pylint: disable=raise-missing-from | ||||
|         raise cv.Invalid("First word must either be ON or OFF, not {}".format(parts[0])) | ||||
|  | ||||
|     if parts[1] != 'for': | ||||
|     if parts[1] != "for": | ||||
|         raise cv.Invalid("Second word must be 'for', got {}".format(parts[1])) | ||||
|  | ||||
|     if parts[2] == 'at': | ||||
|         if parts[3] == 'least': | ||||
|     if parts[2] == "at": | ||||
|         if parts[3] == "least": | ||||
|             key = CONF_MIN_LENGTH | ||||
|         elif parts[3] == 'most': | ||||
|         elif parts[3] == "most": | ||||
|             key = CONF_MAX_LENGTH | ||||
|         else: | ||||
|             raise cv.Invalid("Third word after at must either be 'least' or 'most', got {}" | ||||
|                              "".format(parts[3])) | ||||
|             raise cv.Invalid( | ||||
|                 "Third word after at must either be 'least' or 'most', got {}" | ||||
|                 "".format(parts[3]) | ||||
|             ) | ||||
|         try: | ||||
|             length = cv.positive_time_period_milliseconds(parts[4]) | ||||
|         except cv.Invalid as err: | ||||
|             raise cv.Invalid(f"Multi Click Grammar Parsing length failed: {err}") | ||||
|         return { | ||||
|             CONF_STATE: state, | ||||
|             key: str(length) | ||||
|         } | ||||
|         return {CONF_STATE: state, key: str(length)} | ||||
|  | ||||
|     if parts[3] != 'to': | ||||
|     if parts[3] != "to": | ||||
|         raise cv.Invalid("Multi click grammar: 4th word must be 'to'") | ||||
|  | ||||
|     try: | ||||
| @@ -153,7 +226,7 @@ def parse_multi_click_timing_str(value): | ||||
|     return { | ||||
|         CONF_STATE: state, | ||||
|         CONF_MIN_LENGTH: str(min_length), | ||||
|         CONF_MAX_LENGTH: str(max_length) | ||||
|         CONF_MAX_LENGTH: str(max_length), | ||||
|     } | ||||
|  | ||||
|  | ||||
| @@ -173,11 +246,15 @@ def validate_multi_click_timing(value): | ||||
|  | ||||
|         new_state = v_.get(CONF_STATE, not state) | ||||
|         if new_state == state: | ||||
|             raise cv.Invalid("Timings must have alternating state. Indices {} and {} have " | ||||
|                              "the same state {}".format(i, i + 1, state)) | ||||
|             raise cv.Invalid( | ||||
|                 "Timings must have alternating state. Indices {} and {} have " | ||||
|                 "the same state {}".format(i, i + 1, state) | ||||
|             ) | ||||
|         if max_length is not None and max_length < min_length: | ||||
|             raise cv.Invalid("Max length ({}) must be larger than min length ({})." | ||||
|                              "".format(max_length, min_length)) | ||||
|             raise cv.Invalid( | ||||
|                 "Max length ({}) must be larger than min length ({})." | ||||
|                 "".format(max_length, min_length) | ||||
|             ) | ||||
|  | ||||
|         state = new_state | ||||
|         tim = { | ||||
| @@ -190,46 +267,71 @@ def validate_multi_click_timing(value): | ||||
|     return timings | ||||
|  | ||||
|  | ||||
| device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space='_') | ||||
| device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_") | ||||
|  | ||||
| BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(BinarySensor), | ||||
|     cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTBinarySensorComponent), | ||||
|  | ||||
|     cv.Optional(CONF_DEVICE_CLASS): device_class, | ||||
|     cv.Optional(CONF_FILTERS): validate_filters, | ||||
|     cv.Optional(CONF_ON_PRESS): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PressTrigger), | ||||
|     }), | ||||
|     cv.Optional(CONF_ON_RELEASE): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ReleaseTrigger), | ||||
|     }), | ||||
|     cv.Optional(CONF_ON_CLICK): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ClickTrigger), | ||||
|         cv.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds, | ||||
|         cv.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds, | ||||
|     }), | ||||
|     cv.Optional(CONF_ON_DOUBLE_CLICK): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DoubleClickTrigger), | ||||
|         cv.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds, | ||||
|         cv.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds, | ||||
|     }), | ||||
|     cv.Optional(CONF_ON_MULTI_CLICK): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(MultiClickTrigger), | ||||
|         cv.Required(CONF_TIMING): cv.All([parse_multi_click_timing_str], | ||||
|                                          validate_multi_click_timing), | ||||
|         cv.Optional(CONF_INVALID_COOLDOWN, default='1s'): cv.positive_time_period_milliseconds, | ||||
|     }), | ||||
|     cv.Optional(CONF_ON_STATE): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger), | ||||
|     }), | ||||
|  | ||||
|     cv.Optional(CONF_INVERTED): cv.invalid( | ||||
|         "The inverted binary_sensor property has been replaced by the " | ||||
|         "new 'invert' binary  sensor filter. Please see " | ||||
|         "https://esphome.io/components/binary_sensor/index.html." | ||||
|     ), | ||||
| }) | ||||
| BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(BinarySensor), | ||||
|         cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id( | ||||
|             mqtt.MQTTBinarySensorComponent | ||||
|         ), | ||||
|         cv.Optional(CONF_DEVICE_CLASS): device_class, | ||||
|         cv.Optional(CONF_FILTERS): validate_filters, | ||||
|         cv.Optional(CONF_ON_PRESS): automation.validate_automation( | ||||
|             { | ||||
|                 cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PressTrigger), | ||||
|             } | ||||
|         ), | ||||
|         cv.Optional(CONF_ON_RELEASE): automation.validate_automation( | ||||
|             { | ||||
|                 cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ReleaseTrigger), | ||||
|             } | ||||
|         ), | ||||
|         cv.Optional(CONF_ON_CLICK): automation.validate_automation( | ||||
|             { | ||||
|                 cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ClickTrigger), | ||||
|                 cv.Optional( | ||||
|                     CONF_MIN_LENGTH, default="50ms" | ||||
|                 ): cv.positive_time_period_milliseconds, | ||||
|                 cv.Optional( | ||||
|                     CONF_MAX_LENGTH, default="350ms" | ||||
|                 ): cv.positive_time_period_milliseconds, | ||||
|             } | ||||
|         ), | ||||
|         cv.Optional(CONF_ON_DOUBLE_CLICK): automation.validate_automation( | ||||
|             { | ||||
|                 cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DoubleClickTrigger), | ||||
|                 cv.Optional( | ||||
|                     CONF_MIN_LENGTH, default="50ms" | ||||
|                 ): cv.positive_time_period_milliseconds, | ||||
|                 cv.Optional( | ||||
|                     CONF_MAX_LENGTH, default="350ms" | ||||
|                 ): cv.positive_time_period_milliseconds, | ||||
|             } | ||||
|         ), | ||||
|         cv.Optional(CONF_ON_MULTI_CLICK): automation.validate_automation( | ||||
|             { | ||||
|                 cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(MultiClickTrigger), | ||||
|                 cv.Required(CONF_TIMING): cv.All( | ||||
|                     [parse_multi_click_timing_str], validate_multi_click_timing | ||||
|                 ), | ||||
|                 cv.Optional( | ||||
|                     CONF_INVALID_COOLDOWN, default="1s" | ||||
|                 ): cv.positive_time_period_milliseconds, | ||||
|             } | ||||
|         ), | ||||
|         cv.Optional(CONF_ON_STATE): automation.validate_automation( | ||||
|             { | ||||
|                 cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger), | ||||
|             } | ||||
|         ), | ||||
|         cv.Optional(CONF_INVERTED): cv.invalid( | ||||
|             "The inverted binary_sensor property has been replaced by the " | ||||
|             "new 'invert' binary  sensor filter. Please see " | ||||
|             "https://esphome.io/components/binary_sensor/index.html." | ||||
|         ), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| @@ -254,24 +356,28 @@ def setup_binary_sensor_core_(var, config): | ||||
|         yield automation.build_automation(trigger, [], conf) | ||||
|  | ||||
|     for conf in config.get(CONF_ON_CLICK, []): | ||||
|         trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var, | ||||
|                                    conf[CONF_MIN_LENGTH], conf[CONF_MAX_LENGTH]) | ||||
|         trigger = cg.new_Pvariable( | ||||
|             conf[CONF_TRIGGER_ID], var, conf[CONF_MIN_LENGTH], conf[CONF_MAX_LENGTH] | ||||
|         ) | ||||
|         yield automation.build_automation(trigger, [], conf) | ||||
|  | ||||
|     for conf in config.get(CONF_ON_DOUBLE_CLICK, []): | ||||
|         trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var, | ||||
|                                    conf[CONF_MIN_LENGTH], conf[CONF_MAX_LENGTH]) | ||||
|         trigger = cg.new_Pvariable( | ||||
|             conf[CONF_TRIGGER_ID], var, conf[CONF_MIN_LENGTH], conf[CONF_MAX_LENGTH] | ||||
|         ) | ||||
|         yield automation.build_automation(trigger, [], conf) | ||||
|  | ||||
|     for conf in config.get(CONF_ON_MULTI_CLICK, []): | ||||
|         timings = [] | ||||
|         for tim in conf[CONF_TIMING]: | ||||
|             timings.append(cg.StructInitializer( | ||||
|                 MultiClickTriggerEvent, | ||||
|                 ('state', tim[CONF_STATE]), | ||||
|                 ('min_length', tim[CONF_MIN_LENGTH]), | ||||
|                 ('max_length', tim.get(CONF_MAX_LENGTH, 4294967294)), | ||||
|             )) | ||||
|             timings.append( | ||||
|                 cg.StructInitializer( | ||||
|                     MultiClickTriggerEvent, | ||||
|                     ("state", tim[CONF_STATE]), | ||||
|                     ("min_length", tim[CONF_MIN_LENGTH]), | ||||
|                     ("max_length", tim.get(CONF_MAX_LENGTH, 4294967294)), | ||||
|                 ) | ||||
|             ) | ||||
|         trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var, timings) | ||||
|         if CONF_INVALID_COOLDOWN in conf: | ||||
|             cg.add(trigger.set_invalid_cooldown(conf[CONF_INVALID_COOLDOWN])) | ||||
| @@ -280,7 +386,7 @@ def setup_binary_sensor_core_(var, config): | ||||
|  | ||||
|     for conf in config.get(CONF_ON_STATE, []): | ||||
|         trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) | ||||
|         yield automation.build_automation(trigger, [(bool, 'x')], conf) | ||||
|         yield automation.build_automation(trigger, [(bool, "x")], conf) | ||||
|  | ||||
|     if CONF_MQTT_ID in config: | ||||
|         mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var) | ||||
| @@ -302,22 +408,28 @@ def new_binary_sensor(config): | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| BINARY_SENSOR_CONDITION_SCHEMA = maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.use_id(BinarySensor), | ||||
|     cv.Optional(CONF_FOR): cv.invalid("This option has been removed in 1.13, please use the " | ||||
|                                       "'for' condition instead."), | ||||
| }) | ||||
| BINARY_SENSOR_CONDITION_SCHEMA = maybe_simple_id( | ||||
|     { | ||||
|         cv.Required(CONF_ID): cv.use_id(BinarySensor), | ||||
|         cv.Optional(CONF_FOR): cv.invalid( | ||||
|             "This option has been removed in 1.13, please use the " | ||||
|             "'for' condition instead." | ||||
|         ), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @automation.register_condition('binary_sensor.is_on', BinarySensorCondition, | ||||
|                                BINARY_SENSOR_CONDITION_SCHEMA) | ||||
| @automation.register_condition( | ||||
|     "binary_sensor.is_on", BinarySensorCondition, BINARY_SENSOR_CONDITION_SCHEMA | ||||
| ) | ||||
| def binary_sensor_is_on_to_code(config, condition_id, template_arg, args): | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(condition_id, template_arg, paren, True) | ||||
|  | ||||
|  | ||||
| @automation.register_condition('binary_sensor.is_off', BinarySensorCondition, | ||||
|                                BINARY_SENSOR_CONDITION_SCHEMA) | ||||
| @automation.register_condition( | ||||
|     "binary_sensor.is_off", BinarySensorCondition, BINARY_SENSOR_CONDITION_SCHEMA | ||||
| ) | ||||
| def binary_sensor_is_off_to_code(config, condition_id, template_arg, args): | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(condition_id, template_arg, paren, False) | ||||
| @@ -325,5 +437,5 @@ def binary_sensor_is_off_to_code(config, condition_id, template_arg, args): | ||||
|  | ||||
| @coroutine_with_priority(100.0) | ||||
| def to_code(config): | ||||
|     cg.add_define('USE_BINARY_SENSOR') | ||||
|     cg.add_define("USE_BINARY_SENSOR") | ||||
|     cg.add_global(binary_sensor_ns.using) | ||||
|   | ||||
| @@ -2,14 +2,25 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
|  | ||||
| from esphome.components import sensor, binary_sensor | ||||
| from esphome.const import CONF_ID, CONF_CHANNELS, CONF_VALUE, CONF_TYPE, DEVICE_CLASS_EMPTY, \ | ||||
|     UNIT_EMPTY, ICON_CHECK_CIRCLE_OUTLINE, CONF_BINARY_SENSOR, CONF_GROUP | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     CONF_CHANNELS, | ||||
|     CONF_VALUE, | ||||
|     CONF_TYPE, | ||||
|     DEVICE_CLASS_EMPTY, | ||||
|     UNIT_EMPTY, | ||||
|     ICON_CHECK_CIRCLE_OUTLINE, | ||||
|     CONF_BINARY_SENSOR, | ||||
|     CONF_GROUP, | ||||
| ) | ||||
|  | ||||
| DEPENDENCIES = ['binary_sensor'] | ||||
| DEPENDENCIES = ["binary_sensor"] | ||||
|  | ||||
| binary_sensor_map_ns = cg.esphome_ns.namespace('binary_sensor_map') | ||||
| BinarySensorMap = binary_sensor_map_ns.class_('BinarySensorMap', cg.Component, sensor.Sensor) | ||||
| SensorMapType = binary_sensor_map_ns.enum('SensorMapType') | ||||
| binary_sensor_map_ns = cg.esphome_ns.namespace("binary_sensor_map") | ||||
| BinarySensorMap = binary_sensor_map_ns.class_( | ||||
|     "BinarySensorMap", cg.Component, sensor.Sensor | ||||
| ) | ||||
| SensorMapType = binary_sensor_map_ns.enum("SensorMapType") | ||||
|  | ||||
| SENSOR_MAP_TYPES = { | ||||
|     CONF_GROUP: SensorMapType.BINARY_SENSOR_MAP_TYPE_GROUP, | ||||
| @@ -20,14 +31,21 @@ entry = { | ||||
|     cv.Required(CONF_VALUE): cv.float_, | ||||
| } | ||||
|  | ||||
| CONFIG_SCHEMA = cv.typed_schema({ | ||||
|     CONF_GROUP: sensor.sensor_schema( | ||||
|         UNIT_EMPTY, ICON_CHECK_CIRCLE_OUTLINE, 0, DEVICE_CLASS_EMPTY | ||||
|     ).extend({ | ||||
|         cv.GenerateID(): cv.declare_id(BinarySensorMap), | ||||
|         cv.Required(CONF_CHANNELS): cv.All(cv.ensure_list(entry), cv.Length(min=1)), | ||||
|     }), | ||||
| }, lower=True) | ||||
| CONFIG_SCHEMA = cv.typed_schema( | ||||
|     { | ||||
|         CONF_GROUP: sensor.sensor_schema( | ||||
|             UNIT_EMPTY, ICON_CHECK_CIRCLE_OUTLINE, 0, DEVICE_CLASS_EMPTY | ||||
|         ).extend( | ||||
|             { | ||||
|                 cv.GenerateID(): cv.declare_id(BinarySensorMap), | ||||
|                 cv.Required(CONF_CHANNELS): cv.All( | ||||
|                     cv.ensure_list(entry), cv.Length(min=1) | ||||
|                 ), | ||||
|             } | ||||
|         ), | ||||
|     }, | ||||
|     lower=True, | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -3,18 +3,28 @@ import esphome.config_validation as cv | ||||
| from esphome.components import binary_sensor, esp32_ble_tracker | ||||
| from esphome.const import CONF_MAC_ADDRESS, CONF_SERVICE_UUID, CONF_ID | ||||
|  | ||||
| DEPENDENCIES = ['esp32_ble_tracker'] | ||||
| DEPENDENCIES = ["esp32_ble_tracker"] | ||||
|  | ||||
| ble_presence_ns = cg.esphome_ns.namespace('ble_presence') | ||||
| BLEPresenceDevice = ble_presence_ns.class_('BLEPresenceDevice', binary_sensor.BinarySensor, | ||||
|                                            cg.Component, esp32_ble_tracker.ESPBTDeviceListener) | ||||
| ble_presence_ns = cg.esphome_ns.namespace("ble_presence") | ||||
| BLEPresenceDevice = ble_presence_ns.class_( | ||||
|     "BLEPresenceDevice", | ||||
|     binary_sensor.BinarySensor, | ||||
|     cg.Component, | ||||
|     esp32_ble_tracker.ESPBTDeviceListener, | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All(binary_sensor.BINARY_SENSOR_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(BLEPresenceDevice), | ||||
|     cv.Optional(CONF_MAC_ADDRESS): cv.mac_address, | ||||
|     cv.Optional(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid, | ||||
| }).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend( | ||||
|     cv.COMPONENT_SCHEMA), cv.has_exactly_one_key(CONF_MAC_ADDRESS, CONF_SERVICE_UUID)) | ||||
| CONFIG_SCHEMA = cv.All( | ||||
|     binary_sensor.BINARY_SENSOR_SCHEMA.extend( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(BLEPresenceDevice), | ||||
|             cv.Optional(CONF_MAC_ADDRESS): cv.mac_address, | ||||
|             cv.Optional(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid, | ||||
|         } | ||||
|     ) | ||||
|     .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) | ||||
|     .extend(cv.COMPONENT_SCHEMA), | ||||
|     cv.has_exactly_one_key(CONF_MAC_ADDRESS, CONF_SERVICE_UUID), | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
| @@ -28,9 +38,17 @@ def to_code(config): | ||||
|  | ||||
|     if CONF_SERVICE_UUID in config: | ||||
|         if len(config[CONF_SERVICE_UUID]) == len(esp32_ble_tracker.bt_uuid16_format): | ||||
|             cg.add(var.set_service_uuid16(esp32_ble_tracker.as_hex(config[CONF_SERVICE_UUID]))) | ||||
|             cg.add( | ||||
|                 var.set_service_uuid16( | ||||
|                     esp32_ble_tracker.as_hex(config[CONF_SERVICE_UUID]) | ||||
|                 ) | ||||
|             ) | ||||
|         elif len(config[CONF_SERVICE_UUID]) == len(esp32_ble_tracker.bt_uuid32_format): | ||||
|             cg.add(var.set_service_uuid32(esp32_ble_tracker.as_hex(config[CONF_SERVICE_UUID]))) | ||||
|             cg.add( | ||||
|                 var.set_service_uuid32( | ||||
|                     esp32_ble_tracker.as_hex(config[CONF_SERVICE_UUID]) | ||||
|                 ) | ||||
|             ) | ||||
|         elif len(config[CONF_SERVICE_UUID]) == len(esp32_ble_tracker.bt_uuid128_format): | ||||
|             uuid128 = esp32_ble_tracker.as_hex_array(config[CONF_SERVICE_UUID]) | ||||
|             cg.add(var.set_service_uuid128(uuid128)) | ||||
|   | ||||
| @@ -1,23 +1,35 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor, esp32_ble_tracker | ||||
| from esphome.const import CONF_SERVICE_UUID, CONF_MAC_ADDRESS, CONF_ID, \ | ||||
|     DEVICE_CLASS_SIGNAL_STRENGTH, UNIT_DECIBEL, ICON_EMPTY | ||||
| from esphome.const import ( | ||||
|     CONF_SERVICE_UUID, | ||||
|     CONF_MAC_ADDRESS, | ||||
|     CONF_ID, | ||||
|     DEVICE_CLASS_SIGNAL_STRENGTH, | ||||
|     UNIT_DECIBEL, | ||||
|     ICON_EMPTY, | ||||
| ) | ||||
|  | ||||
| DEPENDENCIES = ['esp32_ble_tracker'] | ||||
| DEPENDENCIES = ["esp32_ble_tracker"] | ||||
|  | ||||
| ble_rssi_ns = cg.esphome_ns.namespace('ble_rssi') | ||||
| BLERSSISensor = ble_rssi_ns.class_('BLERSSISensor', sensor.Sensor, cg.Component, | ||||
|                                    esp32_ble_tracker.ESPBTDeviceListener) | ||||
| ble_rssi_ns = cg.esphome_ns.namespace("ble_rssi") | ||||
| BLERSSISensor = ble_rssi_ns.class_( | ||||
|     "BLERSSISensor", sensor.Sensor, cg.Component, esp32_ble_tracker.ESPBTDeviceListener | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All( | ||||
|     sensor.sensor_schema(UNIT_DECIBEL, ICON_EMPTY, 0, DEVICE_CLASS_SIGNAL_STRENGTH).extend({ | ||||
|         cv.GenerateID(): cv.declare_id(BLERSSISensor), | ||||
|         cv.Optional(CONF_MAC_ADDRESS): cv.mac_address, | ||||
|         cv.Optional(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid, | ||||
|     }).extend( | ||||
|         esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA | ||||
|     ).extend(cv.COMPONENT_SCHEMA), cv.has_exactly_one_key(CONF_MAC_ADDRESS, CONF_SERVICE_UUID)) | ||||
|     sensor.sensor_schema(UNIT_DECIBEL, ICON_EMPTY, 0, DEVICE_CLASS_SIGNAL_STRENGTH) | ||||
|     .extend( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(BLERSSISensor), | ||||
|             cv.Optional(CONF_MAC_ADDRESS): cv.mac_address, | ||||
|             cv.Optional(CONF_SERVICE_UUID): esp32_ble_tracker.bt_uuid, | ||||
|         } | ||||
|     ) | ||||
|     .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) | ||||
|     .extend(cv.COMPONENT_SCHEMA), | ||||
|     cv.has_exactly_one_key(CONF_MAC_ADDRESS, CONF_SERVICE_UUID), | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
| @@ -31,9 +43,17 @@ def to_code(config): | ||||
|  | ||||
|     if CONF_SERVICE_UUID in config: | ||||
|         if len(config[CONF_SERVICE_UUID]) == len(esp32_ble_tracker.bt_uuid16_format): | ||||
|             cg.add(var.set_service_uuid16(esp32_ble_tracker.as_hex(config[CONF_SERVICE_UUID]))) | ||||
|             cg.add( | ||||
|                 var.set_service_uuid16( | ||||
|                     esp32_ble_tracker.as_hex(config[CONF_SERVICE_UUID]) | ||||
|                 ) | ||||
|             ) | ||||
|         elif len(config[CONF_SERVICE_UUID]) == len(esp32_ble_tracker.bt_uuid32_format): | ||||
|             cg.add(var.set_service_uuid32(esp32_ble_tracker.as_hex(config[CONF_SERVICE_UUID]))) | ||||
|             cg.add( | ||||
|                 var.set_service_uuid32( | ||||
|                     esp32_ble_tracker.as_hex(config[CONF_SERVICE_UUID]) | ||||
|                 ) | ||||
|             ) | ||||
|         elif len(config[CONF_SERVICE_UUID]) == len(esp32_ble_tracker.bt_uuid128_format): | ||||
|             uuid128 = esp32_ble_tracker.as_hex_array(config[CONF_SERVICE_UUID]) | ||||
|             cg.add(var.set_service_uuid128(uuid128)) | ||||
|   | ||||
| @@ -3,16 +3,25 @@ import esphome.config_validation as cv | ||||
| from esphome.components import text_sensor, esp32_ble_tracker | ||||
| from esphome.const import CONF_ID | ||||
|  | ||||
| DEPENDENCIES = ['esp32_ble_tracker'] | ||||
| DEPENDENCIES = ["esp32_ble_tracker"] | ||||
|  | ||||
| ble_scanner_ns = cg.esphome_ns.namespace('ble_scanner') | ||||
| BLEScanner = ble_scanner_ns.class_('BLEScanner', text_sensor.TextSensor, cg.Component, | ||||
|                                    esp32_ble_tracker.ESPBTDeviceListener) | ||||
| ble_scanner_ns = cg.esphome_ns.namespace("ble_scanner") | ||||
| BLEScanner = ble_scanner_ns.class_( | ||||
|     "BLEScanner", | ||||
|     text_sensor.TextSensor, | ||||
|     cg.Component, | ||||
|     esp32_ble_tracker.ESPBTDeviceListener, | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All(text_sensor.TEXT_SENSOR_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(BLEScanner), | ||||
| }).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend( | ||||
|     cv.COMPONENT_SCHEMA)) | ||||
| CONFIG_SCHEMA = cv.All( | ||||
|     text_sensor.TEXT_SENSOR_SCHEMA.extend( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(BLEScanner), | ||||
|         } | ||||
|     ) | ||||
|     .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) | ||||
|     .extend(cv.COMPONENT_SCHEMA) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,53 +1,87 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.const import CONF_HUMIDITY, CONF_ID, CONF_IIR_FILTER, CONF_OVERSAMPLING, \ | ||||
|     CONF_PRESSURE, CONF_TEMPERATURE, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_PRESSURE, \ | ||||
|     DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, UNIT_CELSIUS, UNIT_HECTOPASCAL, UNIT_PERCENT | ||||
| from esphome.const import ( | ||||
|     CONF_HUMIDITY, | ||||
|     CONF_ID, | ||||
|     CONF_IIR_FILTER, | ||||
|     CONF_OVERSAMPLING, | ||||
|     CONF_PRESSURE, | ||||
|     CONF_TEMPERATURE, | ||||
|     DEVICE_CLASS_HUMIDITY, | ||||
|     DEVICE_CLASS_PRESSURE, | ||||
|     DEVICE_CLASS_TEMPERATURE, | ||||
|     ICON_EMPTY, | ||||
|     UNIT_CELSIUS, | ||||
|     UNIT_HECTOPASCAL, | ||||
|     UNIT_PERCENT, | ||||
| ) | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| DEPENDENCIES = ["i2c"] | ||||
|  | ||||
| bme280_ns = cg.esphome_ns.namespace('bme280') | ||||
| BME280Oversampling = bme280_ns.enum('BME280Oversampling') | ||||
| bme280_ns = cg.esphome_ns.namespace("bme280") | ||||
| BME280Oversampling = bme280_ns.enum("BME280Oversampling") | ||||
| OVERSAMPLING_OPTIONS = { | ||||
|     'NONE': BME280Oversampling.BME280_OVERSAMPLING_NONE, | ||||
|     '1X': BME280Oversampling.BME280_OVERSAMPLING_1X, | ||||
|     '2X': BME280Oversampling.BME280_OVERSAMPLING_2X, | ||||
|     '4X': BME280Oversampling.BME280_OVERSAMPLING_4X, | ||||
|     '8X': BME280Oversampling.BME280_OVERSAMPLING_8X, | ||||
|     '16X': BME280Oversampling.BME280_OVERSAMPLING_16X, | ||||
|     "NONE": BME280Oversampling.BME280_OVERSAMPLING_NONE, | ||||
|     "1X": BME280Oversampling.BME280_OVERSAMPLING_1X, | ||||
|     "2X": BME280Oversampling.BME280_OVERSAMPLING_2X, | ||||
|     "4X": BME280Oversampling.BME280_OVERSAMPLING_4X, | ||||
|     "8X": BME280Oversampling.BME280_OVERSAMPLING_8X, | ||||
|     "16X": BME280Oversampling.BME280_OVERSAMPLING_16X, | ||||
| } | ||||
|  | ||||
| BME280IIRFilter = bme280_ns.enum('BME280IIRFilter') | ||||
| BME280IIRFilter = bme280_ns.enum("BME280IIRFilter") | ||||
| IIR_FILTER_OPTIONS = { | ||||
|     'OFF': BME280IIRFilter.BME280_IIR_FILTER_OFF, | ||||
|     '2X': BME280IIRFilter.BME280_IIR_FILTER_2X, | ||||
|     '4X': BME280IIRFilter.BME280_IIR_FILTER_4X, | ||||
|     '8X': BME280IIRFilter.BME280_IIR_FILTER_8X, | ||||
|     '16X': BME280IIRFilter.BME280_IIR_FILTER_16X, | ||||
|     "OFF": BME280IIRFilter.BME280_IIR_FILTER_OFF, | ||||
|     "2X": BME280IIRFilter.BME280_IIR_FILTER_2X, | ||||
|     "4X": BME280IIRFilter.BME280_IIR_FILTER_4X, | ||||
|     "8X": BME280IIRFilter.BME280_IIR_FILTER_8X, | ||||
|     "16X": BME280IIRFilter.BME280_IIR_FILTER_16X, | ||||
| } | ||||
|  | ||||
| BME280Component = bme280_ns.class_('BME280Component', cg.PollingComponent, i2c.I2CDevice) | ||||
| BME280Component = bme280_ns.class_( | ||||
|     "BME280Component", cg.PollingComponent, i2c.I2CDevice | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(BME280Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): | ||||
|         sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE).extend({ | ||||
|             cv.Optional(CONF_OVERSAMPLING, default='16X'): | ||||
|                 cv.enum(OVERSAMPLING_OPTIONS, upper=True), | ||||
|         }), | ||||
|     cv.Optional(CONF_PRESSURE): | ||||
|         sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_EMPTY, 1, DEVICE_CLASS_PRESSURE).extend({ | ||||
|             cv.Optional(CONF_OVERSAMPLING, default='16X'): | ||||
|                 cv.enum(OVERSAMPLING_OPTIONS, upper=True), | ||||
|         }), | ||||
|     cv.Optional(CONF_HUMIDITY): | ||||
|         sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 1, DEVICE_CLASS_HUMIDITY).extend({ | ||||
|             cv.Optional(CONF_OVERSAMPLING, default='16X'): | ||||
|                 cv.enum(OVERSAMPLING_OPTIONS, upper=True), | ||||
|         }), | ||||
|     cv.Optional(CONF_IIR_FILTER, default='OFF'): cv.enum(IIR_FILTER_OPTIONS, upper=True), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x77)) | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(BME280Component), | ||||
|             cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( | ||||
|                 UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE | ||||
|             ).extend( | ||||
|                 { | ||||
|                     cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum( | ||||
|                         OVERSAMPLING_OPTIONS, upper=True | ||||
|                     ), | ||||
|                 } | ||||
|             ), | ||||
|             cv.Optional(CONF_PRESSURE): sensor.sensor_schema( | ||||
|                 UNIT_HECTOPASCAL, ICON_EMPTY, 1, DEVICE_CLASS_PRESSURE | ||||
|             ).extend( | ||||
|                 { | ||||
|                     cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum( | ||||
|                         OVERSAMPLING_OPTIONS, upper=True | ||||
|                     ), | ||||
|                 } | ||||
|             ), | ||||
|             cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( | ||||
|                 UNIT_PERCENT, ICON_EMPTY, 1, DEVICE_CLASS_HUMIDITY | ||||
|             ).extend( | ||||
|                 { | ||||
|                     cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum( | ||||
|                         OVERSAMPLING_OPTIONS, upper=True | ||||
|                     ), | ||||
|                 } | ||||
|             ), | ||||
|             cv.Optional(CONF_IIR_FILTER, default="OFF"): cv.enum( | ||||
|                 IIR_FILTER_OPTIONS, upper=True | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
|     .extend(i2c.i2c_device_schema(0x77)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -2,65 +2,116 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import core | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.const import CONF_DURATION, CONF_GAS_RESISTANCE, CONF_HEATER, \ | ||||
|     CONF_HUMIDITY, CONF_ID, CONF_IIR_FILTER, CONF_OVERSAMPLING, CONF_PRESSURE, \ | ||||
|     CONF_TEMPERATURE, DEVICE_CLASS_EMPTY, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_PRESSURE, \ | ||||
|     DEVICE_CLASS_TEMPERATURE, UNIT_OHM, ICON_GAS_CYLINDER, UNIT_CELSIUS, ICON_EMPTY, \ | ||||
|     UNIT_HECTOPASCAL, UNIT_PERCENT | ||||
| from esphome.const import ( | ||||
|     CONF_DURATION, | ||||
|     CONF_GAS_RESISTANCE, | ||||
|     CONF_HEATER, | ||||
|     CONF_HUMIDITY, | ||||
|     CONF_ID, | ||||
|     CONF_IIR_FILTER, | ||||
|     CONF_OVERSAMPLING, | ||||
|     CONF_PRESSURE, | ||||
|     CONF_TEMPERATURE, | ||||
|     DEVICE_CLASS_EMPTY, | ||||
|     DEVICE_CLASS_HUMIDITY, | ||||
|     DEVICE_CLASS_PRESSURE, | ||||
|     DEVICE_CLASS_TEMPERATURE, | ||||
|     UNIT_OHM, | ||||
|     ICON_GAS_CYLINDER, | ||||
|     UNIT_CELSIUS, | ||||
|     ICON_EMPTY, | ||||
|     UNIT_HECTOPASCAL, | ||||
|     UNIT_PERCENT, | ||||
| ) | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| DEPENDENCIES = ["i2c"] | ||||
|  | ||||
| bme680_ns = cg.esphome_ns.namespace('bme680') | ||||
| BME680Oversampling = bme680_ns.enum('BME680Oversampling') | ||||
| bme680_ns = cg.esphome_ns.namespace("bme680") | ||||
| BME680Oversampling = bme680_ns.enum("BME680Oversampling") | ||||
| OVERSAMPLING_OPTIONS = { | ||||
|     'NONE': BME680Oversampling.BME680_OVERSAMPLING_NONE, | ||||
|     '1X': BME680Oversampling.BME680_OVERSAMPLING_1X, | ||||
|     '2X': BME680Oversampling.BME680_OVERSAMPLING_2X, | ||||
|     '4X': BME680Oversampling.BME680_OVERSAMPLING_4X, | ||||
|     '8X': BME680Oversampling.BME680_OVERSAMPLING_8X, | ||||
|     '16X': BME680Oversampling.BME680_OVERSAMPLING_16X, | ||||
|     "NONE": BME680Oversampling.BME680_OVERSAMPLING_NONE, | ||||
|     "1X": BME680Oversampling.BME680_OVERSAMPLING_1X, | ||||
|     "2X": BME680Oversampling.BME680_OVERSAMPLING_2X, | ||||
|     "4X": BME680Oversampling.BME680_OVERSAMPLING_4X, | ||||
|     "8X": BME680Oversampling.BME680_OVERSAMPLING_8X, | ||||
|     "16X": BME680Oversampling.BME680_OVERSAMPLING_16X, | ||||
| } | ||||
|  | ||||
| BME680IIRFilter = bme680_ns.enum('BME680IIRFilter') | ||||
| BME680IIRFilter = bme680_ns.enum("BME680IIRFilter") | ||||
| IIR_FILTER_OPTIONS = { | ||||
|     'OFF': BME680IIRFilter.BME680_IIR_FILTER_OFF, | ||||
|     '1X': BME680IIRFilter.BME680_IIR_FILTER_1X, | ||||
|     '3X': BME680IIRFilter.BME680_IIR_FILTER_3X, | ||||
|     '7X': BME680IIRFilter.BME680_IIR_FILTER_7X, | ||||
|     '15X': BME680IIRFilter.BME680_IIR_FILTER_15X, | ||||
|     '31X': BME680IIRFilter.BME680_IIR_FILTER_31X, | ||||
|     '63X': BME680IIRFilter.BME680_IIR_FILTER_63X, | ||||
|     '127X': BME680IIRFilter.BME680_IIR_FILTER_127X, | ||||
|     "OFF": BME680IIRFilter.BME680_IIR_FILTER_OFF, | ||||
|     "1X": BME680IIRFilter.BME680_IIR_FILTER_1X, | ||||
|     "3X": BME680IIRFilter.BME680_IIR_FILTER_3X, | ||||
|     "7X": BME680IIRFilter.BME680_IIR_FILTER_7X, | ||||
|     "15X": BME680IIRFilter.BME680_IIR_FILTER_15X, | ||||
|     "31X": BME680IIRFilter.BME680_IIR_FILTER_31X, | ||||
|     "63X": BME680IIRFilter.BME680_IIR_FILTER_63X, | ||||
|     "127X": BME680IIRFilter.BME680_IIR_FILTER_127X, | ||||
| } | ||||
|  | ||||
| BME680Component = bme680_ns.class_('BME680Component', cg.PollingComponent, i2c.I2CDevice) | ||||
| BME680Component = bme680_ns.class_( | ||||
|     "BME680Component", cg.PollingComponent, i2c.I2CDevice | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(BME680Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): | ||||
|         sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE).extend({ | ||||
|             cv.Optional(CONF_OVERSAMPLING, default='16X'): | ||||
|                 cv.enum(OVERSAMPLING_OPTIONS, upper=True), | ||||
|         }), | ||||
|     cv.Optional(CONF_PRESSURE): | ||||
|         sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_EMPTY, 1, DEVICE_CLASS_PRESSURE).extend({ | ||||
|             cv.Optional(CONF_OVERSAMPLING, default='16X'): | ||||
|                 cv.enum(OVERSAMPLING_OPTIONS, upper=True), | ||||
|         }), | ||||
|     cv.Optional(CONF_HUMIDITY): | ||||
|         sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 1, DEVICE_CLASS_HUMIDITY).extend({ | ||||
|             cv.Optional(CONF_OVERSAMPLING, default='16X'): | ||||
|                 cv.enum(OVERSAMPLING_OPTIONS, upper=True), | ||||
|         }), | ||||
|     cv.Optional(CONF_GAS_RESISTANCE): | ||||
|         sensor.sensor_schema(UNIT_OHM, ICON_GAS_CYLINDER, 1, DEVICE_CLASS_EMPTY), | ||||
|     cv.Optional(CONF_IIR_FILTER, default='OFF'): cv.enum(IIR_FILTER_OPTIONS, upper=True), | ||||
|     cv.Optional(CONF_HEATER): cv.Any(None, cv.All(cv.Schema({ | ||||
|         cv.Optional(CONF_TEMPERATURE, default=320): cv.int_range(min=200, max=400), | ||||
|         cv.Optional(CONF_DURATION, default='150ms'): cv.All( | ||||
|             cv.positive_time_period_milliseconds, cv.Range(max=core.TimePeriod(milliseconds=4032))) | ||||
|     }), cv.has_at_least_one_key(CONF_TEMPERATURE, CONF_DURATION))), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x76)) | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(BME680Component), | ||||
|             cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( | ||||
|                 UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE | ||||
|             ).extend( | ||||
|                 { | ||||
|                     cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum( | ||||
|                         OVERSAMPLING_OPTIONS, upper=True | ||||
|                     ), | ||||
|                 } | ||||
|             ), | ||||
|             cv.Optional(CONF_PRESSURE): sensor.sensor_schema( | ||||
|                 UNIT_HECTOPASCAL, ICON_EMPTY, 1, DEVICE_CLASS_PRESSURE | ||||
|             ).extend( | ||||
|                 { | ||||
|                     cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum( | ||||
|                         OVERSAMPLING_OPTIONS, upper=True | ||||
|                     ), | ||||
|                 } | ||||
|             ), | ||||
|             cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( | ||||
|                 UNIT_PERCENT, ICON_EMPTY, 1, DEVICE_CLASS_HUMIDITY | ||||
|             ).extend( | ||||
|                 { | ||||
|                     cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum( | ||||
|                         OVERSAMPLING_OPTIONS, upper=True | ||||
|                     ), | ||||
|                 } | ||||
|             ), | ||||
|             cv.Optional(CONF_GAS_RESISTANCE): sensor.sensor_schema( | ||||
|                 UNIT_OHM, ICON_GAS_CYLINDER, 1, DEVICE_CLASS_EMPTY | ||||
|             ), | ||||
|             cv.Optional(CONF_IIR_FILTER, default="OFF"): cv.enum( | ||||
|                 IIR_FILTER_OPTIONS, upper=True | ||||
|             ), | ||||
|             cv.Optional(CONF_HEATER): cv.Any( | ||||
|                 None, | ||||
|                 cv.All( | ||||
|                     cv.Schema( | ||||
|                         { | ||||
|                             cv.Optional(CONF_TEMPERATURE, default=320): cv.int_range( | ||||
|                                 min=200, max=400 | ||||
|                             ), | ||||
|                             cv.Optional(CONF_DURATION, default="150ms"): cv.All( | ||||
|                                 cv.positive_time_period_milliseconds, | ||||
|                                 cv.Range(max=core.TimePeriod(milliseconds=4032)), | ||||
|                             ), | ||||
|                         } | ||||
|                     ), | ||||
|                     cv.has_at_least_one_key(CONF_TEMPERATURE, CONF_DURATION), | ||||
|                 ), | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
|     .extend(i2c.i2c_device_schema(0x76)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,21 +1,39 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.const import CONF_ID, CONF_PRESSURE, CONF_TEMPERATURE, DEVICE_CLASS_PRESSURE, \ | ||||
|     DEVICE_CLASS_TEMPERATURE, UNIT_CELSIUS, ICON_EMPTY, UNIT_HECTOPASCAL | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     CONF_PRESSURE, | ||||
|     CONF_TEMPERATURE, | ||||
|     DEVICE_CLASS_PRESSURE, | ||||
|     DEVICE_CLASS_TEMPERATURE, | ||||
|     UNIT_CELSIUS, | ||||
|     ICON_EMPTY, | ||||
|     UNIT_HECTOPASCAL, | ||||
| ) | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| DEPENDENCIES = ["i2c"] | ||||
|  | ||||
| bmp085_ns = cg.esphome_ns.namespace('bmp085') | ||||
| BMP085Component = bmp085_ns.class_('BMP085Component', cg.PollingComponent, i2c.I2CDevice) | ||||
| bmp085_ns = cg.esphome_ns.namespace("bmp085") | ||||
| BMP085Component = bmp085_ns.class_( | ||||
|     "BMP085Component", cg.PollingComponent, i2c.I2CDevice | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(BMP085Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, | ||||
|                                                         DEVICE_CLASS_TEMPERATURE), | ||||
|     cv.Optional(CONF_PRESSURE): sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_EMPTY, 1, | ||||
|                                                      DEVICE_CLASS_PRESSURE), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x77)) | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(BMP085Component), | ||||
|             cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( | ||||
|                 UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE | ||||
|             ), | ||||
|             cv.Optional(CONF_PRESSURE): sensor.sensor_schema( | ||||
|                 UNIT_HECTOPASCAL, ICON_EMPTY, 1, DEVICE_CLASS_PRESSURE | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
|     .extend(i2c.i2c_device_schema(0x77)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,48 +1,75 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.const import CONF_ID, CONF_PRESSURE, CONF_TEMPERATURE, DEVICE_CLASS_PRESSURE, \ | ||||
|     DEVICE_CLASS_TEMPERATURE, UNIT_CELSIUS, ICON_EMPTY, UNIT_HECTOPASCAL, CONF_IIR_FILTER, \ | ||||
|     CONF_OVERSAMPLING | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     CONF_PRESSURE, | ||||
|     CONF_TEMPERATURE, | ||||
|     DEVICE_CLASS_PRESSURE, | ||||
|     DEVICE_CLASS_TEMPERATURE, | ||||
|     UNIT_CELSIUS, | ||||
|     ICON_EMPTY, | ||||
|     UNIT_HECTOPASCAL, | ||||
|     CONF_IIR_FILTER, | ||||
|     CONF_OVERSAMPLING, | ||||
| ) | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| DEPENDENCIES = ["i2c"] | ||||
|  | ||||
| bmp280_ns = cg.esphome_ns.namespace('bmp280') | ||||
| BMP280Oversampling = bmp280_ns.enum('BMP280Oversampling') | ||||
| bmp280_ns = cg.esphome_ns.namespace("bmp280") | ||||
| BMP280Oversampling = bmp280_ns.enum("BMP280Oversampling") | ||||
| OVERSAMPLING_OPTIONS = { | ||||
|     'NONE': BMP280Oversampling.BMP280_OVERSAMPLING_NONE, | ||||
|     '1X': BMP280Oversampling.BMP280_OVERSAMPLING_1X, | ||||
|     '2X': BMP280Oversampling.BMP280_OVERSAMPLING_2X, | ||||
|     '4X': BMP280Oversampling.BMP280_OVERSAMPLING_4X, | ||||
|     '8X': BMP280Oversampling.BMP280_OVERSAMPLING_8X, | ||||
|     '16X': BMP280Oversampling.BMP280_OVERSAMPLING_16X, | ||||
|     "NONE": BMP280Oversampling.BMP280_OVERSAMPLING_NONE, | ||||
|     "1X": BMP280Oversampling.BMP280_OVERSAMPLING_1X, | ||||
|     "2X": BMP280Oversampling.BMP280_OVERSAMPLING_2X, | ||||
|     "4X": BMP280Oversampling.BMP280_OVERSAMPLING_4X, | ||||
|     "8X": BMP280Oversampling.BMP280_OVERSAMPLING_8X, | ||||
|     "16X": BMP280Oversampling.BMP280_OVERSAMPLING_16X, | ||||
| } | ||||
|  | ||||
| BMP280IIRFilter = bmp280_ns.enum('BMP280IIRFilter') | ||||
| BMP280IIRFilter = bmp280_ns.enum("BMP280IIRFilter") | ||||
| IIR_FILTER_OPTIONS = { | ||||
|     'OFF': BMP280IIRFilter.BMP280_IIR_FILTER_OFF, | ||||
|     '2X': BMP280IIRFilter.BMP280_IIR_FILTER_2X, | ||||
|     '4X': BMP280IIRFilter.BMP280_IIR_FILTER_4X, | ||||
|     '8X': BMP280IIRFilter.BMP280_IIR_FILTER_8X, | ||||
|     '16X': BMP280IIRFilter.BMP280_IIR_FILTER_16X, | ||||
|     "OFF": BMP280IIRFilter.BMP280_IIR_FILTER_OFF, | ||||
|     "2X": BMP280IIRFilter.BMP280_IIR_FILTER_2X, | ||||
|     "4X": BMP280IIRFilter.BMP280_IIR_FILTER_4X, | ||||
|     "8X": BMP280IIRFilter.BMP280_IIR_FILTER_8X, | ||||
|     "16X": BMP280IIRFilter.BMP280_IIR_FILTER_16X, | ||||
| } | ||||
|  | ||||
| BMP280Component = bmp280_ns.class_('BMP280Component', cg.PollingComponent, i2c.I2CDevice) | ||||
| BMP280Component = bmp280_ns.class_( | ||||
|     "BMP280Component", cg.PollingComponent, i2c.I2CDevice | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(BMP280Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( | ||||
|         UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE | ||||
|     ).extend({ | ||||
|         cv.Optional(CONF_OVERSAMPLING, default='16X'): cv.enum(OVERSAMPLING_OPTIONS, upper=True), | ||||
|     }), | ||||
|     cv.Optional(CONF_PRESSURE): sensor.sensor_schema( | ||||
|         UNIT_HECTOPASCAL, ICON_EMPTY, 1, DEVICE_CLASS_PRESSURE | ||||
|     ).extend({ | ||||
|         cv.Optional(CONF_OVERSAMPLING, default='16X'): cv.enum(OVERSAMPLING_OPTIONS, upper=True), | ||||
|     }), | ||||
|     cv.Optional(CONF_IIR_FILTER, default='OFF'): cv.enum(IIR_FILTER_OPTIONS, upper=True), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x77)) | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(BMP280Component), | ||||
|             cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( | ||||
|                 UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE | ||||
|             ).extend( | ||||
|                 { | ||||
|                     cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum( | ||||
|                         OVERSAMPLING_OPTIONS, upper=True | ||||
|                     ), | ||||
|                 } | ||||
|             ), | ||||
|             cv.Optional(CONF_PRESSURE): sensor.sensor_schema( | ||||
|                 UNIT_HECTOPASCAL, ICON_EMPTY, 1, DEVICE_CLASS_PRESSURE | ||||
|             ).extend( | ||||
|                 { | ||||
|                     cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum( | ||||
|                         OVERSAMPLING_OPTIONS, upper=True | ||||
|                     ), | ||||
|                 } | ||||
|             ), | ||||
|             cv.Optional(CONF_IIR_FILTER, default="OFF"): cv.enum( | ||||
|                 IIR_FILTER_OPTIONS, upper=True | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
|     .extend(i2c.i2c_device_schema(0x77)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -4,68 +4,76 @@ from esphome import automation | ||||
| from esphome.core import CORE, coroutine | ||||
| from esphome.const import CONF_ID, CONF_TRIGGER_ID, CONF_DATA | ||||
|  | ||||
| CODEOWNERS = ['@mvturnho', '@danielschramm'] | ||||
| CODEOWNERS = ["@mvturnho", "@danielschramm"] | ||||
| IS_PLATFORM_COMPONENT = True | ||||
|  | ||||
| CONF_CAN_ID = 'can_id' | ||||
| CONF_USE_EXTENDED_ID = 'use_extended_id' | ||||
| CONF_CANBUS_ID = 'canbus_id' | ||||
| CONF_BIT_RATE = 'bit_rate' | ||||
| CONF_ON_FRAME = 'on_frame' | ||||
| CONF_CANBUS_SEND = 'canbus.send' | ||||
| CONF_CAN_ID = "can_id" | ||||
| CONF_USE_EXTENDED_ID = "use_extended_id" | ||||
| CONF_CANBUS_ID = "canbus_id" | ||||
| CONF_BIT_RATE = "bit_rate" | ||||
| CONF_ON_FRAME = "on_frame" | ||||
| CONF_CANBUS_SEND = "canbus.send" | ||||
|  | ||||
|  | ||||
| def validate_id(id_value, id_ext): | ||||
|     if not id_ext: | ||||
|         if id_value > 0x7ff: | ||||
|         if id_value > 0x7FF: | ||||
|             raise cv.Invalid("Standard IDs must be 11 Bit (0x000-0x7ff / 0-2047)") | ||||
|  | ||||
|  | ||||
| def validate_raw_data(value): | ||||
|     if isinstance(value, str): | ||||
|         return value.encode('utf-8') | ||||
|         return value.encode("utf-8") | ||||
|     if isinstance(value, list): | ||||
|         return cv.Schema([cv.hex_uint8_t])(value) | ||||
|     raise cv.Invalid("data must either be a string wrapped in quotes or a list of bytes") | ||||
|     raise cv.Invalid( | ||||
|         "data must either be a string wrapped in quotes or a list of bytes" | ||||
|     ) | ||||
|  | ||||
|  | ||||
| canbus_ns = cg.esphome_ns.namespace('canbus') | ||||
| CanbusComponent = canbus_ns.class_('CanbusComponent', cg.Component) | ||||
| CanbusTrigger = canbus_ns.class_('CanbusTrigger', | ||||
|                                  automation.Trigger.template(cg.std_vector.template(cg.uint8)), | ||||
|                                  cg.Component) | ||||
| CanSpeed = canbus_ns.enum('CAN_SPEED') | ||||
| canbus_ns = cg.esphome_ns.namespace("canbus") | ||||
| CanbusComponent = canbus_ns.class_("CanbusComponent", cg.Component) | ||||
| CanbusTrigger = canbus_ns.class_( | ||||
|     "CanbusTrigger", | ||||
|     automation.Trigger.template(cg.std_vector.template(cg.uint8)), | ||||
|     cg.Component, | ||||
| ) | ||||
| CanSpeed = canbus_ns.enum("CAN_SPEED") | ||||
|  | ||||
| CAN_SPEEDS = { | ||||
|     '5KBPS': CanSpeed.CAN_5KBPS, | ||||
|     '10KBPS': CanSpeed.CAN_10KBPS, | ||||
|     '20KBPS': CanSpeed.CAN_20KBPS, | ||||
|     '31K25BPS': CanSpeed.CAN_31K25BPS, | ||||
|     '33KBPS': CanSpeed.CAN_33KBPS, | ||||
|     '40KBPS': CanSpeed.CAN_40KBPS, | ||||
|     '50KBPS': CanSpeed.CAN_50KBPS, | ||||
|     '80KBPS': CanSpeed.CAN_80KBPS, | ||||
|     '83K3BPS': CanSpeed.CAN_83K3BPS, | ||||
|     '95KBPS': CanSpeed.CAN_95KBPS, | ||||
|     '100KBPS': CanSpeed.CAN_100KBPS, | ||||
|     '125KBPS': CanSpeed.CAN_125KBPS, | ||||
|     '200KBPS': CanSpeed.CAN_200KBPS, | ||||
|     '250KBPS': CanSpeed.CAN_250KBPS, | ||||
|     '500KBPS': CanSpeed.CAN_500KBPS, | ||||
|     '1000KBPS': CanSpeed.CAN_1000KBPS, | ||||
|     "5KBPS": CanSpeed.CAN_5KBPS, | ||||
|     "10KBPS": CanSpeed.CAN_10KBPS, | ||||
|     "20KBPS": CanSpeed.CAN_20KBPS, | ||||
|     "31K25BPS": CanSpeed.CAN_31K25BPS, | ||||
|     "33KBPS": CanSpeed.CAN_33KBPS, | ||||
|     "40KBPS": CanSpeed.CAN_40KBPS, | ||||
|     "50KBPS": CanSpeed.CAN_50KBPS, | ||||
|     "80KBPS": CanSpeed.CAN_80KBPS, | ||||
|     "83K3BPS": CanSpeed.CAN_83K3BPS, | ||||
|     "95KBPS": CanSpeed.CAN_95KBPS, | ||||
|     "100KBPS": CanSpeed.CAN_100KBPS, | ||||
|     "125KBPS": CanSpeed.CAN_125KBPS, | ||||
|     "200KBPS": CanSpeed.CAN_200KBPS, | ||||
|     "250KBPS": CanSpeed.CAN_250KBPS, | ||||
|     "500KBPS": CanSpeed.CAN_500KBPS, | ||||
|     "1000KBPS": CanSpeed.CAN_1000KBPS, | ||||
| } | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(CanbusComponent), | ||||
|     cv.Required(CONF_CAN_ID): cv.int_range(min=0, max=0x1fffffff), | ||||
|     cv.Optional(CONF_BIT_RATE, default='125KBPS'): cv.enum(CAN_SPEEDS, upper=True), | ||||
|     cv.Optional(CONF_USE_EXTENDED_ID, default=False): cv.boolean, | ||||
|     cv.Optional(CONF_ON_FRAME): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CanbusTrigger), | ||||
|         cv.GenerateID(CONF_CAN_ID): cv.int_range(min=0, max=0x1fffffff), | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(CanbusComponent), | ||||
|         cv.Required(CONF_CAN_ID): cv.int_range(min=0, max=0x1FFFFFFF), | ||||
|         cv.Optional(CONF_BIT_RATE, default="125KBPS"): cv.enum(CAN_SPEEDS, upper=True), | ||||
|         cv.Optional(CONF_USE_EXTENDED_ID, default=False): cv.boolean, | ||||
|     }), | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
|         cv.Optional(CONF_ON_FRAME): automation.validate_automation( | ||||
|             { | ||||
|                 cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CanbusTrigger), | ||||
|                 cv.GenerateID(CONF_CAN_ID): cv.int_range(min=0, max=0x1FFFFFFF), | ||||
|                 cv.Optional(CONF_USE_EXTENDED_ID, default=False): cv.boolean, | ||||
|             } | ||||
|         ), | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| @@ -82,7 +90,9 @@ def setup_canbus_core_(var, config): | ||||
|         validate_id(can_id, ext_id) | ||||
|         trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var, can_id, ext_id) | ||||
|         yield cg.register_component(trigger, conf) | ||||
|         yield automation.build_automation(trigger, [(cg.std_vector.template(cg.uint8), 'x')], conf) | ||||
|         yield automation.build_automation( | ||||
|             trigger, [(cg.std_vector.template(cg.uint8), "x")], conf | ||||
|         ) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| @@ -93,14 +103,19 @@ def register_canbus(var, config): | ||||
|  | ||||
|  | ||||
| # Actions | ||||
| @automation.register_action(CONF_CANBUS_SEND, | ||||
|                             canbus_ns.class_('CanbusSendAction', automation.Action), | ||||
|                             cv.maybe_simple_value({ | ||||
|                                 cv.GenerateID(CONF_CANBUS_ID): cv.use_id(CanbusComponent), | ||||
|                                 cv.Optional(CONF_CAN_ID): cv.int_range(min=0, max=0x1fffffff), | ||||
|                                 cv.Optional(CONF_USE_EXTENDED_ID, default=False): cv.boolean, | ||||
|                                 cv.Required(CONF_DATA): cv.templatable(validate_raw_data), | ||||
|                             }, key=CONF_DATA)) | ||||
| @automation.register_action( | ||||
|     CONF_CANBUS_SEND, | ||||
|     canbus_ns.class_("CanbusSendAction", automation.Action), | ||||
|     cv.maybe_simple_value( | ||||
|         { | ||||
|             cv.GenerateID(CONF_CANBUS_ID): cv.use_id(CanbusComponent), | ||||
|             cv.Optional(CONF_CAN_ID): cv.int_range(min=0, max=0x1FFFFFFF), | ||||
|             cv.Optional(CONF_USE_EXTENDED_ID, default=False): cv.boolean, | ||||
|             cv.Required(CONF_DATA): cv.templatable(validate_raw_data), | ||||
|         }, | ||||
|         key=CONF_DATA, | ||||
|     ), | ||||
| ) | ||||
| def canbus_action_to_code(config, action_id, template_arg, args): | ||||
|     validate_id(config[CONF_CAN_ID], config[CONF_USE_EXTENDED_ID]) | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
| @@ -110,7 +125,9 @@ def canbus_action_to_code(config, action_id, template_arg, args): | ||||
|         can_id = yield cg.templatable(config[CONF_CAN_ID], args, cg.uint32) | ||||
|         cg.add(var.set_can_id(can_id)) | ||||
|  | ||||
|     use_extended_id = yield cg.templatable(config[CONF_USE_EXTENDED_ID], args, cg.uint32) | ||||
|     use_extended_id = yield cg.templatable( | ||||
|         config[CONF_USE_EXTENDED_ID], args, cg.uint32 | ||||
|     ) | ||||
|     cg.add(var.set_use_extended_id(use_extended_id)) | ||||
|  | ||||
|     data = config[CONF_DATA] | ||||
|   | ||||
| @@ -5,17 +5,21 @@ from esphome.components.web_server_base import CONF_WEB_SERVER_BASE_ID | ||||
| from esphome.const import CONF_ID | ||||
| from esphome.core import coroutine_with_priority | ||||
|  | ||||
| AUTO_LOAD = ['web_server_base'] | ||||
| DEPENDENCIES = ['wifi'] | ||||
| CODEOWNERS = ['@OttoWinter'] | ||||
| AUTO_LOAD = ["web_server_base"] | ||||
| DEPENDENCIES = ["wifi"] | ||||
| CODEOWNERS = ["@OttoWinter"] | ||||
|  | ||||
| captive_portal_ns = cg.esphome_ns.namespace('captive_portal') | ||||
| CaptivePortal = captive_portal_ns.class_('CaptivePortal', cg.Component) | ||||
| captive_portal_ns = cg.esphome_ns.namespace("captive_portal") | ||||
| CaptivePortal = captive_portal_ns.class_("CaptivePortal", cg.Component) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(CaptivePortal), | ||||
|     cv.GenerateID(CONF_WEB_SERVER_BASE_ID): cv.use_id(web_server_base.WebServerBase), | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(CaptivePortal), | ||||
|         cv.GenerateID(CONF_WEB_SERVER_BASE_ID): cv.use_id( | ||||
|             web_server_base.WebServerBase | ||||
|         ), | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| @coroutine_with_priority(64.0) | ||||
| @@ -24,4 +28,4 @@ def to_code(config): | ||||
|  | ||||
|     var = cg.new_Pvariable(config[CONF_ID], paren) | ||||
|     yield cg.register_component(var, config) | ||||
|     cg.add_define('USE_CAPTIVE_PORTAL') | ||||
|     cg.add_define("USE_CAPTIVE_PORTAL") | ||||
|   | ||||
| @@ -1,28 +1,46 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.const import CONF_ID, DEVICE_CLASS_EMPTY, ICON_RADIATOR, UNIT_PARTS_PER_MILLION, \ | ||||
|     UNIT_PARTS_PER_BILLION, CONF_TEMPERATURE, CONF_TVOC, CONF_HUMIDITY, ICON_MOLECULE_CO2 | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     DEVICE_CLASS_EMPTY, | ||||
|     ICON_RADIATOR, | ||||
|     UNIT_PARTS_PER_MILLION, | ||||
|     UNIT_PARTS_PER_BILLION, | ||||
|     CONF_TEMPERATURE, | ||||
|     CONF_TVOC, | ||||
|     CONF_HUMIDITY, | ||||
|     ICON_MOLECULE_CO2, | ||||
| ) | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| DEPENDENCIES = ["i2c"] | ||||
|  | ||||
| ccs811_ns = cg.esphome_ns.namespace('ccs811') | ||||
| CCS811Component = ccs811_ns.class_('CCS811Component', cg.PollingComponent, i2c.I2CDevice) | ||||
| ccs811_ns = cg.esphome_ns.namespace("ccs811") | ||||
| CCS811Component = ccs811_ns.class_( | ||||
|     "CCS811Component", cg.PollingComponent, i2c.I2CDevice | ||||
| ) | ||||
|  | ||||
| CONF_ECO2 = 'eco2' | ||||
| CONF_BASELINE = 'baseline' | ||||
| CONF_ECO2 = "eco2" | ||||
| CONF_BASELINE = "baseline" | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(CCS811Component), | ||||
|     cv.Required(CONF_ECO2): sensor.sensor_schema(UNIT_PARTS_PER_MILLION, ICON_MOLECULE_CO2, | ||||
|                                                  0, DEVICE_CLASS_EMPTY), | ||||
|     cv.Required(CONF_TVOC): sensor.sensor_schema(UNIT_PARTS_PER_BILLION, ICON_RADIATOR, | ||||
|                                                  0, DEVICE_CLASS_EMPTY), | ||||
|  | ||||
|     cv.Optional(CONF_BASELINE): cv.hex_uint16_t, | ||||
|     cv.Optional(CONF_TEMPERATURE): cv.use_id(sensor.Sensor), | ||||
|     cv.Optional(CONF_HUMIDITY): cv.use_id(sensor.Sensor), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x5A)) | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(CCS811Component), | ||||
|             cv.Required(CONF_ECO2): sensor.sensor_schema( | ||||
|                 UNIT_PARTS_PER_MILLION, ICON_MOLECULE_CO2, 0, DEVICE_CLASS_EMPTY | ||||
|             ), | ||||
|             cv.Required(CONF_TVOC): sensor.sensor_schema( | ||||
|                 UNIT_PARTS_PER_BILLION, ICON_RADIATOR, 0, DEVICE_CLASS_EMPTY | ||||
|             ), | ||||
|             cv.Optional(CONF_BASELINE): cv.hex_uint16_t, | ||||
|             cv.Optional(CONF_TEMPERATURE): cv.use_id(sensor.Sensor), | ||||
|             cv.Optional(CONF_HUMIDITY): cv.use_id(sensor.Sensor), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
|     .extend(i2c.i2c_device_schema(0x5A)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -2,70 +2,87 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import automation | ||||
| from esphome.components import mqtt | ||||
| from esphome.const import CONF_AWAY, CONF_ID, CONF_INTERNAL, CONF_MAX_TEMPERATURE, \ | ||||
|     CONF_MIN_TEMPERATURE, CONF_MODE, CONF_TARGET_TEMPERATURE, \ | ||||
|     CONF_TARGET_TEMPERATURE_HIGH, CONF_TARGET_TEMPERATURE_LOW, CONF_TEMPERATURE_STEP, CONF_VISUAL, \ | ||||
|     CONF_MQTT_ID, CONF_NAME, CONF_FAN_MODE, CONF_SWING_MODE | ||||
| from esphome.const import ( | ||||
|     CONF_AWAY, | ||||
|     CONF_ID, | ||||
|     CONF_INTERNAL, | ||||
|     CONF_MAX_TEMPERATURE, | ||||
|     CONF_MIN_TEMPERATURE, | ||||
|     CONF_MODE, | ||||
|     CONF_TARGET_TEMPERATURE, | ||||
|     CONF_TARGET_TEMPERATURE_HIGH, | ||||
|     CONF_TARGET_TEMPERATURE_LOW, | ||||
|     CONF_TEMPERATURE_STEP, | ||||
|     CONF_VISUAL, | ||||
|     CONF_MQTT_ID, | ||||
|     CONF_NAME, | ||||
|     CONF_FAN_MODE, | ||||
|     CONF_SWING_MODE, | ||||
| ) | ||||
| from esphome.core import CORE, coroutine, coroutine_with_priority | ||||
|  | ||||
| IS_PLATFORM_COMPONENT = True | ||||
|  | ||||
| CODEOWNERS = ['@esphome/core'] | ||||
| climate_ns = cg.esphome_ns.namespace('climate') | ||||
| CODEOWNERS = ["@esphome/core"] | ||||
| climate_ns = cg.esphome_ns.namespace("climate") | ||||
|  | ||||
| Climate = climate_ns.class_('Climate', cg.Nameable) | ||||
| ClimateCall = climate_ns.class_('ClimateCall') | ||||
| ClimateTraits = climate_ns.class_('ClimateTraits') | ||||
| Climate = climate_ns.class_("Climate", cg.Nameable) | ||||
| ClimateCall = climate_ns.class_("ClimateCall") | ||||
| ClimateTraits = climate_ns.class_("ClimateTraits") | ||||
|  | ||||
| ClimateMode = climate_ns.enum('ClimateMode') | ||||
| ClimateMode = climate_ns.enum("ClimateMode") | ||||
| CLIMATE_MODES = { | ||||
|     'OFF': ClimateMode.CLIMATE_MODE_OFF, | ||||
|     'AUTO': ClimateMode.CLIMATE_MODE_AUTO, | ||||
|     'COOL': ClimateMode.CLIMATE_MODE_COOL, | ||||
|     'HEAT': ClimateMode.CLIMATE_MODE_HEAT, | ||||
|     'DRY': ClimateMode.CLIMATE_MODE_DRY, | ||||
|     'FAN_ONLY': ClimateMode.CLIMATE_MODE_FAN_ONLY, | ||||
|     "OFF": ClimateMode.CLIMATE_MODE_OFF, | ||||
|     "AUTO": ClimateMode.CLIMATE_MODE_AUTO, | ||||
|     "COOL": ClimateMode.CLIMATE_MODE_COOL, | ||||
|     "HEAT": ClimateMode.CLIMATE_MODE_HEAT, | ||||
|     "DRY": ClimateMode.CLIMATE_MODE_DRY, | ||||
|     "FAN_ONLY": ClimateMode.CLIMATE_MODE_FAN_ONLY, | ||||
| } | ||||
| validate_climate_mode = cv.enum(CLIMATE_MODES, upper=True) | ||||
|  | ||||
| ClimateFanMode = climate_ns.enum('ClimateFanMode') | ||||
| ClimateFanMode = climate_ns.enum("ClimateFanMode") | ||||
| CLIMATE_FAN_MODES = { | ||||
|     'ON': ClimateFanMode.CLIMATE_FAN_ON, | ||||
|     'OFF': ClimateFanMode.CLIMATE_FAN_OFF, | ||||
|     'AUTO': ClimateFanMode.CLIMATE_FAN_AUTO, | ||||
|     'LOW': ClimateFanMode.CLIMATE_FAN_LOW, | ||||
|     'MEDIUM': ClimateFanMode.CLIMATE_FAN_MEDIUM, | ||||
|     'HIGH': ClimateFanMode.CLIMATE_FAN_HIGH, | ||||
|     'MIDDLE': ClimateFanMode.CLIMATE_FAN_MIDDLE, | ||||
|     'FOCUS': ClimateFanMode.CLIMATE_FAN_FOCUS, | ||||
|     'DIFFUSE': ClimateFanMode.CLIMATE_FAN_DIFFUSE, | ||||
|     "ON": ClimateFanMode.CLIMATE_FAN_ON, | ||||
|     "OFF": ClimateFanMode.CLIMATE_FAN_OFF, | ||||
|     "AUTO": ClimateFanMode.CLIMATE_FAN_AUTO, | ||||
|     "LOW": ClimateFanMode.CLIMATE_FAN_LOW, | ||||
|     "MEDIUM": ClimateFanMode.CLIMATE_FAN_MEDIUM, | ||||
|     "HIGH": ClimateFanMode.CLIMATE_FAN_HIGH, | ||||
|     "MIDDLE": ClimateFanMode.CLIMATE_FAN_MIDDLE, | ||||
|     "FOCUS": ClimateFanMode.CLIMATE_FAN_FOCUS, | ||||
|     "DIFFUSE": ClimateFanMode.CLIMATE_FAN_DIFFUSE, | ||||
| } | ||||
|  | ||||
| validate_climate_fan_mode = cv.enum(CLIMATE_FAN_MODES, upper=True) | ||||
|  | ||||
| ClimateSwingMode = climate_ns.enum('ClimateSwingMode') | ||||
| ClimateSwingMode = climate_ns.enum("ClimateSwingMode") | ||||
| CLIMATE_SWING_MODES = { | ||||
|     'OFF': ClimateSwingMode.CLIMATE_SWING_OFF, | ||||
|     'BOTH': ClimateSwingMode.CLIMATE_SWING_BOTH, | ||||
|     'VERTICAL': ClimateSwingMode.CLIMATE_SWING_VERTICAL, | ||||
|     'HORIZONTAL': ClimateSwingMode.CLIMATE_SWING_HORIZONTAL, | ||||
|     "OFF": ClimateSwingMode.CLIMATE_SWING_OFF, | ||||
|     "BOTH": ClimateSwingMode.CLIMATE_SWING_BOTH, | ||||
|     "VERTICAL": ClimateSwingMode.CLIMATE_SWING_VERTICAL, | ||||
|     "HORIZONTAL": ClimateSwingMode.CLIMATE_SWING_HORIZONTAL, | ||||
| } | ||||
|  | ||||
| validate_climate_swing_mode = cv.enum(CLIMATE_SWING_MODES, upper=True) | ||||
|  | ||||
| # Actions | ||||
| ControlAction = climate_ns.class_('ControlAction', automation.Action) | ||||
| ControlAction = climate_ns.class_("ControlAction", automation.Action) | ||||
|  | ||||
| CLIMATE_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(Climate), | ||||
|     cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTClimateComponent), | ||||
|     cv.Optional(CONF_VISUAL, default={}): cv.Schema({ | ||||
|         cv.Optional(CONF_MIN_TEMPERATURE): cv.temperature, | ||||
|         cv.Optional(CONF_MAX_TEMPERATURE): cv.temperature, | ||||
|         cv.Optional(CONF_TEMPERATURE_STEP): cv.temperature, | ||||
|     }), | ||||
|     # TODO: MQTT topic options | ||||
| }) | ||||
| CLIMATE_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(Climate), | ||||
|         cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTClimateComponent), | ||||
|         cv.Optional(CONF_VISUAL, default={}): cv.Schema( | ||||
|             { | ||||
|                 cv.Optional(CONF_MIN_TEMPERATURE): cv.temperature, | ||||
|                 cv.Optional(CONF_MAX_TEMPERATURE): cv.temperature, | ||||
|                 cv.Optional(CONF_TEMPERATURE_STEP): cv.temperature, | ||||
|             } | ||||
|         ), | ||||
|         # TODO: MQTT topic options | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| @@ -94,19 +111,23 @@ def register_climate(var, config): | ||||
|     yield setup_climate_core_(var, config) | ||||
|  | ||||
|  | ||||
| CLIMATE_CONTROL_ACTION_SCHEMA = cv.Schema({ | ||||
|     cv.Required(CONF_ID): cv.use_id(Climate), | ||||
|     cv.Optional(CONF_MODE): cv.templatable(validate_climate_mode), | ||||
|     cv.Optional(CONF_TARGET_TEMPERATURE): cv.templatable(cv.temperature), | ||||
|     cv.Optional(CONF_TARGET_TEMPERATURE_LOW): cv.templatable(cv.temperature), | ||||
|     cv.Optional(CONF_TARGET_TEMPERATURE_HIGH): cv.templatable(cv.temperature), | ||||
|     cv.Optional(CONF_AWAY): cv.templatable(cv.boolean), | ||||
|     cv.Optional(CONF_FAN_MODE): cv.templatable(validate_climate_fan_mode), | ||||
|     cv.Optional(CONF_SWING_MODE): cv.templatable(validate_climate_swing_mode), | ||||
| }) | ||||
| CLIMATE_CONTROL_ACTION_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.Required(CONF_ID): cv.use_id(Climate), | ||||
|         cv.Optional(CONF_MODE): cv.templatable(validate_climate_mode), | ||||
|         cv.Optional(CONF_TARGET_TEMPERATURE): cv.templatable(cv.temperature), | ||||
|         cv.Optional(CONF_TARGET_TEMPERATURE_LOW): cv.templatable(cv.temperature), | ||||
|         cv.Optional(CONF_TARGET_TEMPERATURE_HIGH): cv.templatable(cv.temperature), | ||||
|         cv.Optional(CONF_AWAY): cv.templatable(cv.boolean), | ||||
|         cv.Optional(CONF_FAN_MODE): cv.templatable(validate_climate_fan_mode), | ||||
|         cv.Optional(CONF_SWING_MODE): cv.templatable(validate_climate_swing_mode), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @automation.register_action('climate.control', ControlAction, CLIMATE_CONTROL_ACTION_SCHEMA) | ||||
| @automation.register_action( | ||||
|     "climate.control", ControlAction, CLIMATE_CONTROL_ACTION_SCHEMA | ||||
| ) | ||||
| def climate_control_to_code(config, action_id, template_arg, args): | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, paren) | ||||
| @@ -117,10 +138,14 @@ def climate_control_to_code(config, action_id, template_arg, args): | ||||
|         template_ = yield cg.templatable(config[CONF_TARGET_TEMPERATURE], args, float) | ||||
|         cg.add(var.set_target_temperature(template_)) | ||||
|     if CONF_TARGET_TEMPERATURE_LOW in config: | ||||
|         template_ = yield cg.templatable(config[CONF_TARGET_TEMPERATURE_LOW], args, float) | ||||
|         template_ = yield cg.templatable( | ||||
|             config[CONF_TARGET_TEMPERATURE_LOW], args, float | ||||
|         ) | ||||
|         cg.add(var.set_target_temperature_low(template_)) | ||||
|     if CONF_TARGET_TEMPERATURE_HIGH in config: | ||||
|         template_ = yield cg.templatable(config[CONF_TARGET_TEMPERATURE_HIGH], args, float) | ||||
|         template_ = yield cg.templatable( | ||||
|             config[CONF_TARGET_TEMPERATURE_HIGH], args, float | ||||
|         ) | ||||
|         cg.add(var.set_target_temperature_high(template_)) | ||||
|     if CONF_AWAY in config: | ||||
|         template_ = yield cg.templatable(config[CONF_AWAY], args, bool) | ||||
| @@ -129,12 +154,14 @@ def climate_control_to_code(config, action_id, template_arg, args): | ||||
|         template_ = yield cg.templatable(config[CONF_FAN_MODE], args, ClimateFanMode) | ||||
|         cg.add(var.set_fan_mode(template_)) | ||||
|     if CONF_SWING_MODE in config: | ||||
|         template_ = yield cg.templatable(config[CONF_SWING_MODE], args, ClimateSwingMode) | ||||
|         template_ = yield cg.templatable( | ||||
|             config[CONF_SWING_MODE], args, ClimateSwingMode | ||||
|         ) | ||||
|         cg.add(var.set_swing_mode(template_)) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @coroutine_with_priority(100.0) | ||||
| def to_code(config): | ||||
|     cg.add_define('USE_CLIMATE') | ||||
|     cg.add_define("USE_CLIMATE") | ||||
|     cg.add_global(climate_ns.using) | ||||
|   | ||||
| @@ -1,27 +1,42 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import climate, remote_transmitter, remote_receiver, sensor, remote_base | ||||
| from esphome.components import ( | ||||
|     climate, | ||||
|     remote_transmitter, | ||||
|     remote_receiver, | ||||
|     sensor, | ||||
|     remote_base, | ||||
| ) | ||||
| from esphome.components.remote_base import CONF_RECEIVER_ID, CONF_TRANSMITTER_ID | ||||
| from esphome.const import CONF_SUPPORTS_COOL, CONF_SUPPORTS_HEAT, CONF_SENSOR | ||||
| from esphome.core import coroutine | ||||
|  | ||||
| AUTO_LOAD = ['sensor', 'remote_base'] | ||||
| CODEOWNERS = ['@glmnet'] | ||||
| AUTO_LOAD = ["sensor", "remote_base"] | ||||
| CODEOWNERS = ["@glmnet"] | ||||
|  | ||||
| climate_ir_ns = cg.esphome_ns.namespace('climate_ir') | ||||
| ClimateIR = climate_ir_ns.class_('ClimateIR', climate.Climate, cg.Component, | ||||
|                                  remote_base.RemoteReceiverListener) | ||||
| climate_ir_ns = cg.esphome_ns.namespace("climate_ir") | ||||
| ClimateIR = climate_ir_ns.class_( | ||||
|     "ClimateIR", climate.Climate, cg.Component, remote_base.RemoteReceiverListener | ||||
| ) | ||||
|  | ||||
| CLIMATE_IR_SCHEMA = climate.CLIMATE_SCHEMA.extend({ | ||||
|     cv.GenerateID(CONF_TRANSMITTER_ID): cv.use_id(remote_transmitter.RemoteTransmitterComponent), | ||||
|     cv.Optional(CONF_SUPPORTS_COOL, default=True): cv.boolean, | ||||
|     cv.Optional(CONF_SUPPORTS_HEAT, default=True): cv.boolean, | ||||
|     cv.Optional(CONF_SENSOR): cv.use_id(sensor.Sensor), | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| CLIMATE_IR_SCHEMA = climate.CLIMATE_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(CONF_TRANSMITTER_ID): cv.use_id( | ||||
|             remote_transmitter.RemoteTransmitterComponent | ||||
|         ), | ||||
|         cv.Optional(CONF_SUPPORTS_COOL, default=True): cv.boolean, | ||||
|         cv.Optional(CONF_SUPPORTS_HEAT, default=True): cv.boolean, | ||||
|         cv.Optional(CONF_SENSOR): cv.use_id(sensor.Sensor), | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
| CLIMATE_IR_WITH_RECEIVER_SCHEMA = CLIMATE_IR_SCHEMA.extend({ | ||||
|     cv.Optional(CONF_RECEIVER_ID): cv.use_id(remote_receiver.RemoteReceiverComponent), | ||||
| }) | ||||
| CLIMATE_IR_WITH_RECEIVER_SCHEMA = CLIMATE_IR_SCHEMA.extend( | ||||
|     { | ||||
|         cv.Optional(CONF_RECEIVER_ID): cv.use_id( | ||||
|             remote_receiver.RemoteReceiverComponent | ||||
|         ), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
|   | ||||
| @@ -3,25 +3,37 @@ import esphome.config_validation as cv | ||||
| from esphome.components import climate_ir | ||||
| from esphome.const import CONF_ID | ||||
|  | ||||
| AUTO_LOAD = ['climate_ir'] | ||||
| AUTO_LOAD = ["climate_ir"] | ||||
|  | ||||
| climate_ir_lg_ns = cg.esphome_ns.namespace('climate_ir_lg') | ||||
| LgIrClimate = climate_ir_lg_ns.class_('LgIrClimate', climate_ir.ClimateIR) | ||||
| climate_ir_lg_ns = cg.esphome_ns.namespace("climate_ir_lg") | ||||
| LgIrClimate = climate_ir_lg_ns.class_("LgIrClimate", climate_ir.ClimateIR) | ||||
|  | ||||
| CONF_HEADER_HIGH = 'header_high' | ||||
| CONF_HEADER_LOW = 'header_low' | ||||
| CONF_BIT_HIGH = 'bit_high' | ||||
| CONF_BIT_ONE_LOW = 'bit_one_low' | ||||
| CONF_BIT_ZERO_LOW = 'bit_zero_low' | ||||
| CONF_HEADER_HIGH = "header_high" | ||||
| CONF_HEADER_LOW = "header_low" | ||||
| CONF_BIT_HIGH = "bit_high" | ||||
| CONF_BIT_ONE_LOW = "bit_one_low" | ||||
| CONF_BIT_ZERO_LOW = "bit_zero_low" | ||||
|  | ||||
| CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(LgIrClimate), | ||||
|     cv.Optional(CONF_HEADER_HIGH, default='8000us'): cv.positive_time_period_microseconds, | ||||
|     cv.Optional(CONF_HEADER_LOW, default='4000us'): cv.positive_time_period_microseconds, | ||||
|     cv.Optional(CONF_BIT_HIGH, default='600us'): cv.positive_time_period_microseconds, | ||||
|     cv.Optional(CONF_BIT_ONE_LOW, default='1600us'): cv.positive_time_period_microseconds, | ||||
|     cv.Optional(CONF_BIT_ZERO_LOW, default='550us'): cv.positive_time_period_microseconds, | ||||
| }) | ||||
| CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(LgIrClimate), | ||||
|         cv.Optional( | ||||
|             CONF_HEADER_HIGH, default="8000us" | ||||
|         ): cv.positive_time_period_microseconds, | ||||
|         cv.Optional( | ||||
|             CONF_HEADER_LOW, default="4000us" | ||||
|         ): cv.positive_time_period_microseconds, | ||||
|         cv.Optional( | ||||
|             CONF_BIT_HIGH, default="600us" | ||||
|         ): cv.positive_time_period_microseconds, | ||||
|         cv.Optional( | ||||
|             CONF_BIT_ONE_LOW, default="1600us" | ||||
|         ): cv.positive_time_period_microseconds, | ||||
|         cv.Optional( | ||||
|             CONF_BIT_ZERO_LOW, default="550us" | ||||
|         ): cv.positive_time_period_microseconds, | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -14,14 +14,14 @@ CONF_WHITE_INT = "white_int" | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.Required(CONF_ID): cv.declare_id(ColorStruct), | ||||
|         cv.Exclusive(CONF_RED, 'red'): cv.percentage, | ||||
|         cv.Exclusive(CONF_RED_INT, 'red'): cv.uint8_t, | ||||
|         cv.Exclusive(CONF_GREEN, 'green'): cv.percentage, | ||||
|         cv.Exclusive(CONF_GREEN_INT, 'green'): cv.uint8_t, | ||||
|         cv.Exclusive(CONF_BLUE, 'blue'): cv.percentage, | ||||
|         cv.Exclusive(CONF_BLUE_INT, 'blue'): cv.uint8_t, | ||||
|         cv.Exclusive(CONF_WHITE, 'white'): cv.percentage, | ||||
|         cv.Exclusive(CONF_WHITE_INT, 'white'): cv.uint8_t, | ||||
|         cv.Exclusive(CONF_RED, "red"): cv.percentage, | ||||
|         cv.Exclusive(CONF_RED_INT, "red"): cv.uint8_t, | ||||
|         cv.Exclusive(CONF_GREEN, "green"): cv.percentage, | ||||
|         cv.Exclusive(CONF_GREEN_INT, "green"): cv.uint8_t, | ||||
|         cv.Exclusive(CONF_BLUE, "blue"): cv.percentage, | ||||
|         cv.Exclusive(CONF_BLUE_INT, "blue"): cv.uint8_t, | ||||
|         cv.Exclusive(CONF_WHITE, "white"): cv.percentage, | ||||
|         cv.Exclusive(CONF_WHITE_INT, "white"): cv.uint8_t, | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
| @@ -29,31 +29,29 @@ CONFIG_SCHEMA = cv.Schema( | ||||
| def to_code(config): | ||||
|     r = 0 | ||||
|     if CONF_RED in config: | ||||
|         r = int(config[CONF_RED]*255) | ||||
|         r = int(config[CONF_RED] * 255) | ||||
|     elif CONF_RED_INT in config: | ||||
|         r = config[CONF_RED_INT] | ||||
|  | ||||
|     g = 0 | ||||
|     if CONF_GREEN in config: | ||||
|         g = int(config[CONF_GREEN]*255) | ||||
|         g = int(config[CONF_GREEN] * 255) | ||||
|     elif CONF_GREEN_INT in config: | ||||
|         g = config[CONF_GREEN_INT] | ||||
|  | ||||
|     b = 0 | ||||
|     if CONF_BLUE in config: | ||||
|         b = int(config[CONF_BLUE]*255) | ||||
|         b = int(config[CONF_BLUE] * 255) | ||||
|     elif CONF_BLUE_INT in config: | ||||
|         b = config[CONF_BLUE_INT] | ||||
|  | ||||
|     w = 0 | ||||
|     if CONF_WHITE in config: | ||||
|         w = int(config[CONF_WHITE]*255) | ||||
|         w = int(config[CONF_WHITE] * 255) | ||||
|     elif CONF_WHITE_INT in config: | ||||
|         w = config[CONF_WHITE_INT] | ||||
|  | ||||
|     cg.variable(config[CONF_ID], cg.StructInitializer( | ||||
|         ColorStruct, | ||||
|         ('r', r), | ||||
|         ('g', g), | ||||
|         ('b', b), | ||||
|         ('w', w))) | ||||
|     cg.variable( | ||||
|         config[CONF_ID], | ||||
|         cg.StructInitializer(ColorStruct, ("r", r), ("g", g), ("b", b), ("w", w)), | ||||
|     ) | ||||
|   | ||||
| @@ -3,15 +3,17 @@ import esphome.config_validation as cv | ||||
| from esphome.components import climate_ir | ||||
| from esphome.const import CONF_ID | ||||
|  | ||||
| AUTO_LOAD = ['climate_ir'] | ||||
| CODEOWNERS = ['@glmnet'] | ||||
| AUTO_LOAD = ["climate_ir"] | ||||
| CODEOWNERS = ["@glmnet"] | ||||
|  | ||||
| coolix_ns = cg.esphome_ns.namespace('coolix') | ||||
| CoolixClimate = coolix_ns.class_('CoolixClimate', climate_ir.ClimateIR) | ||||
| coolix_ns = cg.esphome_ns.namespace("coolix") | ||||
| CoolixClimate = coolix_ns.class_("CoolixClimate", climate_ir.ClimateIR) | ||||
|  | ||||
| CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(CoolixClimate), | ||||
| }) | ||||
| CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(CoolixClimate), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -3,54 +3,74 @@ import esphome.config_validation as cv | ||||
| from esphome import automation | ||||
| from esphome.automation import maybe_simple_id, Condition | ||||
| from esphome.components import mqtt | ||||
| from esphome.const import CONF_ID, CONF_INTERNAL, CONF_DEVICE_CLASS, CONF_STATE, \ | ||||
|     CONF_POSITION, CONF_TILT, CONF_STOP, CONF_MQTT_ID, CONF_NAME | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     CONF_INTERNAL, | ||||
|     CONF_DEVICE_CLASS, | ||||
|     CONF_STATE, | ||||
|     CONF_POSITION, | ||||
|     CONF_TILT, | ||||
|     CONF_STOP, | ||||
|     CONF_MQTT_ID, | ||||
|     CONF_NAME, | ||||
| ) | ||||
| from esphome.core import CORE, coroutine, coroutine_with_priority | ||||
|  | ||||
| IS_PLATFORM_COMPONENT = True | ||||
|  | ||||
| CODEOWNERS = ['@esphome/core'] | ||||
| CODEOWNERS = ["@esphome/core"] | ||||
| DEVICE_CLASSES = [ | ||||
|     '', 'awning', 'blind', 'curtain', 'damper', 'door', 'garage', | ||||
|     'gate', 'shade', 'shutter', 'window' | ||||
|     "", | ||||
|     "awning", | ||||
|     "blind", | ||||
|     "curtain", | ||||
|     "damper", | ||||
|     "door", | ||||
|     "garage", | ||||
|     "gate", | ||||
|     "shade", | ||||
|     "shutter", | ||||
|     "window", | ||||
| ] | ||||
|  | ||||
| cover_ns = cg.esphome_ns.namespace('cover') | ||||
| cover_ns = cg.esphome_ns.namespace("cover") | ||||
|  | ||||
| Cover = cover_ns.class_('Cover', cg.Nameable) | ||||
| Cover = cover_ns.class_("Cover", cg.Nameable) | ||||
|  | ||||
| COVER_OPEN = cover_ns.COVER_OPEN | ||||
| COVER_CLOSED = cover_ns.COVER_CLOSED | ||||
|  | ||||
| COVER_STATES = { | ||||
|     'OPEN': COVER_OPEN, | ||||
|     'CLOSED': COVER_CLOSED, | ||||
|     "OPEN": COVER_OPEN, | ||||
|     "CLOSED": COVER_CLOSED, | ||||
| } | ||||
| validate_cover_state = cv.enum(COVER_STATES, upper=True) | ||||
|  | ||||
| CoverOperation = cover_ns.enum('CoverOperation') | ||||
| CoverOperation = cover_ns.enum("CoverOperation") | ||||
| COVER_OPERATIONS = { | ||||
|     'IDLE': CoverOperation.COVER_OPERATION_IDLE, | ||||
|     'OPENING': CoverOperation.COVER_OPERATION_OPENING, | ||||
|     'CLOSING': CoverOperation.COVER_OPERATION_CLOSING, | ||||
|     "IDLE": CoverOperation.COVER_OPERATION_IDLE, | ||||
|     "OPENING": CoverOperation.COVER_OPERATION_OPENING, | ||||
|     "CLOSING": CoverOperation.COVER_OPERATION_CLOSING, | ||||
| } | ||||
| validate_cover_operation = cv.enum(COVER_OPERATIONS, upper=True) | ||||
|  | ||||
| # Actions | ||||
| OpenAction = cover_ns.class_('OpenAction', automation.Action) | ||||
| CloseAction = cover_ns.class_('CloseAction', automation.Action) | ||||
| StopAction = cover_ns.class_('StopAction', automation.Action) | ||||
| ControlAction = cover_ns.class_('ControlAction', automation.Action) | ||||
| CoverPublishAction = cover_ns.class_('CoverPublishAction', automation.Action) | ||||
| CoverIsOpenCondition = cover_ns.class_('CoverIsOpenCondition', Condition) | ||||
| CoverIsClosedCondition = cover_ns.class_('CoverIsClosedCondition', Condition) | ||||
| OpenAction = cover_ns.class_("OpenAction", automation.Action) | ||||
| CloseAction = cover_ns.class_("CloseAction", automation.Action) | ||||
| StopAction = cover_ns.class_("StopAction", automation.Action) | ||||
| ControlAction = cover_ns.class_("ControlAction", automation.Action) | ||||
| CoverPublishAction = cover_ns.class_("CoverPublishAction", automation.Action) | ||||
| CoverIsOpenCondition = cover_ns.class_("CoverIsOpenCondition", Condition) | ||||
| CoverIsClosedCondition = cover_ns.class_("CoverIsClosedCondition", Condition) | ||||
|  | ||||
| COVER_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(Cover), | ||||
|     cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTCoverComponent), | ||||
|     cv.Optional(CONF_DEVICE_CLASS): cv.one_of(*DEVICE_CLASSES, lower=True), | ||||
|     # TODO: MQTT topic options | ||||
| }) | ||||
| COVER_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(Cover), | ||||
|         cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTCoverComponent), | ||||
|         cv.Optional(CONF_DEVICE_CLASS): cv.one_of(*DEVICE_CLASSES, lower=True), | ||||
|         # TODO: MQTT topic options | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| @@ -74,39 +94,43 @@ def register_cover(var, config): | ||||
|     yield setup_cover_core_(var, config) | ||||
|  | ||||
|  | ||||
| COVER_ACTION_SCHEMA = maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.use_id(Cover), | ||||
| }) | ||||
| COVER_ACTION_SCHEMA = maybe_simple_id( | ||||
|     { | ||||
|         cv.Required(CONF_ID): cv.use_id(Cover), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @automation.register_action('cover.open', OpenAction, COVER_ACTION_SCHEMA) | ||||
| @automation.register_action("cover.open", OpenAction, COVER_ACTION_SCHEMA) | ||||
| def cover_open_to_code(config, action_id, template_arg, args): | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|  | ||||
|  | ||||
| @automation.register_action('cover.close', CloseAction, COVER_ACTION_SCHEMA) | ||||
| @automation.register_action("cover.close", CloseAction, COVER_ACTION_SCHEMA) | ||||
| def cover_close_to_code(config, action_id, template_arg, args): | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|  | ||||
|  | ||||
| @automation.register_action('cover.stop', StopAction, COVER_ACTION_SCHEMA) | ||||
| @automation.register_action("cover.stop", StopAction, COVER_ACTION_SCHEMA) | ||||
| def cover_stop_to_code(config, action_id, template_arg, args): | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|  | ||||
|  | ||||
| COVER_CONTROL_ACTION_SCHEMA = cv.Schema({ | ||||
|     cv.Required(CONF_ID): cv.use_id(Cover), | ||||
|     cv.Optional(CONF_STOP): cv.templatable(cv.boolean), | ||||
|     cv.Exclusive(CONF_STATE, 'pos'): cv.templatable(validate_cover_state), | ||||
|     cv.Exclusive(CONF_POSITION, 'pos'): cv.templatable(cv.percentage), | ||||
|     cv.Optional(CONF_TILT): cv.templatable(cv.percentage), | ||||
| }) | ||||
| COVER_CONTROL_ACTION_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.Required(CONF_ID): cv.use_id(Cover), | ||||
|         cv.Optional(CONF_STOP): cv.templatable(cv.boolean), | ||||
|         cv.Exclusive(CONF_STATE, "pos"): cv.templatable(validate_cover_state), | ||||
|         cv.Exclusive(CONF_POSITION, "pos"): cv.templatable(cv.percentage), | ||||
|         cv.Optional(CONF_TILT): cv.templatable(cv.percentage), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @automation.register_action('cover.control', ControlAction, COVER_CONTROL_ACTION_SCHEMA) | ||||
| @automation.register_action("cover.control", ControlAction, COVER_CONTROL_ACTION_SCHEMA) | ||||
| def cover_control_to_code(config, action_id, template_arg, args): | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, paren) | ||||
| @@ -127,5 +151,5 @@ def cover_control_to_code(config, action_id, template_arg, args): | ||||
|  | ||||
| @coroutine_with_priority(100.0) | ||||
| def to_code(config): | ||||
|     cg.add_define('USE_COVER') | ||||
|     cg.add_define("USE_COVER") | ||||
|     cg.add_global(cover_ns.using) | ||||
|   | ||||
| @@ -1,22 +1,45 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor, uart | ||||
| from esphome.const import CONF_CURRENT, CONF_ID, CONF_POWER, CONF_VOLTAGE, DEVICE_CLASS_CURRENT, \ | ||||
|     DEVICE_CLASS_POWER, DEVICE_CLASS_VOLTAGE, ICON_EMPTY, UNIT_VOLT, UNIT_AMPERE, UNIT_WATT | ||||
| from esphome.const import ( | ||||
|     CONF_CURRENT, | ||||
|     CONF_ID, | ||||
|     CONF_POWER, | ||||
|     CONF_VOLTAGE, | ||||
|     DEVICE_CLASS_CURRENT, | ||||
|     DEVICE_CLASS_POWER, | ||||
|     DEVICE_CLASS_VOLTAGE, | ||||
|     ICON_EMPTY, | ||||
|     UNIT_VOLT, | ||||
|     UNIT_AMPERE, | ||||
|     UNIT_WATT, | ||||
| ) | ||||
|  | ||||
| DEPENDENCIES = ['uart'] | ||||
| DEPENDENCIES = ["uart"] | ||||
|  | ||||
| cse7766_ns = cg.esphome_ns.namespace('cse7766') | ||||
| CSE7766Component = cse7766_ns.class_('CSE7766Component', cg.PollingComponent, uart.UARTDevice) | ||||
| cse7766_ns = cg.esphome_ns.namespace("cse7766") | ||||
| CSE7766Component = cse7766_ns.class_( | ||||
|     "CSE7766Component", cg.PollingComponent, uart.UARTDevice | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(CSE7766Component), | ||||
|  | ||||
|     cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(UNIT_VOLT, ICON_EMPTY, 1, DEVICE_CLASS_VOLTAGE), | ||||
|     cv.Optional(CONF_CURRENT): sensor.sensor_schema(UNIT_AMPERE, ICON_EMPTY, 2, | ||||
|                                                     DEVICE_CLASS_CURRENT), | ||||
|     cv.Optional(CONF_POWER): sensor.sensor_schema(UNIT_WATT, ICON_EMPTY, 1, DEVICE_CLASS_POWER), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(uart.UART_DEVICE_SCHEMA) | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(CSE7766Component), | ||||
|             cv.Optional(CONF_VOLTAGE): sensor.sensor_schema( | ||||
|                 UNIT_VOLT, ICON_EMPTY, 1, DEVICE_CLASS_VOLTAGE | ||||
|             ), | ||||
|             cv.Optional(CONF_CURRENT): sensor.sensor_schema( | ||||
|                 UNIT_AMPERE, ICON_EMPTY, 2, DEVICE_CLASS_CURRENT | ||||
|             ), | ||||
|             cv.Optional(CONF_POWER): sensor.sensor_schema( | ||||
|                 UNIT_WATT, ICON_EMPTY, 1, DEVICE_CLASS_POWER | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
|     .extend(uart.UART_DEVICE_SCHEMA) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,21 +1,35 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor, voltage_sampler | ||||
| from esphome.const import CONF_SENSOR, CONF_ID, DEVICE_CLASS_CURRENT, ICON_EMPTY, UNIT_AMPERE | ||||
| from esphome.const import ( | ||||
|     CONF_SENSOR, | ||||
|     CONF_ID, | ||||
|     DEVICE_CLASS_CURRENT, | ||||
|     ICON_EMPTY, | ||||
|     UNIT_AMPERE, | ||||
| ) | ||||
|  | ||||
| AUTO_LOAD = ['voltage_sampler'] | ||||
| CODEOWNERS = ['@jesserockz'] | ||||
| AUTO_LOAD = ["voltage_sampler"] | ||||
| CODEOWNERS = ["@jesserockz"] | ||||
|  | ||||
| CONF_SAMPLE_DURATION = 'sample_duration' | ||||
| CONF_SAMPLE_DURATION = "sample_duration" | ||||
|  | ||||
| ct_clamp_ns = cg.esphome_ns.namespace('ct_clamp') | ||||
| CTClampSensor = ct_clamp_ns.class_('CTClampSensor', sensor.Sensor, cg.PollingComponent) | ||||
| ct_clamp_ns = cg.esphome_ns.namespace("ct_clamp") | ||||
| CTClampSensor = ct_clamp_ns.class_("CTClampSensor", sensor.Sensor, cg.PollingComponent) | ||||
|  | ||||
| CONFIG_SCHEMA = sensor.sensor_schema(UNIT_AMPERE, ICON_EMPTY, 2, DEVICE_CLASS_CURRENT).extend({ | ||||
|     cv.GenerateID(): cv.declare_id(CTClampSensor), | ||||
|     cv.Required(CONF_SENSOR): cv.use_id(voltage_sampler.VoltageSampler), | ||||
|     cv.Optional(CONF_SAMPLE_DURATION, default='200ms'): cv.positive_time_period_milliseconds, | ||||
| }).extend(cv.polling_component_schema('60s')) | ||||
| CONFIG_SCHEMA = ( | ||||
|     sensor.sensor_schema(UNIT_AMPERE, ICON_EMPTY, 2, DEVICE_CLASS_CURRENT) | ||||
|     .extend( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(CTClampSensor), | ||||
|             cv.Required(CONF_SENSOR): cv.use_id(voltage_sampler.VoltageSampler), | ||||
|             cv.Optional( | ||||
|                 CONF_SAMPLE_DURATION, default="200ms" | ||||
|             ): cv.positive_time_period_milliseconds, | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,3 +1,3 @@ | ||||
| import esphome.codegen as cg | ||||
|  | ||||
| custom_ns = cg.esphome_ns.namespace('custom') | ||||
| custom_ns = cg.esphome_ns.namespace("custom") | ||||
|   | ||||
| @@ -4,18 +4,25 @@ from esphome.components import binary_sensor | ||||
| from esphome.const import CONF_BINARY_SENSORS, CONF_ID, CONF_LAMBDA | ||||
| from .. import custom_ns | ||||
|  | ||||
| CustomBinarySensorConstructor = custom_ns.class_('CustomBinarySensorConstructor') | ||||
| CustomBinarySensorConstructor = custom_ns.class_("CustomBinarySensorConstructor") | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(CustomBinarySensorConstructor), | ||||
|     cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|     cv.Required(CONF_BINARY_SENSORS): cv.ensure_list(binary_sensor.BINARY_SENSOR_SCHEMA), | ||||
| }) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(CustomBinarySensorConstructor), | ||||
|         cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|         cv.Required(CONF_BINARY_SENSORS): cv.ensure_list( | ||||
|             binary_sensor.BINARY_SENSOR_SCHEMA | ||||
|         ), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     template_ = yield cg.process_lambda( | ||||
|         config[CONF_LAMBDA], [], return_type=cg.std_vector.template(binary_sensor.BinarySensorPtr)) | ||||
|         config[CONF_LAMBDA], | ||||
|         [], | ||||
|         return_type=cg.std_vector.template(binary_sensor.BinarySensorPtr), | ||||
|     ) | ||||
|  | ||||
|     rhs = CustomBinarySensorConstructor(template_) | ||||
|     custom = cg.variable(config[CONF_ID], rhs) | ||||
|   | ||||
| @@ -4,20 +4,24 @@ from esphome.components import climate | ||||
| from esphome.const import CONF_ID, CONF_LAMBDA | ||||
| from .. import custom_ns | ||||
|  | ||||
| CustomClimateConstructor = custom_ns.class_('CustomClimateConstructor') | ||||
| CONF_CLIMATES = 'climates' | ||||
| CustomClimateConstructor = custom_ns.class_("CustomClimateConstructor") | ||||
| CONF_CLIMATES = "climates" | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(CustomClimateConstructor), | ||||
|     cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|     cv.Required(CONF_CLIMATES): cv.ensure_list(climate.CLIMATE_SCHEMA), | ||||
| }) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(CustomClimateConstructor), | ||||
|         cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|         cv.Required(CONF_CLIMATES): cv.ensure_list(climate.CLIMATE_SCHEMA), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     template_ = yield cg.process_lambda( | ||||
|         config[CONF_LAMBDA], [], | ||||
|         return_type=cg.std_vector.template(climate.Climate.operator('ptr'))) | ||||
|         config[CONF_LAMBDA], | ||||
|         [], | ||||
|         return_type=cg.std_vector.template(climate.Climate.operator("ptr")), | ||||
|     ) | ||||
|  | ||||
|     rhs = CustomClimateConstructor(template_) | ||||
|     custom = cg.variable(config[CONF_ID], rhs) | ||||
|   | ||||
| @@ -4,20 +4,24 @@ from esphome.components import cover | ||||
| from esphome.const import CONF_ID, CONF_LAMBDA | ||||
| from .. import custom_ns | ||||
|  | ||||
| CustomCoverConstructor = custom_ns.class_('CustomCoverConstructor') | ||||
| CONF_COVERS = 'covers' | ||||
| CustomCoverConstructor = custom_ns.class_("CustomCoverConstructor") | ||||
| CONF_COVERS = "covers" | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(CustomCoverConstructor), | ||||
|     cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|     cv.Required(CONF_COVERS): cv.ensure_list(cover.COVER_SCHEMA), | ||||
| }) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(CustomCoverConstructor), | ||||
|         cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|         cv.Required(CONF_COVERS): cv.ensure_list(cover.COVER_SCHEMA), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     template_ = yield cg.process_lambda( | ||||
|         config[CONF_LAMBDA], [], | ||||
|         return_type=cg.std_vector.template(cover.Cover.operator('ptr'))) | ||||
|         config[CONF_LAMBDA], | ||||
|         [], | ||||
|         return_type=cg.std_vector.template(cover.Cover.operator("ptr")), | ||||
|     ) | ||||
|  | ||||
|     rhs = CustomCoverConstructor(template_) | ||||
|     custom = cg.variable(config[CONF_ID], rhs) | ||||
|   | ||||
| @@ -4,20 +4,24 @@ from esphome.components import light | ||||
| from esphome.const import CONF_ID, CONF_LAMBDA | ||||
| from .. import custom_ns | ||||
|  | ||||
| CustomLightOutputConstructor = custom_ns.class_('CustomLightOutputConstructor') | ||||
| CONF_LIGHTS = 'lights' | ||||
| CustomLightOutputConstructor = custom_ns.class_("CustomLightOutputConstructor") | ||||
| CONF_LIGHTS = "lights" | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(CustomLightOutputConstructor), | ||||
|     cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|     cv.Required(CONF_LIGHTS): cv.ensure_list(light.ADDRESSABLE_LIGHT_SCHEMA), | ||||
| }) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(CustomLightOutputConstructor), | ||||
|         cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|         cv.Required(CONF_LIGHTS): cv.ensure_list(light.ADDRESSABLE_LIGHT_SCHEMA), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     template_ = yield cg.process_lambda( | ||||
|         config[CONF_LAMBDA], [], | ||||
|         return_type=cg.std_vector.template(light.LightOutput.operator('ptr'))) | ||||
|         config[CONF_LAMBDA], | ||||
|         [], | ||||
|         return_type=cg.std_vector.template(light.LightOutput.operator("ptr")), | ||||
|     ) | ||||
|  | ||||
|     rhs = CustomLightOutputConstructor(template_) | ||||
|     custom = cg.variable(config[CONF_ID], rhs) | ||||
|   | ||||
| @@ -4,41 +4,55 @@ from esphome.components import output | ||||
| from esphome.const import CONF_ID, CONF_LAMBDA, CONF_OUTPUTS, CONF_TYPE, CONF_BINARY | ||||
| from .. import custom_ns | ||||
|  | ||||
| CustomBinaryOutputConstructor = custom_ns.class_('CustomBinaryOutputConstructor') | ||||
| CustomFloatOutputConstructor = custom_ns.class_('CustomFloatOutputConstructor') | ||||
| CustomBinaryOutputConstructor = custom_ns.class_("CustomBinaryOutputConstructor") | ||||
| CustomFloatOutputConstructor = custom_ns.class_("CustomFloatOutputConstructor") | ||||
|  | ||||
| CONF_FLOAT = 'float' | ||||
| CONF_FLOAT = "float" | ||||
|  | ||||
| CONFIG_SCHEMA = cv.typed_schema({ | ||||
|     CONF_BINARY: cv.Schema({ | ||||
|         cv.GenerateID(): cv.declare_id(CustomBinaryOutputConstructor), | ||||
|         cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|         cv.Required(CONF_OUTPUTS): | ||||
|             cv.ensure_list(output.BINARY_OUTPUT_SCHEMA.extend({ | ||||
|                 cv.GenerateID(): cv.declare_id(output.BinaryOutput), | ||||
|             })), | ||||
|     }), | ||||
|     CONF_FLOAT: cv.Schema({ | ||||
|         cv.GenerateID(): cv.declare_id(CustomFloatOutputConstructor), | ||||
|         cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|         cv.Required(CONF_OUTPUTS): | ||||
|             cv.ensure_list(output.FLOAT_OUTPUT_SCHEMA.extend({ | ||||
|                 cv.GenerateID(): cv.declare_id(output.FloatOutput), | ||||
|             })), | ||||
|     }) | ||||
| }, lower=True) | ||||
| CONFIG_SCHEMA = cv.typed_schema( | ||||
|     { | ||||
|         CONF_BINARY: cv.Schema( | ||||
|             { | ||||
|                 cv.GenerateID(): cv.declare_id(CustomBinaryOutputConstructor), | ||||
|                 cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|                 cv.Required(CONF_OUTPUTS): cv.ensure_list( | ||||
|                     output.BINARY_OUTPUT_SCHEMA.extend( | ||||
|                         { | ||||
|                             cv.GenerateID(): cv.declare_id(output.BinaryOutput), | ||||
|                         } | ||||
|                     ) | ||||
|                 ), | ||||
|             } | ||||
|         ), | ||||
|         CONF_FLOAT: cv.Schema( | ||||
|             { | ||||
|                 cv.GenerateID(): cv.declare_id(CustomFloatOutputConstructor), | ||||
|                 cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|                 cv.Required(CONF_OUTPUTS): cv.ensure_list( | ||||
|                     output.FLOAT_OUTPUT_SCHEMA.extend( | ||||
|                         { | ||||
|                             cv.GenerateID(): cv.declare_id(output.FloatOutput), | ||||
|                         } | ||||
|                     ) | ||||
|                 ), | ||||
|             } | ||||
|         ), | ||||
|     }, | ||||
|     lower=True, | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     type = config[CONF_TYPE] | ||||
|     if type == 'binary': | ||||
|     if type == "binary": | ||||
|         ret_type = output.BinaryOutputPtr | ||||
|         klass = CustomBinaryOutputConstructor | ||||
|     else: | ||||
|         ret_type = output.FloatOutputPtr | ||||
|         klass = CustomFloatOutputConstructor | ||||
|     template_ = yield cg.process_lambda(config[CONF_LAMBDA], [], | ||||
|                                         return_type=cg.std_vector.template(ret_type)) | ||||
|     template_ = yield cg.process_lambda( | ||||
|         config[CONF_LAMBDA], [], return_type=cg.std_vector.template(ret_type) | ||||
|     ) | ||||
|  | ||||
|     rhs = klass(template_) | ||||
|     custom = cg.variable(config[CONF_ID], rhs) | ||||
|   | ||||
| @@ -4,18 +4,21 @@ from esphome.components import sensor | ||||
| from esphome.const import CONF_ID, CONF_LAMBDA, CONF_SENSORS | ||||
| from .. import custom_ns | ||||
|  | ||||
| CustomSensorConstructor = custom_ns.class_('CustomSensorConstructor') | ||||
| CustomSensorConstructor = custom_ns.class_("CustomSensorConstructor") | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(CustomSensorConstructor), | ||||
|     cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|     cv.Required(CONF_SENSORS): cv.ensure_list(sensor.SENSOR_SCHEMA), | ||||
| }) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(CustomSensorConstructor), | ||||
|         cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|         cv.Required(CONF_SENSORS): cv.ensure_list(sensor.SENSOR_SCHEMA), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     template_ = yield cg.process_lambda( | ||||
|         config[CONF_LAMBDA], [], return_type=cg.std_vector.template(sensor.SensorPtr)) | ||||
|         config[CONF_LAMBDA], [], return_type=cg.std_vector.template(sensor.SensorPtr) | ||||
|     ) | ||||
|  | ||||
|     rhs = CustomSensorConstructor(template_) | ||||
|     var = cg.variable(config[CONF_ID], rhs) | ||||
|   | ||||
| @@ -4,21 +4,27 @@ from esphome.components import switch | ||||
| from esphome.const import CONF_ID, CONF_LAMBDA, CONF_SWITCHES | ||||
| from .. import custom_ns | ||||
|  | ||||
| CustomSwitchConstructor = custom_ns.class_('CustomSwitchConstructor') | ||||
| CustomSwitchConstructor = custom_ns.class_("CustomSwitchConstructor") | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(CustomSwitchConstructor), | ||||
|     cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|     cv.Required(CONF_SWITCHES): | ||||
|         cv.ensure_list(switch.SWITCH_SCHEMA.extend({ | ||||
|             cv.GenerateID(): cv.declare_id(switch.Switch), | ||||
|         })), | ||||
| }) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(CustomSwitchConstructor), | ||||
|         cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|         cv.Required(CONF_SWITCHES): cv.ensure_list( | ||||
|             switch.SWITCH_SCHEMA.extend( | ||||
|                 { | ||||
|                     cv.GenerateID(): cv.declare_id(switch.Switch), | ||||
|                 } | ||||
|             ) | ||||
|         ), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     template_ = yield cg.process_lambda( | ||||
|         config[CONF_LAMBDA], [], return_type=cg.std_vector.template(switch.SwitchPtr)) | ||||
|         config[CONF_LAMBDA], [], return_type=cg.std_vector.template(switch.SwitchPtr) | ||||
|     ) | ||||
|  | ||||
|     rhs = CustomSwitchConstructor(template_) | ||||
|     var = cg.variable(config[CONF_ID], rhs) | ||||
|   | ||||
| @@ -4,21 +4,29 @@ from esphome.components import text_sensor | ||||
| from esphome.const import CONF_ID, CONF_LAMBDA, CONF_TEXT_SENSORS | ||||
| from .. import custom_ns | ||||
|  | ||||
| CustomTextSensorConstructor = custom_ns.class_('CustomTextSensorConstructor') | ||||
| CustomTextSensorConstructor = custom_ns.class_("CustomTextSensorConstructor") | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(CustomTextSensorConstructor), | ||||
|     cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|     cv.Required(CONF_TEXT_SENSORS): | ||||
|         cv.ensure_list(text_sensor.TEXT_SENSOR_SCHEMA.extend({ | ||||
|             cv.GenerateID(): cv.declare_id(text_sensor.TextSensor), | ||||
|         })), | ||||
| }) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(CustomTextSensorConstructor), | ||||
|         cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|         cv.Required(CONF_TEXT_SENSORS): cv.ensure_list( | ||||
|             text_sensor.TEXT_SENSOR_SCHEMA.extend( | ||||
|                 { | ||||
|                     cv.GenerateID(): cv.declare_id(text_sensor.TextSensor), | ||||
|                 } | ||||
|             ) | ||||
|         ), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     template_ = yield cg.process_lambda( | ||||
|         config[CONF_LAMBDA], [], return_type=cg.std_vector.template(text_sensor.TextSensorPtr)) | ||||
|         config[CONF_LAMBDA], | ||||
|         [], | ||||
|         return_type=cg.std_vector.template(text_sensor.TextSensorPtr), | ||||
|     ) | ||||
|  | ||||
|     rhs = CustomTextSensorConstructor(template_) | ||||
|     var = cg.variable(config[CONF_ID], rhs) | ||||
|   | ||||
| @@ -2,22 +2,27 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.const import CONF_COMPONENTS, CONF_ID, CONF_LAMBDA | ||||
|  | ||||
| custom_component_ns = cg.esphome_ns.namespace('custom_component') | ||||
| CustomComponentConstructor = custom_component_ns.class_('CustomComponentConstructor') | ||||
| custom_component_ns = cg.esphome_ns.namespace("custom_component") | ||||
| CustomComponentConstructor = custom_component_ns.class_("CustomComponentConstructor") | ||||
|  | ||||
| MULTI_CONF = True | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(CustomComponentConstructor), | ||||
|     cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|     cv.Optional(CONF_COMPONENTS): cv.ensure_list(cv.Schema({ | ||||
|         cv.GenerateID(): cv.declare_id(cg.Component) | ||||
|     }).extend(cv.COMPONENT_SCHEMA)), | ||||
| }) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(CustomComponentConstructor), | ||||
|         cv.Required(CONF_LAMBDA): cv.returning_lambda, | ||||
|         cv.Optional(CONF_COMPONENTS): cv.ensure_list( | ||||
|             cv.Schema({cv.GenerateID(): cv.declare_id(cg.Component)}).extend( | ||||
|                 cv.COMPONENT_SCHEMA | ||||
|             ) | ||||
|         ), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     template_ = yield cg.process_lambda( | ||||
|         config[CONF_LAMBDA], [], return_type=cg.std_vector.template(cg.ComponentPtr)) | ||||
|         config[CONF_LAMBDA], [], return_type=cg.std_vector.template(cg.ComponentPtr) | ||||
|     ) | ||||
|  | ||||
|     rhs = CustomComponentConstructor(template_) | ||||
|     var = cg.variable(config[CONF_ID], rhs) | ||||
|   | ||||
| @@ -1,22 +1,29 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import light, output | ||||
| from esphome.const import CONF_OUTPUT_ID, CONF_COLD_WHITE, CONF_WARM_WHITE, \ | ||||
|     CONF_COLD_WHITE_COLOR_TEMPERATURE, CONF_WARM_WHITE_COLOR_TEMPERATURE | ||||
| from esphome.const import ( | ||||
|     CONF_OUTPUT_ID, | ||||
|     CONF_COLD_WHITE, | ||||
|     CONF_WARM_WHITE, | ||||
|     CONF_COLD_WHITE_COLOR_TEMPERATURE, | ||||
|     CONF_WARM_WHITE_COLOR_TEMPERATURE, | ||||
| ) | ||||
|  | ||||
| cwww_ns = cg.esphome_ns.namespace('cwww') | ||||
| CWWWLightOutput = cwww_ns.class_('CWWWLightOutput', light.LightOutput) | ||||
| cwww_ns = cg.esphome_ns.namespace("cwww") | ||||
| CWWWLightOutput = cwww_ns.class_("CWWWLightOutput", light.LightOutput) | ||||
|  | ||||
| CONF_CONSTANT_BRIGHTNESS = 'constant_brightness' | ||||
| CONF_CONSTANT_BRIGHTNESS = "constant_brightness" | ||||
|  | ||||
| CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend({ | ||||
|     cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(CWWWLightOutput), | ||||
|     cv.Required(CONF_COLD_WHITE): cv.use_id(output.FloatOutput), | ||||
|     cv.Required(CONF_WARM_WHITE): cv.use_id(output.FloatOutput), | ||||
|     cv.Required(CONF_COLD_WHITE_COLOR_TEMPERATURE): cv.color_temperature, | ||||
|     cv.Required(CONF_WARM_WHITE_COLOR_TEMPERATURE): cv.color_temperature, | ||||
|     cv.Optional(CONF_CONSTANT_BRIGHTNESS, default=False): cv.boolean, | ||||
| }) | ||||
| CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(CWWWLightOutput), | ||||
|         cv.Required(CONF_COLD_WHITE): cv.use_id(output.FloatOutput), | ||||
|         cv.Required(CONF_WARM_WHITE): cv.use_id(output.FloatOutput), | ||||
|         cv.Required(CONF_COLD_WHITE_COLOR_TEMPERATURE): cv.color_temperature, | ||||
|         cv.Required(CONF_WARM_WHITE_COLOR_TEMPERATURE): cv.color_temperature, | ||||
|         cv.Optional(CONF_CONSTANT_BRIGHTNESS, default=False): cv.boolean, | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -3,14 +3,16 @@ import esphome.config_validation as cv | ||||
| from esphome.components import climate_ir | ||||
| from esphome.const import CONF_ID | ||||
|  | ||||
| AUTO_LOAD = ['climate_ir'] | ||||
| AUTO_LOAD = ["climate_ir"] | ||||
|  | ||||
| daikin_ns = cg.esphome_ns.namespace('daikin') | ||||
| DaikinClimate = daikin_ns.class_('DaikinClimate', climate_ir.ClimateIR) | ||||
| daikin_ns = cg.esphome_ns.namespace("daikin") | ||||
| DaikinClimate = daikin_ns.class_("DaikinClimate", climate_ir.ClimateIR) | ||||
|  | ||||
| CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(DaikinClimate), | ||||
| }) | ||||
| CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(DaikinClimate), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -4,18 +4,20 @@ from esphome import pins | ||||
| from esphome.const import CONF_ID, CONF_PIN | ||||
|  | ||||
| MULTI_CONF = True | ||||
| AUTO_LOAD = ['sensor'] | ||||
| AUTO_LOAD = ["sensor"] | ||||
|  | ||||
| CONF_ONE_WIRE_ID = 'one_wire_id' | ||||
| dallas_ns = cg.esphome_ns.namespace('dallas') | ||||
| DallasComponent = dallas_ns.class_('DallasComponent', cg.PollingComponent) | ||||
| ESPOneWire = dallas_ns.class_('ESPOneWire') | ||||
| CONF_ONE_WIRE_ID = "one_wire_id" | ||||
| dallas_ns = cg.esphome_ns.namespace("dallas") | ||||
| DallasComponent = dallas_ns.class_("DallasComponent", cg.PollingComponent) | ||||
| ESPOneWire = dallas_ns.class_("ESPOneWire") | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(DallasComponent), | ||||
|     cv.GenerateID(CONF_ONE_WIRE_ID): cv.declare_id(ESPOneWire), | ||||
|     cv.Required(CONF_PIN): pins.gpio_input_pin_schema, | ||||
| }).extend(cv.polling_component_schema('60s')) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(DallasComponent), | ||||
|         cv.GenerateID(CONF_ONE_WIRE_ID): cv.declare_id(ESPOneWire), | ||||
|         cv.Required(CONF_PIN): pins.gpio_input_pin_schema, | ||||
|     } | ||||
| ).extend(cv.polling_component_schema("60s")) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,22 +1,32 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor | ||||
| from esphome.const import CONF_ADDRESS, CONF_DALLAS_ID, CONF_INDEX, CONF_RESOLUTION, \ | ||||
|     DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, UNIT_CELSIUS, CONF_ID | ||||
| from esphome.const import ( | ||||
|     CONF_ADDRESS, | ||||
|     CONF_DALLAS_ID, | ||||
|     CONF_INDEX, | ||||
|     CONF_RESOLUTION, | ||||
|     DEVICE_CLASS_TEMPERATURE, | ||||
|     ICON_EMPTY, | ||||
|     UNIT_CELSIUS, | ||||
|     CONF_ID, | ||||
| ) | ||||
| from . import DallasComponent, dallas_ns | ||||
|  | ||||
| DallasTemperatureSensor = dallas_ns.class_('DallasTemperatureSensor', sensor.Sensor) | ||||
| DallasTemperatureSensor = dallas_ns.class_("DallasTemperatureSensor", sensor.Sensor) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All(sensor.sensor_schema( | ||||
|     UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE | ||||
| ).extend({ | ||||
|     cv.GenerateID(): cv.declare_id(DallasTemperatureSensor), | ||||
|     cv.GenerateID(CONF_DALLAS_ID): cv.use_id(DallasComponent), | ||||
|  | ||||
|     cv.Optional(CONF_ADDRESS): cv.hex_int, | ||||
|     cv.Optional(CONF_INDEX): cv.positive_int, | ||||
|     cv.Optional(CONF_RESOLUTION, default=12): cv.int_range(min=9, max=12), | ||||
| }), cv.has_exactly_one_key(CONF_ADDRESS, CONF_INDEX)) | ||||
| CONFIG_SCHEMA = cv.All( | ||||
|     sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE).extend( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(DallasTemperatureSensor), | ||||
|             cv.GenerateID(CONF_DALLAS_ID): cv.use_id(DallasComponent), | ||||
|             cv.Optional(CONF_ADDRESS): cv.hex_int, | ||||
|             cv.Optional(CONF_INDEX): cv.positive_int, | ||||
|             cv.Optional(CONF_RESOLUTION, default=12): cv.int_range(min=9, max=12), | ||||
|         } | ||||
|     ), | ||||
|     cv.has_exactly_one_key(CONF_ADDRESS, CONF_INDEX), | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -2,14 +2,16 @@ import esphome.config_validation as cv | ||||
| import esphome.codegen as cg | ||||
| from esphome.const import CONF_ID | ||||
|  | ||||
| CODEOWNERS = ['@OttoWinter'] | ||||
| DEPENDENCIES = ['logger'] | ||||
| CODEOWNERS = ["@OttoWinter"] | ||||
| DEPENDENCIES = ["logger"] | ||||
|  | ||||
| debug_ns = cg.esphome_ns.namespace('debug') | ||||
| DebugComponent = debug_ns.class_('DebugComponent', cg.Component) | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(DebugComponent), | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| debug_ns = cg.esphome_ns.namespace("debug") | ||||
| DebugComponent = debug_ns.class_("DebugComponent", cg.Component) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(DebugComponent), | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,58 +1,81 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins, automation | ||||
| from esphome.const import CONF_ID, CONF_MODE, CONF_NUMBER, CONF_PINS, CONF_RUN_CYCLES, \ | ||||
|     CONF_RUN_DURATION, CONF_SLEEP_DURATION, CONF_WAKEUP_PIN | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     CONF_MODE, | ||||
|     CONF_NUMBER, | ||||
|     CONF_PINS, | ||||
|     CONF_RUN_CYCLES, | ||||
|     CONF_RUN_DURATION, | ||||
|     CONF_SLEEP_DURATION, | ||||
|     CONF_WAKEUP_PIN, | ||||
| ) | ||||
|  | ||||
|  | ||||
| def validate_pin_number(value): | ||||
|     valid_pins = [0, 2, 4, 12, 13, 14, 15, 25, 26, 27, 32, 33, 34, 35, 36, 37, 38, 39] | ||||
|     if value[CONF_NUMBER] not in valid_pins: | ||||
|         raise cv.Invalid("Only pins {} support wakeup" | ||||
|                          "".format(', '.join(str(x) for x in valid_pins))) | ||||
|         raise cv.Invalid( | ||||
|             "Only pins {} support wakeup" | ||||
|             "".format(", ".join(str(x) for x in valid_pins)) | ||||
|         ) | ||||
|     return value | ||||
|  | ||||
|  | ||||
| deep_sleep_ns = cg.esphome_ns.namespace('deep_sleep') | ||||
| DeepSleepComponent = deep_sleep_ns.class_('DeepSleepComponent', cg.Component) | ||||
| EnterDeepSleepAction = deep_sleep_ns.class_('EnterDeepSleepAction', automation.Action) | ||||
| PreventDeepSleepAction = deep_sleep_ns.class_('PreventDeepSleepAction', automation.Action) | ||||
| deep_sleep_ns = cg.esphome_ns.namespace("deep_sleep") | ||||
| DeepSleepComponent = deep_sleep_ns.class_("DeepSleepComponent", cg.Component) | ||||
| EnterDeepSleepAction = deep_sleep_ns.class_("EnterDeepSleepAction", automation.Action) | ||||
| PreventDeepSleepAction = deep_sleep_ns.class_( | ||||
|     "PreventDeepSleepAction", automation.Action | ||||
| ) | ||||
|  | ||||
| WakeupPinMode = deep_sleep_ns.enum('WakeupPinMode') | ||||
| WakeupPinMode = deep_sleep_ns.enum("WakeupPinMode") | ||||
| WAKEUP_PIN_MODES = { | ||||
|     'IGNORE': WakeupPinMode.WAKEUP_PIN_MODE_IGNORE, | ||||
|     'KEEP_AWAKE': WakeupPinMode.WAKEUP_PIN_MODE_KEEP_AWAKE, | ||||
|     'INVERT_WAKEUP': WakeupPinMode.WAKEUP_PIN_MODE_INVERT_WAKEUP, | ||||
|     "IGNORE": WakeupPinMode.WAKEUP_PIN_MODE_IGNORE, | ||||
|     "KEEP_AWAKE": WakeupPinMode.WAKEUP_PIN_MODE_KEEP_AWAKE, | ||||
|     "INVERT_WAKEUP": WakeupPinMode.WAKEUP_PIN_MODE_INVERT_WAKEUP, | ||||
| } | ||||
|  | ||||
| esp_sleep_ext1_wakeup_mode_t = cg.global_ns.enum('esp_sleep_ext1_wakeup_mode_t') | ||||
| Ext1Wakeup = deep_sleep_ns.struct('Ext1Wakeup') | ||||
| esp_sleep_ext1_wakeup_mode_t = cg.global_ns.enum("esp_sleep_ext1_wakeup_mode_t") | ||||
| Ext1Wakeup = deep_sleep_ns.struct("Ext1Wakeup") | ||||
| EXT1_WAKEUP_MODES = { | ||||
|     'ALL_LOW': esp_sleep_ext1_wakeup_mode_t.ESP_EXT1_WAKEUP_ALL_LOW, | ||||
|     'ANY_HIGH': esp_sleep_ext1_wakeup_mode_t.ESP_EXT1_WAKEUP_ANY_HIGH, | ||||
|     "ALL_LOW": esp_sleep_ext1_wakeup_mode_t.ESP_EXT1_WAKEUP_ALL_LOW, | ||||
|     "ANY_HIGH": esp_sleep_ext1_wakeup_mode_t.ESP_EXT1_WAKEUP_ANY_HIGH, | ||||
| } | ||||
|  | ||||
| CONF_WAKEUP_PIN_MODE = 'wakeup_pin_mode' | ||||
| CONF_ESP32_EXT1_WAKEUP = 'esp32_ext1_wakeup' | ||||
| CONF_WAKEUP_PIN_MODE = "wakeup_pin_mode" | ||||
| CONF_ESP32_EXT1_WAKEUP = "esp32_ext1_wakeup" | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(DeepSleepComponent), | ||||
|     cv.Optional(CONF_RUN_DURATION): cv.positive_time_period_milliseconds, | ||||
|  | ||||
|     cv.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds, | ||||
|     cv.Optional(CONF_WAKEUP_PIN): cv.All(cv.only_on_esp32, pins.internal_gpio_input_pin_schema, | ||||
|                                          validate_pin_number), | ||||
|     cv.Optional(CONF_WAKEUP_PIN_MODE): cv.All(cv.only_on_esp32, | ||||
|                                               cv.enum(WAKEUP_PIN_MODES), upper=True), | ||||
|     cv.Optional(CONF_ESP32_EXT1_WAKEUP): cv.All(cv.only_on_esp32, cv.Schema({ | ||||
|         cv.Required(CONF_PINS): cv.ensure_list(pins.shorthand_input_pin, validate_pin_number), | ||||
|         cv.Required(CONF_MODE): cv.enum(EXT1_WAKEUP_MODES, upper=True), | ||||
|     })), | ||||
|  | ||||
|     cv.Optional(CONF_RUN_CYCLES): cv.invalid("The run_cycles option has been removed in 1.11.0 as " | ||||
|                                              "it was essentially the same as a run_duration of 0s." | ||||
|                                              "Please use run_duration now.") | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(DeepSleepComponent), | ||||
|         cv.Optional(CONF_RUN_DURATION): cv.positive_time_period_milliseconds, | ||||
|         cv.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds, | ||||
|         cv.Optional(CONF_WAKEUP_PIN): cv.All( | ||||
|             cv.only_on_esp32, pins.internal_gpio_input_pin_schema, validate_pin_number | ||||
|         ), | ||||
|         cv.Optional(CONF_WAKEUP_PIN_MODE): cv.All( | ||||
|             cv.only_on_esp32, cv.enum(WAKEUP_PIN_MODES), upper=True | ||||
|         ), | ||||
|         cv.Optional(CONF_ESP32_EXT1_WAKEUP): cv.All( | ||||
|             cv.only_on_esp32, | ||||
|             cv.Schema( | ||||
|                 { | ||||
|                     cv.Required(CONF_PINS): cv.ensure_list( | ||||
|                         pins.shorthand_input_pin, validate_pin_number | ||||
|                     ), | ||||
|                     cv.Required(CONF_MODE): cv.enum(EXT1_WAKEUP_MODES, upper=True), | ||||
|                 } | ||||
|             ), | ||||
|         ), | ||||
|         cv.Optional(CONF_RUN_CYCLES): cv.invalid( | ||||
|             "The run_cycles option has been removed in 1.11.0 as " | ||||
|             "it was essentially the same as a run_duration of 0s." | ||||
|             "Please use run_duration now." | ||||
|         ), | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
| @@ -75,27 +98,31 @@ def to_code(config): | ||||
|         for pin in conf[CONF_PINS]: | ||||
|             mask |= 1 << pin[CONF_NUMBER] | ||||
|         struct = cg.StructInitializer( | ||||
|             Ext1Wakeup, | ||||
|             ('mask', mask), | ||||
|             ('wakeup_mode', conf[CONF_MODE]) | ||||
|             Ext1Wakeup, ("mask", mask), ("wakeup_mode", conf[CONF_MODE]) | ||||
|         ) | ||||
|         cg.add(var.set_ext1_wakeup(struct)) | ||||
|  | ||||
|     cg.add_define('USE_DEEP_SLEEP') | ||||
|     cg.add_define("USE_DEEP_SLEEP") | ||||
|  | ||||
|  | ||||
| DEEP_SLEEP_ENTER_SCHEMA = automation.maybe_simple_id({ | ||||
|     cv.GenerateID(): cv.use_id(DeepSleepComponent), | ||||
|     cv.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds, | ||||
| }) | ||||
| DEEP_SLEEP_ENTER_SCHEMA = automation.maybe_simple_id( | ||||
|     { | ||||
|         cv.GenerateID(): cv.use_id(DeepSleepComponent), | ||||
|         cv.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds, | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| DEEP_SLEEP_PREVENT_SCHEMA = automation.maybe_simple_id({ | ||||
|     cv.GenerateID(): cv.use_id(DeepSleepComponent), | ||||
| }) | ||||
| DEEP_SLEEP_PREVENT_SCHEMA = automation.maybe_simple_id( | ||||
|     { | ||||
|         cv.GenerateID(): cv.use_id(DeepSleepComponent), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @automation.register_action('deep_sleep.enter', EnterDeepSleepAction, DEEP_SLEEP_ENTER_SCHEMA) | ||||
| @automation.register_action( | ||||
|     "deep_sleep.enter", EnterDeepSleepAction, DEEP_SLEEP_ENTER_SCHEMA | ||||
| ) | ||||
| def deep_sleep_enter_to_code(config, action_id, template_arg, args): | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, paren) | ||||
| @@ -105,7 +132,9 @@ def deep_sleep_enter_to_code(config, action_id, template_arg, args): | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_action('deep_sleep.prevent', PreventDeepSleepAction, DEEP_SLEEP_PREVENT_SCHEMA) | ||||
| @automation.register_action( | ||||
|     "deep_sleep.prevent", PreventDeepSleepAction, DEEP_SLEEP_PREVENT_SCHEMA | ||||
| ) | ||||
| def deep_sleep_prevent_to_code(config, action_id, template_arg, args): | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|   | ||||
| @@ -4,57 +4,68 @@ from esphome import automation | ||||
| from esphome.const import CONF_ID, CONF_TRIGGER_ID, CONF_FILE, CONF_DEVICE | ||||
| from esphome.components import uart | ||||
|  | ||||
| DEPENDENCIES = ['uart'] | ||||
| CODEOWNERS = ['@glmnet'] | ||||
| DEPENDENCIES = ["uart"] | ||||
| CODEOWNERS = ["@glmnet"] | ||||
|  | ||||
| dfplayer_ns = cg.esphome_ns.namespace('dfplayer') | ||||
| DFPlayer = dfplayer_ns.class_('DFPlayer', cg.Component) | ||||
| DFPlayerFinishedPlaybackTrigger = dfplayer_ns.class_('DFPlayerFinishedPlaybackTrigger', | ||||
|                                                      automation.Trigger.template()) | ||||
| DFPlayerIsPlayingCondition = dfplayer_ns.class_('DFPlayerIsPlayingCondition', automation.Condition) | ||||
| dfplayer_ns = cg.esphome_ns.namespace("dfplayer") | ||||
| DFPlayer = dfplayer_ns.class_("DFPlayer", cg.Component) | ||||
| DFPlayerFinishedPlaybackTrigger = dfplayer_ns.class_( | ||||
|     "DFPlayerFinishedPlaybackTrigger", automation.Trigger.template() | ||||
| ) | ||||
| DFPlayerIsPlayingCondition = dfplayer_ns.class_( | ||||
|     "DFPlayerIsPlayingCondition", automation.Condition | ||||
| ) | ||||
|  | ||||
| MULTI_CONF = True | ||||
| CONF_FOLDER = 'folder' | ||||
| CONF_LOOP = 'loop' | ||||
| CONF_VOLUME = 'volume' | ||||
| CONF_EQ_PRESET = 'eq_preset' | ||||
| CONF_ON_FINISHED_PLAYBACK = 'on_finished_playback' | ||||
| CONF_FOLDER = "folder" | ||||
| CONF_LOOP = "loop" | ||||
| CONF_VOLUME = "volume" | ||||
| CONF_EQ_PRESET = "eq_preset" | ||||
| CONF_ON_FINISHED_PLAYBACK = "on_finished_playback" | ||||
|  | ||||
| EqPreset = dfplayer_ns.enum("EqPreset") | ||||
| EQ_PRESET = { | ||||
|     'NORMAL': EqPreset.NORMAL, | ||||
|     'POP': EqPreset.POP, | ||||
|     'ROCK': EqPreset.ROCK, | ||||
|     'JAZZ': EqPreset.JAZZ, | ||||
|     'CLASSIC': EqPreset.CLASSIC, | ||||
|     'BASS': EqPreset.BASS, | ||||
|     "NORMAL": EqPreset.NORMAL, | ||||
|     "POP": EqPreset.POP, | ||||
|     "ROCK": EqPreset.ROCK, | ||||
|     "JAZZ": EqPreset.JAZZ, | ||||
|     "CLASSIC": EqPreset.CLASSIC, | ||||
|     "BASS": EqPreset.BASS, | ||||
| } | ||||
| Device = dfplayer_ns.enum("Device") | ||||
| DEVICE = { | ||||
|     'USB': Device.USB, | ||||
|     'TF_CARD': Device.TF_CARD, | ||||
|     "USB": Device.USB, | ||||
|     "TF_CARD": Device.TF_CARD, | ||||
| } | ||||
|  | ||||
| NextAction = dfplayer_ns.class_('NextAction', automation.Action) | ||||
| PreviousAction = dfplayer_ns.class_('PreviousAction', automation.Action) | ||||
| PlayFileAction = dfplayer_ns.class_('PlayFileAction', automation.Action) | ||||
| PlayFolderAction = dfplayer_ns.class_('PlayFolderAction', automation.Action) | ||||
| SetVolumeAction = dfplayer_ns.class_('SetVolumeAction', automation.Action) | ||||
| SetEqAction = dfplayer_ns.class_('SetEqAction', automation.Action) | ||||
| SleepAction = dfplayer_ns.class_('SleepAction', automation.Action) | ||||
| ResetAction = dfplayer_ns.class_('ResetAction', automation.Action) | ||||
| StartAction = dfplayer_ns.class_('StartAction', automation.Action) | ||||
| PauseAction = dfplayer_ns.class_('PauseAction', automation.Action) | ||||
| StopAction = dfplayer_ns.class_('StopAction', automation.Action) | ||||
| RandomAction = dfplayer_ns.class_('RandomAction', automation.Action) | ||||
| SetDeviceAction = dfplayer_ns.class_('SetDeviceAction', automation.Action) | ||||
| NextAction = dfplayer_ns.class_("NextAction", automation.Action) | ||||
| PreviousAction = dfplayer_ns.class_("PreviousAction", automation.Action) | ||||
| PlayFileAction = dfplayer_ns.class_("PlayFileAction", automation.Action) | ||||
| PlayFolderAction = dfplayer_ns.class_("PlayFolderAction", automation.Action) | ||||
| SetVolumeAction = dfplayer_ns.class_("SetVolumeAction", automation.Action) | ||||
| SetEqAction = dfplayer_ns.class_("SetEqAction", automation.Action) | ||||
| SleepAction = dfplayer_ns.class_("SleepAction", automation.Action) | ||||
| ResetAction = dfplayer_ns.class_("ResetAction", automation.Action) | ||||
| StartAction = dfplayer_ns.class_("StartAction", automation.Action) | ||||
| PauseAction = dfplayer_ns.class_("PauseAction", automation.Action) | ||||
| StopAction = dfplayer_ns.class_("StopAction", automation.Action) | ||||
| RandomAction = dfplayer_ns.class_("RandomAction", automation.Action) | ||||
| SetDeviceAction = dfplayer_ns.class_("SetDeviceAction", automation.Action) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All(cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(DFPlayer), | ||||
|     cv.Optional(CONF_ON_FINISHED_PLAYBACK): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DFPlayerFinishedPlaybackTrigger), | ||||
|     }), | ||||
| }).extend(uart.UART_DEVICE_SCHEMA)) | ||||
| CONFIG_SCHEMA = cv.All( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(DFPlayer), | ||||
|             cv.Optional(CONF_ON_FINISHED_PLAYBACK): automation.validate_automation( | ||||
|                 { | ||||
|                     cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( | ||||
|                         DFPlayerFinishedPlaybackTrigger | ||||
|                     ), | ||||
|                 } | ||||
|             ), | ||||
|         } | ||||
|     ).extend(uart.UART_DEVICE_SCHEMA) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
| @@ -67,29 +78,48 @@ def to_code(config): | ||||
|         yield automation.build_automation(trigger, [], conf) | ||||
|  | ||||
|  | ||||
| @automation.register_action('dfplayer.play_next', NextAction, cv.Schema({ | ||||
|     cv.GenerateID(): cv.use_id(DFPlayer), | ||||
| })) | ||||
| @automation.register_action( | ||||
|     "dfplayer.play_next", | ||||
|     NextAction, | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def dfplayer_next_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_action('dfplayer.play_previous', PreviousAction, cv.Schema({ | ||||
|     cv.GenerateID(): cv.use_id(DFPlayer), | ||||
| })) | ||||
| @automation.register_action( | ||||
|     "dfplayer.play_previous", | ||||
|     PreviousAction, | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def dfplayer_previous_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_action('dfplayer.play', PlayFileAction, cv.maybe_simple_value({ | ||||
|     cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|     cv.Required(CONF_FILE): cv.templatable(cv.int_), | ||||
|     cv.Optional(CONF_LOOP): cv.templatable(cv.boolean), | ||||
| }, key=CONF_FILE)) | ||||
| @automation.register_action( | ||||
|     "dfplayer.play", | ||||
|     PlayFileAction, | ||||
|     cv.maybe_simple_value( | ||||
|         { | ||||
|             cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|             cv.Required(CONF_FILE): cv.templatable(cv.int_), | ||||
|             cv.Optional(CONF_LOOP): cv.templatable(cv.boolean), | ||||
|         }, | ||||
|         key=CONF_FILE, | ||||
|     ), | ||||
| ) | ||||
| def dfplayer_play_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
| @@ -101,12 +131,18 @@ def dfplayer_play_to_code(config, action_id, template_arg, args): | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_action('dfplayer.play_folder', PlayFolderAction, cv.Schema({ | ||||
|     cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|     cv.Required(CONF_FOLDER): cv.templatable(cv.int_), | ||||
|     cv.Optional(CONF_FILE): cv.templatable(cv.int_), | ||||
|     cv.Optional(CONF_LOOP): cv.templatable(cv.boolean), | ||||
| })) | ||||
| @automation.register_action( | ||||
|     "dfplayer.play_folder", | ||||
|     PlayFolderAction, | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|             cv.Required(CONF_FOLDER): cv.templatable(cv.int_), | ||||
|             cv.Optional(CONF_FILE): cv.templatable(cv.int_), | ||||
|             cv.Optional(CONF_LOOP): cv.templatable(cv.boolean), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def dfplayer_play_folder_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
| @@ -121,10 +157,17 @@ def dfplayer_play_folder_to_code(config, action_id, template_arg, args): | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_action('dfplayer.set_device', SetDeviceAction, cv.maybe_simple_value({ | ||||
|     cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|     cv.Required(CONF_DEVICE): cv.enum(DEVICE, upper=True), | ||||
| }, key=CONF_DEVICE)) | ||||
| @automation.register_action( | ||||
|     "dfplayer.set_device", | ||||
|     SetDeviceAction, | ||||
|     cv.maybe_simple_value( | ||||
|         { | ||||
|             cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|             cv.Required(CONF_DEVICE): cv.enum(DEVICE, upper=True), | ||||
|         }, | ||||
|         key=CONF_DEVICE, | ||||
|     ), | ||||
| ) | ||||
| def dfplayer_set_device_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
| @@ -133,10 +176,17 @@ def dfplayer_set_device_to_code(config, action_id, template_arg, args): | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_action('dfplayer.set_volume', SetVolumeAction, cv.maybe_simple_value({ | ||||
|     cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|     cv.Required(CONF_VOLUME): cv.templatable(cv.int_), | ||||
| }, key=CONF_VOLUME)) | ||||
| @automation.register_action( | ||||
|     "dfplayer.set_volume", | ||||
|     SetVolumeAction, | ||||
|     cv.maybe_simple_value( | ||||
|         { | ||||
|             cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|             cv.Required(CONF_VOLUME): cv.templatable(cv.int_), | ||||
|         }, | ||||
|         key=CONF_VOLUME, | ||||
|     ), | ||||
| ) | ||||
| def dfplayer_set_volume_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
| @@ -145,10 +195,17 @@ def dfplayer_set_volume_to_code(config, action_id, template_arg, args): | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_action('dfplayer.set_eq', SetEqAction, cv.maybe_simple_value({ | ||||
|     cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|     cv.Required(CONF_EQ_PRESET): cv.templatable(cv.enum(EQ_PRESET, upper=True)), | ||||
| }, key=CONF_EQ_PRESET)) | ||||
| @automation.register_action( | ||||
|     "dfplayer.set_eq", | ||||
|     SetEqAction, | ||||
|     cv.maybe_simple_value( | ||||
|         { | ||||
|             cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|             cv.Required(CONF_EQ_PRESET): cv.templatable(cv.enum(EQ_PRESET, upper=True)), | ||||
|         }, | ||||
|         key=CONF_EQ_PRESET, | ||||
|     ), | ||||
| ) | ||||
| def dfplayer_set_eq_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
| @@ -157,63 +214,105 @@ def dfplayer_set_eq_to_code(config, action_id, template_arg, args): | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_action('dfplayer.sleep', SleepAction, cv.Schema({ | ||||
|     cv.GenerateID(): cv.use_id(DFPlayer), | ||||
| })) | ||||
| @automation.register_action( | ||||
|     "dfplayer.sleep", | ||||
|     SleepAction, | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def dfplayer_sleep_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_action('dfplayer.reset', ResetAction, cv.Schema({ | ||||
|     cv.GenerateID(): cv.use_id(DFPlayer), | ||||
| })) | ||||
| @automation.register_action( | ||||
|     "dfplayer.reset", | ||||
|     ResetAction, | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def dfplayer_reset_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_action('dfplayer.start', StartAction, cv.Schema({ | ||||
|     cv.GenerateID(): cv.use_id(DFPlayer), | ||||
| })) | ||||
| @automation.register_action( | ||||
|     "dfplayer.start", | ||||
|     StartAction, | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def dfplayer_start_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_action('dfplayer.pause', PauseAction, cv.Schema({ | ||||
|     cv.GenerateID(): cv.use_id(DFPlayer), | ||||
| })) | ||||
| @automation.register_action( | ||||
|     "dfplayer.pause", | ||||
|     PauseAction, | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def dfplayer_pause_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_action('dfplayer.stop', StopAction, cv.Schema({ | ||||
|     cv.GenerateID(): cv.use_id(DFPlayer), | ||||
| })) | ||||
| @automation.register_action( | ||||
|     "dfplayer.stop", | ||||
|     StopAction, | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def dfplayer_stop_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_action('dfplayer.random', RandomAction, cv.Schema({ | ||||
|     cv.GenerateID(): cv.use_id(DFPlayer), | ||||
| })) | ||||
| @automation.register_action( | ||||
|     "dfplayer.random", | ||||
|     RandomAction, | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def dfplayer_random_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_condition('dfplayer.is_playing', DFPlayerIsPlayingCondition, cv.Schema({ | ||||
|     cv.GenerateID(): cv.use_id(DFPlayer), | ||||
| })) | ||||
| @automation.register_condition( | ||||
|     "dfplayer.is_playing", | ||||
|     DFPlayerIsPlayingCondition, | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.use_id(DFPlayer), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def dfplyaer_is_playing_to_code(config, condition_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(condition_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| CODEOWNERS = ['@OttoWinter'] | ||||
| CODEOWNERS = ["@OttoWinter"] | ||||
|   | ||||
| @@ -2,33 +2,49 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.components import sensor | ||||
| from esphome.const import CONF_HUMIDITY, CONF_ID, CONF_MODEL, CONF_PIN, CONF_TEMPERATURE, \ | ||||
|     ICON_EMPTY, UNIT_CELSIUS, UNIT_PERCENT, DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_HUMIDITY | ||||
| from esphome.const import ( | ||||
|     CONF_HUMIDITY, | ||||
|     CONF_ID, | ||||
|     CONF_MODEL, | ||||
|     CONF_PIN, | ||||
|     CONF_TEMPERATURE, | ||||
|     ICON_EMPTY, | ||||
|     UNIT_CELSIUS, | ||||
|     UNIT_PERCENT, | ||||
|     DEVICE_CLASS_TEMPERATURE, | ||||
|     DEVICE_CLASS_HUMIDITY, | ||||
| ) | ||||
|  | ||||
| from esphome.cpp_helpers import gpio_pin_expression | ||||
|  | ||||
| dht_ns = cg.esphome_ns.namespace('dht') | ||||
| DHTModel = dht_ns.enum('DHTModel') | ||||
| dht_ns = cg.esphome_ns.namespace("dht") | ||||
| DHTModel = dht_ns.enum("DHTModel") | ||||
| DHT_MODELS = { | ||||
|     'AUTO_DETECT': DHTModel.DHT_MODEL_AUTO_DETECT, | ||||
|     'DHT11': DHTModel.DHT_MODEL_DHT11, | ||||
|     'DHT22': DHTModel.DHT_MODEL_DHT22, | ||||
|     'AM2302': DHTModel.DHT_MODEL_AM2302, | ||||
|     'RHT03': DHTModel.DHT_MODEL_RHT03, | ||||
|     'SI7021': DHTModel.DHT_MODEL_SI7021, | ||||
|     'DHT22_TYPE2': DHTModel.DHT_MODEL_DHT22_TYPE2, | ||||
|     "AUTO_DETECT": DHTModel.DHT_MODEL_AUTO_DETECT, | ||||
|     "DHT11": DHTModel.DHT_MODEL_DHT11, | ||||
|     "DHT22": DHTModel.DHT_MODEL_DHT22, | ||||
|     "AM2302": DHTModel.DHT_MODEL_AM2302, | ||||
|     "RHT03": DHTModel.DHT_MODEL_RHT03, | ||||
|     "SI7021": DHTModel.DHT_MODEL_SI7021, | ||||
|     "DHT22_TYPE2": DHTModel.DHT_MODEL_DHT22_TYPE2, | ||||
| } | ||||
| DHT = dht_ns.class_('DHT', cg.PollingComponent) | ||||
| DHT = dht_ns.class_("DHT", cg.PollingComponent) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(DHT), | ||||
|     cv.Required(CONF_PIN): pins.gpio_input_pin_schema, | ||||
|     cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, | ||||
|                                                         DEVICE_CLASS_TEMPERATURE), | ||||
|     cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 0, | ||||
|                                                      DEVICE_CLASS_HUMIDITY), | ||||
|     cv.Optional(CONF_MODEL, default='auto detect'): cv.enum(DHT_MODELS, upper=True, space='_'), | ||||
| }).extend(cv.polling_component_schema('60s')) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(DHT), | ||||
|         cv.Required(CONF_PIN): pins.gpio_input_pin_schema, | ||||
|         cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( | ||||
|             UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE | ||||
|         ), | ||||
|         cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( | ||||
|             UNIT_PERCENT, ICON_EMPTY, 0, DEVICE_CLASS_HUMIDITY | ||||
|         ), | ||||
|         cv.Optional(CONF_MODEL, default="auto detect"): cv.enum( | ||||
|             DHT_MODELS, upper=True, space="_" | ||||
|         ), | ||||
|     } | ||||
| ).extend(cv.polling_component_schema("60s")) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,21 +1,37 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.const import CONF_HUMIDITY, CONF_ID, CONF_TEMPERATURE, \ | ||||
|     UNIT_CELSIUS, ICON_EMPTY, UNIT_PERCENT, DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_HUMIDITY | ||||
| from esphome.const import ( | ||||
|     CONF_HUMIDITY, | ||||
|     CONF_ID, | ||||
|     CONF_TEMPERATURE, | ||||
|     UNIT_CELSIUS, | ||||
|     ICON_EMPTY, | ||||
|     UNIT_PERCENT, | ||||
|     DEVICE_CLASS_TEMPERATURE, | ||||
|     DEVICE_CLASS_HUMIDITY, | ||||
| ) | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| DEPENDENCIES = ["i2c"] | ||||
|  | ||||
| dht12_ns = cg.esphome_ns.namespace('dht12') | ||||
| DHT12Component = dht12_ns.class_('DHT12Component', cg.PollingComponent, i2c.I2CDevice) | ||||
| dht12_ns = cg.esphome_ns.namespace("dht12") | ||||
| DHT12Component = dht12_ns.class_("DHT12Component", cg.PollingComponent, i2c.I2CDevice) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(DHT12Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, | ||||
|                                                         DEVICE_CLASS_TEMPERATURE), | ||||
|     cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 1, | ||||
|                                                      DEVICE_CLASS_HUMIDITY), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x5C)) | ||||
| CONFIG_SCHEMA = ( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(DHT12Component), | ||||
|             cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( | ||||
|                 UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE | ||||
|             ), | ||||
|             cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( | ||||
|                 UNIT_PERCENT, ICON_EMPTY, 1, DEVICE_CLASS_HUMIDITY | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
|     .extend(i2c.i2c_device_schema(0x5C)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -7,14 +7,18 @@ from esphome.core import coroutine, coroutine_with_priority | ||||
|  | ||||
| IS_PLATFORM_COMPONENT = True | ||||
|  | ||||
| display_ns = cg.esphome_ns.namespace('display') | ||||
| DisplayBuffer = display_ns.class_('DisplayBuffer') | ||||
| DisplayPage = display_ns.class_('DisplayPage') | ||||
| DisplayPagePtr = DisplayPage.operator('ptr') | ||||
| DisplayBufferRef = DisplayBuffer.operator('ref') | ||||
| DisplayPageShowAction = display_ns.class_('DisplayPageShowAction', automation.Action) | ||||
| DisplayPageShowNextAction = display_ns.class_('DisplayPageShowNextAction', automation.Action) | ||||
| DisplayPageShowPrevAction = display_ns.class_('DisplayPageShowPrevAction', automation.Action) | ||||
| display_ns = cg.esphome_ns.namespace("display") | ||||
| DisplayBuffer = display_ns.class_("DisplayBuffer") | ||||
| DisplayPage = display_ns.class_("DisplayPage") | ||||
| DisplayPagePtr = DisplayPage.operator("ptr") | ||||
| DisplayBufferRef = DisplayBuffer.operator("ref") | ||||
| DisplayPageShowAction = display_ns.class_("DisplayPageShowAction", automation.Action) | ||||
| DisplayPageShowNextAction = display_ns.class_( | ||||
|     "DisplayPageShowNextAction", automation.Action | ||||
| ) | ||||
| DisplayPageShowPrevAction = display_ns.class_( | ||||
|     "DisplayPageShowPrevAction", automation.Action | ||||
| ) | ||||
|  | ||||
| DISPLAY_ROTATIONS = { | ||||
|     0: display_ns.DISPLAY_ROTATION_0_DEGREES, | ||||
| @@ -31,17 +35,26 @@ def validate_rotation(value): | ||||
|     return cv.enum(DISPLAY_ROTATIONS, int=True)(value) | ||||
|  | ||||
|  | ||||
| BASIC_DISPLAY_SCHEMA = cv.Schema({ | ||||
|     cv.Optional(CONF_LAMBDA): cv.lambda_, | ||||
| }) | ||||
| BASIC_DISPLAY_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.Optional(CONF_LAMBDA): cv.lambda_, | ||||
|     } | ||||
| ) | ||||
|  | ||||
| FULL_DISPLAY_SCHEMA = BASIC_DISPLAY_SCHEMA.extend({ | ||||
|     cv.Optional(CONF_ROTATION): validate_rotation, | ||||
|     cv.Optional(CONF_PAGES): cv.All(cv.ensure_list({ | ||||
|         cv.GenerateID(): cv.declare_id(DisplayPage), | ||||
|         cv.Required(CONF_LAMBDA): cv.lambda_, | ||||
|     }), cv.Length(min=1)), | ||||
| }) | ||||
| FULL_DISPLAY_SCHEMA = BASIC_DISPLAY_SCHEMA.extend( | ||||
|     { | ||||
|         cv.Optional(CONF_ROTATION): validate_rotation, | ||||
|         cv.Optional(CONF_PAGES): cv.All( | ||||
|             cv.ensure_list( | ||||
|                 { | ||||
|                     cv.GenerateID(): cv.declare_id(DisplayPage), | ||||
|                     cv.Required(CONF_LAMBDA): cv.lambda_, | ||||
|                 } | ||||
|             ), | ||||
|             cv.Length(min=1), | ||||
|         ), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| @@ -51,8 +64,9 @@ def setup_display_core_(var, config): | ||||
|     if CONF_PAGES in config: | ||||
|         pages = [] | ||||
|         for conf in config[CONF_PAGES]: | ||||
|             lambda_ = yield cg.process_lambda(conf[CONF_LAMBDA], [(DisplayBufferRef, 'it')], | ||||
|                                               return_type=cg.void) | ||||
|             lambda_ = yield cg.process_lambda( | ||||
|                 conf[CONF_LAMBDA], [(DisplayBufferRef, "it")], return_type=cg.void | ||||
|             ) | ||||
|             page = cg.new_Pvariable(conf[CONF_ID], lambda_) | ||||
|             pages.append(page) | ||||
|         cg.add(var.set_pages(pages)) | ||||
| @@ -63,9 +77,15 @@ def register_display(var, config): | ||||
|     yield setup_display_core_(var, config) | ||||
|  | ||||
|  | ||||
| @automation.register_action('display.page.show', DisplayPageShowAction, maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.templatable(cv.use_id(DisplayPage)), | ||||
| })) | ||||
| @automation.register_action( | ||||
|     "display.page.show", | ||||
|     DisplayPageShowAction, | ||||
|     maybe_simple_id( | ||||
|         { | ||||
|             cv.Required(CONF_ID): cv.templatable(cv.use_id(DisplayPage)), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def display_page_show_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     if isinstance(config[CONF_ID], core.Lambda): | ||||
| @@ -77,18 +97,29 @@ def display_page_show_to_code(config, action_id, template_arg, args): | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_action('display.page.show_next', DisplayPageShowNextAction, maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.templatable(cv.use_id(DisplayBuffer)), | ||||
| })) | ||||
| @automation.register_action( | ||||
|     "display.page.show_next", | ||||
|     DisplayPageShowNextAction, | ||||
|     maybe_simple_id( | ||||
|         { | ||||
|             cv.Required(CONF_ID): cv.templatable(cv.use_id(DisplayBuffer)), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def display_page_show_next_to_code(config, action_id, template_arg, args): | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|  | ||||
|  | ||||
| @automation.register_action('display.page.show_previous', DisplayPageShowPrevAction, | ||||
|                             maybe_simple_id({ | ||||
|                                 cv.Required(CONF_ID): cv.templatable(cv.use_id(DisplayBuffer)), | ||||
|                             })) | ||||
| @automation.register_action( | ||||
|     "display.page.show_previous", | ||||
|     DisplayPageShowPrevAction, | ||||
|     maybe_simple_id( | ||||
|         { | ||||
|             cv.Required(CONF_ID): cv.templatable(cv.use_id(DisplayBuffer)), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def display_page_show_previous_to_code(config, action_id, template_arg, args): | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|   | ||||
| @@ -5,31 +5,45 @@ from esphome.components import i2c, time | ||||
| from esphome.const import CONF_ID | ||||
|  | ||||
|  | ||||
| CODEOWNERS = ['@badbadc0ffee'] | ||||
| DEPENDENCIES = ['i2c'] | ||||
| ds1307_ns = cg.esphome_ns.namespace('ds1307') | ||||
| DS1307Component = ds1307_ns.class_('DS1307Component', time.RealTimeClock, i2c.I2CDevice) | ||||
| WriteAction = ds1307_ns.class_('WriteAction', automation.Action) | ||||
| ReadAction = ds1307_ns.class_('ReadAction', automation.Action) | ||||
| CODEOWNERS = ["@badbadc0ffee"] | ||||
| DEPENDENCIES = ["i2c"] | ||||
| ds1307_ns = cg.esphome_ns.namespace("ds1307") | ||||
| DS1307Component = ds1307_ns.class_("DS1307Component", time.RealTimeClock, i2c.I2CDevice) | ||||
| WriteAction = ds1307_ns.class_("WriteAction", automation.Action) | ||||
| ReadAction = ds1307_ns.class_("ReadAction", automation.Action) | ||||
|  | ||||
|  | ||||
| CONFIG_SCHEMA = time.TIME_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(DS1307Component), | ||||
| }).extend(i2c.i2c_device_schema(0x68)) | ||||
| CONFIG_SCHEMA = time.TIME_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(DS1307Component), | ||||
|     } | ||||
| ).extend(i2c.i2c_device_schema(0x68)) | ||||
|  | ||||
|  | ||||
| @automation.register_action('ds1307.write_time', WriteAction, cv.Schema({ | ||||
|     cv.GenerateID(): cv.use_id(DS1307Component), | ||||
| })) | ||||
| @automation.register_action( | ||||
|     "ds1307.write_time", | ||||
|     WriteAction, | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.use_id(DS1307Component), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def ds1307_write_time_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @automation.register_action('ds1307.read_time', ReadAction, automation.maybe_simple_id({ | ||||
|     cv.GenerateID(): cv.use_id(DS1307Component), | ||||
| })) | ||||
| @automation.register_action( | ||||
|     "ds1307.read_time", | ||||
|     ReadAction, | ||||
|     automation.maybe_simple_id( | ||||
|         { | ||||
|             cv.GenerateID(): cv.use_id(DS1307Component), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def ds1307_read_time_to_code(config, action_id, template_arg, args): | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_parented(var, config[CONF_ID]) | ||||
|   | ||||
| @@ -2,16 +2,31 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.components import sensor | ||||
| from esphome.const import CONF_ID, CONF_PIN, DEVICE_CLASS_EMPTY, UNIT_PERCENT, ICON_PERCENT | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     CONF_PIN, | ||||
|     DEVICE_CLASS_EMPTY, | ||||
|     UNIT_PERCENT, | ||||
|     ICON_PERCENT, | ||||
| ) | ||||
|  | ||||
| duty_cycle_ns = cg.esphome_ns.namespace('duty_cycle') | ||||
| DutyCycleSensor = duty_cycle_ns.class_('DutyCycleSensor', sensor.Sensor, cg.PollingComponent) | ||||
| duty_cycle_ns = cg.esphome_ns.namespace("duty_cycle") | ||||
| DutyCycleSensor = duty_cycle_ns.class_( | ||||
|     "DutyCycleSensor", sensor.Sensor, cg.PollingComponent | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = sensor.sensor_schema(UNIT_PERCENT, ICON_PERCENT, 1, DEVICE_CLASS_EMPTY).extend({ | ||||
|     cv.GenerateID(): cv.declare_id(DutyCycleSensor), | ||||
|     cv.Required(CONF_PIN): cv.All(pins.internal_gpio_input_pin_schema, | ||||
|                                   pins.validate_has_interrupt), | ||||
| }).extend(cv.polling_component_schema('60s')) | ||||
| CONFIG_SCHEMA = ( | ||||
|     sensor.sensor_schema(UNIT_PERCENT, ICON_PERCENT, 1, DEVICE_CLASS_EMPTY) | ||||
|     .extend( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(DutyCycleSensor), | ||||
|             cv.Required(CONF_PIN): cv.All( | ||||
|                 pins.internal_gpio_input_pin_schema, pins.validate_has_interrupt | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -4,28 +4,29 @@ from esphome.components.light.types import AddressableLightEffect | ||||
| from esphome.components.light.effects import register_addressable_effect | ||||
| from esphome.const import CONF_ID, CONF_NAME, CONF_METHOD, CONF_CHANNELS | ||||
|  | ||||
| e131_ns = cg.esphome_ns.namespace('e131') | ||||
| E131AddressableLightEffect = e131_ns.class_('E131AddressableLightEffect', AddressableLightEffect) | ||||
| E131Component = e131_ns.class_('E131Component', cg.Component) | ||||
| e131_ns = cg.esphome_ns.namespace("e131") | ||||
| E131AddressableLightEffect = e131_ns.class_( | ||||
|     "E131AddressableLightEffect", AddressableLightEffect | ||||
| ) | ||||
| E131Component = e131_ns.class_("E131Component", cg.Component) | ||||
|  | ||||
| METHODS = { | ||||
|     'UNICAST': e131_ns.E131_UNICAST, | ||||
|     'MULTICAST': e131_ns.E131_MULTICAST | ||||
| } | ||||
| METHODS = {"UNICAST": e131_ns.E131_UNICAST, "MULTICAST": e131_ns.E131_MULTICAST} | ||||
|  | ||||
| CHANNELS = { | ||||
|     'MONO': e131_ns.E131_MONO, | ||||
|     'RGB': e131_ns.E131_RGB, | ||||
|     'RGBW': e131_ns.E131_RGBW | ||||
|     "MONO": e131_ns.E131_MONO, | ||||
|     "RGB": e131_ns.E131_RGB, | ||||
|     "RGBW": e131_ns.E131_RGBW, | ||||
| } | ||||
|  | ||||
| CONF_UNIVERSE = 'universe' | ||||
| CONF_E131_ID = 'e131_id' | ||||
| CONF_UNIVERSE = "universe" | ||||
| CONF_E131_ID = "e131_id" | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(E131Component), | ||||
|     cv.Optional(CONF_METHOD, default='MULTICAST'): cv.one_of(*METHODS, upper=True), | ||||
| }) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(E131Component), | ||||
|         cv.Optional(CONF_METHOD, default="MULTICAST"): cv.one_of(*METHODS, upper=True), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
| @@ -34,11 +35,16 @@ def to_code(config): | ||||
|     cg.add(var.set_method(METHODS[config[CONF_METHOD]])) | ||||
|  | ||||
|  | ||||
| @register_addressable_effect('e131', E131AddressableLightEffect, "E1.31", { | ||||
|     cv.GenerateID(CONF_E131_ID): cv.use_id(E131Component), | ||||
|     cv.Required(CONF_UNIVERSE): cv.int_range(min=1, max=512), | ||||
|     cv.Optional(CONF_CHANNELS, default='RGB'): cv.one_of(*CHANNELS, upper=True) | ||||
| }) | ||||
| @register_addressable_effect( | ||||
|     "e131", | ||||
|     E131AddressableLightEffect, | ||||
|     "E1.31", | ||||
|     { | ||||
|         cv.GenerateID(CONF_E131_ID): cv.use_id(E131Component), | ||||
|         cv.Required(CONF_UNIVERSE): cv.int_range(min=1, max=512), | ||||
|         cv.Optional(CONF_CHANNELS, default="RGB"): cv.one_of(*CHANNELS, upper=True), | ||||
|     }, | ||||
| ) | ||||
| def e131_light_effect_to_code(config, effect_id): | ||||
|     parent = yield cg.get_variable(config[CONF_E131_ID]) | ||||
|  | ||||
|   | ||||
| @@ -2,27 +2,34 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import automation | ||||
| from esphome.components import binary_sensor, cover | ||||
| from esphome.const import CONF_CLOSE_ACTION, CONF_CLOSE_DURATION, \ | ||||
|     CONF_CLOSE_ENDSTOP, CONF_ID, CONF_OPEN_ACTION, CONF_OPEN_DURATION, \ | ||||
|     CONF_OPEN_ENDSTOP, CONF_STOP_ACTION, CONF_MAX_DURATION | ||||
| from esphome.const import ( | ||||
|     CONF_CLOSE_ACTION, | ||||
|     CONF_CLOSE_DURATION, | ||||
|     CONF_CLOSE_ENDSTOP, | ||||
|     CONF_ID, | ||||
|     CONF_OPEN_ACTION, | ||||
|     CONF_OPEN_DURATION, | ||||
|     CONF_OPEN_ENDSTOP, | ||||
|     CONF_STOP_ACTION, | ||||
|     CONF_MAX_DURATION, | ||||
| ) | ||||
|  | ||||
| endstop_ns = cg.esphome_ns.namespace('endstop') | ||||
| EndstopCover = endstop_ns.class_('EndstopCover', cover.Cover, cg.Component) | ||||
| endstop_ns = cg.esphome_ns.namespace("endstop") | ||||
| EndstopCover = endstop_ns.class_("EndstopCover", cover.Cover, cg.Component) | ||||
|  | ||||
| CONFIG_SCHEMA = cover.COVER_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(EndstopCover), | ||||
|     cv.Required(CONF_STOP_ACTION): automation.validate_automation(single=True), | ||||
|  | ||||
|     cv.Required(CONF_OPEN_ENDSTOP): cv.use_id(binary_sensor.BinarySensor), | ||||
|     cv.Required(CONF_OPEN_ACTION): automation.validate_automation(single=True), | ||||
|     cv.Required(CONF_OPEN_DURATION): cv.positive_time_period_milliseconds, | ||||
|  | ||||
|     cv.Required(CONF_CLOSE_ACTION): automation.validate_automation(single=True), | ||||
|     cv.Required(CONF_CLOSE_ENDSTOP): cv.use_id(binary_sensor.BinarySensor), | ||||
|     cv.Required(CONF_CLOSE_DURATION): cv.positive_time_period_milliseconds, | ||||
|  | ||||
|     cv.Optional(CONF_MAX_DURATION): cv.positive_time_period_milliseconds, | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| CONFIG_SCHEMA = cover.COVER_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(EndstopCover), | ||||
|         cv.Required(CONF_STOP_ACTION): automation.validate_automation(single=True), | ||||
|         cv.Required(CONF_OPEN_ENDSTOP): cv.use_id(binary_sensor.BinarySensor), | ||||
|         cv.Required(CONF_OPEN_ACTION): automation.validate_automation(single=True), | ||||
|         cv.Required(CONF_OPEN_DURATION): cv.positive_time_period_milliseconds, | ||||
|         cv.Required(CONF_CLOSE_ACTION): automation.validate_automation(single=True), | ||||
|         cv.Required(CONF_CLOSE_ENDSTOP): cv.use_id(binary_sensor.BinarySensor), | ||||
|         cv.Required(CONF_CLOSE_DURATION): cv.positive_time_period_milliseconds, | ||||
|         cv.Optional(CONF_MAX_DURATION): cv.positive_time_period_milliseconds, | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
| @@ -30,17 +37,23 @@ def to_code(config): | ||||
|     yield cg.register_component(var, config) | ||||
|     yield cover.register_cover(var, config) | ||||
|  | ||||
|     yield automation.build_automation(var.get_stop_trigger(), [], config[CONF_STOP_ACTION]) | ||||
|     yield automation.build_automation( | ||||
|         var.get_stop_trigger(), [], config[CONF_STOP_ACTION] | ||||
|     ) | ||||
|  | ||||
|     bin = yield cg.get_variable(config[CONF_OPEN_ENDSTOP]) | ||||
|     cg.add(var.set_open_endstop(bin)) | ||||
|     cg.add(var.set_open_duration(config[CONF_OPEN_DURATION])) | ||||
|     yield automation.build_automation(var.get_open_trigger(), [], config[CONF_OPEN_ACTION]) | ||||
|     yield automation.build_automation( | ||||
|         var.get_open_trigger(), [], config[CONF_OPEN_ACTION] | ||||
|     ) | ||||
|  | ||||
|     bin = yield cg.get_variable(config[CONF_CLOSE_ENDSTOP]) | ||||
|     cg.add(var.set_close_endstop(bin)) | ||||
|     cg.add(var.set_close_duration(config[CONF_CLOSE_DURATION])) | ||||
|     yield automation.build_automation(var.get_close_trigger(), [], config[CONF_CLOSE_ACTION]) | ||||
|     yield automation.build_automation( | ||||
|         var.get_close_trigger(), [], config[CONF_CLOSE_ACTION] | ||||
|     ) | ||||
|  | ||||
|     if CONF_MAX_DURATION in config: | ||||
|         cg.add(var.set_max_duration(config[CONF_MAX_DURATION])) | ||||
|   | ||||
| @@ -3,26 +3,30 @@ import esphome.config_validation as cv | ||||
| from esphome.const import CONF_ID, CONF_TYPE, CONF_UUID, ESP_PLATFORM_ESP32 | ||||
|  | ||||
| ESP_PLATFORMS = [ESP_PLATFORM_ESP32] | ||||
| CONFLICTS_WITH = ['esp32_ble_tracker'] | ||||
| CONFLICTS_WITH = ["esp32_ble_tracker"] | ||||
|  | ||||
| esp32_ble_beacon_ns = cg.esphome_ns.namespace('esp32_ble_beacon') | ||||
| ESP32BLEBeacon = esp32_ble_beacon_ns.class_('ESP32BLEBeacon', cg.Component) | ||||
| esp32_ble_beacon_ns = cg.esphome_ns.namespace("esp32_ble_beacon") | ||||
| ESP32BLEBeacon = esp32_ble_beacon_ns.class_("ESP32BLEBeacon", cg.Component) | ||||
|  | ||||
| CONF_MAJOR = 'major' | ||||
| CONF_MINOR = 'minor' | ||||
| CONF_MAJOR = "major" | ||||
| CONF_MINOR = "minor" | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(ESP32BLEBeacon), | ||||
|     cv.Required(CONF_TYPE): cv.one_of('IBEACON', upper=True), | ||||
|     cv.Required(CONF_UUID): cv.uuid, | ||||
|     cv.Optional(CONF_MAJOR, default=10167): cv.uint16_t, | ||||
|     cv.Optional(CONF_MINOR, default=61958): cv.uint16_t, | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(ESP32BLEBeacon), | ||||
|         cv.Required(CONF_TYPE): cv.one_of("IBEACON", upper=True), | ||||
|         cv.Required(CONF_UUID): cv.uuid, | ||||
|         cv.Optional(CONF_MAJOR, default=10167): cv.uint16_t, | ||||
|         cv.Optional(CONF_MINOR, default=61958): cv.uint16_t, | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     uuid = config[CONF_UUID].hex | ||||
|     uuid_arr = [cg.RawExpression('0x{}'.format(uuid[i:i + 2])) for i in range(0, len(uuid), 2)] | ||||
|     uuid_arr = [ | ||||
|         cg.RawExpression("0x{}".format(uuid[i : i + 2])) for i in range(0, len(uuid), 2) | ||||
|     ] | ||||
|     var = cg.new_Pvariable(config[CONF_ID], uuid_arr) | ||||
|     yield cg.register_component(var, config) | ||||
|     cg.add(var.set_major(config[CONF_MAJOR])) | ||||
|   | ||||
| @@ -2,33 +2,46 @@ import re | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import automation | ||||
| from esphome.const import CONF_ID, ESP_PLATFORM_ESP32, CONF_INTERVAL, \ | ||||
|     CONF_DURATION, CONF_TRIGGER_ID, CONF_MAC_ADDRESS, CONF_SERVICE_UUID, CONF_MANUFACTURER_ID, \ | ||||
|     CONF_ON_BLE_ADVERTISE, CONF_ON_BLE_SERVICE_DATA_ADVERTISE, \ | ||||
|     CONF_ON_BLE_MANUFACTURER_DATA_ADVERTISE | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     ESP_PLATFORM_ESP32, | ||||
|     CONF_INTERVAL, | ||||
|     CONF_DURATION, | ||||
|     CONF_TRIGGER_ID, | ||||
|     CONF_MAC_ADDRESS, | ||||
|     CONF_SERVICE_UUID, | ||||
|     CONF_MANUFACTURER_ID, | ||||
|     CONF_ON_BLE_ADVERTISE, | ||||
|     CONF_ON_BLE_SERVICE_DATA_ADVERTISE, | ||||
|     CONF_ON_BLE_MANUFACTURER_DATA_ADVERTISE, | ||||
| ) | ||||
| from esphome.core import coroutine | ||||
|  | ||||
| ESP_PLATFORMS = [ESP_PLATFORM_ESP32] | ||||
| AUTO_LOAD = ['xiaomi_ble', 'ruuvi_ble'] | ||||
| AUTO_LOAD = ["xiaomi_ble", "ruuvi_ble"] | ||||
|  | ||||
| CONF_ESP32_BLE_ID = 'esp32_ble_id' | ||||
| CONF_SCAN_PARAMETERS = 'scan_parameters' | ||||
| CONF_WINDOW = 'window' | ||||
| CONF_ACTIVE = 'active' | ||||
| esp32_ble_tracker_ns = cg.esphome_ns.namespace('esp32_ble_tracker') | ||||
| ESP32BLETracker = esp32_ble_tracker_ns.class_('ESP32BLETracker', cg.Component) | ||||
| ESPBTDeviceListener = esp32_ble_tracker_ns.class_('ESPBTDeviceListener') | ||||
| ESPBTDevice = esp32_ble_tracker_ns.class_('ESPBTDevice') | ||||
| ESPBTDeviceConstRef = ESPBTDevice.operator('ref').operator('const') | ||||
| CONF_ESP32_BLE_ID = "esp32_ble_id" | ||||
| CONF_SCAN_PARAMETERS = "scan_parameters" | ||||
| CONF_WINDOW = "window" | ||||
| CONF_ACTIVE = "active" | ||||
| esp32_ble_tracker_ns = cg.esphome_ns.namespace("esp32_ble_tracker") | ||||
| ESP32BLETracker = esp32_ble_tracker_ns.class_("ESP32BLETracker", cg.Component) | ||||
| ESPBTDeviceListener = esp32_ble_tracker_ns.class_("ESPBTDeviceListener") | ||||
| ESPBTDevice = esp32_ble_tracker_ns.class_("ESPBTDevice") | ||||
| ESPBTDeviceConstRef = ESPBTDevice.operator("ref").operator("const") | ||||
| adv_data_t = cg.std_vector.template(cg.uint8) | ||||
| adv_data_t_const_ref = adv_data_t.operator('ref').operator('const') | ||||
| adv_data_t_const_ref = adv_data_t.operator("ref").operator("const") | ||||
| # Triggers | ||||
| ESPBTAdvertiseTrigger = esp32_ble_tracker_ns.class_( | ||||
|     'ESPBTAdvertiseTrigger', automation.Trigger.template(ESPBTDeviceConstRef)) | ||||
|     "ESPBTAdvertiseTrigger", automation.Trigger.template(ESPBTDeviceConstRef) | ||||
| ) | ||||
| BLEServiceDataAdvertiseTrigger = esp32_ble_tracker_ns.class_( | ||||
|     'BLEServiceDataAdvertiseTrigger', automation.Trigger.template(adv_data_t_const_ref)) | ||||
|     "BLEServiceDataAdvertiseTrigger", automation.Trigger.template(adv_data_t_const_ref) | ||||
| ) | ||||
| BLEManufacturerDataAdvertiseTrigger = esp32_ble_tracker_ns.class_( | ||||
|     'BLEManufacturerDataAdvertiseTrigger', automation.Trigger.template(adv_data_t_const_ref)) | ||||
|     "BLEManufacturerDataAdvertiseTrigger", | ||||
|     automation.Trigger.template(adv_data_t_const_ref), | ||||
| ) | ||||
|  | ||||
|  | ||||
| def validate_scan_parameters(config): | ||||
| @@ -37,19 +50,23 @@ def validate_scan_parameters(config): | ||||
|     window = config[CONF_WINDOW] | ||||
|  | ||||
|     if window > interval: | ||||
|         raise cv.Invalid("Scan window ({}) needs to be smaller than scan interval ({})" | ||||
|                          "".format(window, interval)) | ||||
|         raise cv.Invalid( | ||||
|             "Scan window ({}) needs to be smaller than scan interval ({})" | ||||
|             "".format(window, interval) | ||||
|         ) | ||||
|  | ||||
|     if interval.total_milliseconds * 3 > duration.total_milliseconds: | ||||
|         raise cv.Invalid("Scan duration needs to be at least three times the scan interval to" | ||||
|                          "cover all BLE channels.") | ||||
|         raise cv.Invalid( | ||||
|             "Scan duration needs to be at least three times the scan interval to" | ||||
|             "cover all BLE channels." | ||||
|         ) | ||||
|  | ||||
|     return config | ||||
|  | ||||
|  | ||||
| bt_uuid16_format = 'XXXX' | ||||
| bt_uuid32_format = 'XXXXXXXX' | ||||
| bt_uuid128_format = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX' | ||||
| bt_uuid16_format = "XXXX" | ||||
| bt_uuid32_format = "XXXXXXXX" | ||||
| bt_uuid128_format = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" | ||||
|  | ||||
|  | ||||
| def bt_uuid(value): | ||||
| @@ -60,67 +77,103 @@ def bt_uuid(value): | ||||
|         pattern = re.compile("^[A-F|0-9]{4,}$") | ||||
|         if not pattern.match(value): | ||||
|             raise cv.Invalid( | ||||
|                 f"Invalid hexadecimal value for 16 bit UUID format: '{in_value}'") | ||||
|                 f"Invalid hexadecimal value for 16 bit UUID format: '{in_value}'" | ||||
|             ) | ||||
|         return value | ||||
|     if len(value) == len(bt_uuid32_format): | ||||
|         pattern = re.compile("^[A-F|0-9]{8,}$") | ||||
|         if not pattern.match(value): | ||||
|             raise cv.Invalid( | ||||
|                 f"Invalid hexadecimal value for 32 bit UUID format: '{in_value}'") | ||||
|                 f"Invalid hexadecimal value for 32 bit UUID format: '{in_value}'" | ||||
|             ) | ||||
|         return value | ||||
|     if len(value) == len(bt_uuid128_format): | ||||
|         pattern = re.compile( | ||||
|             "^[A-F|0-9]{8,}-[A-F|0-9]{4,}-[A-F|0-9]{4,}-[A-F|0-9]{4,}-[A-F|0-9]{12,}$") | ||||
|             "^[A-F|0-9]{8,}-[A-F|0-9]{4,}-[A-F|0-9]{4,}-[A-F|0-9]{4,}-[A-F|0-9]{12,}$" | ||||
|         ) | ||||
|         if not pattern.match(value): | ||||
|             raise cv.Invalid( | ||||
|                 f"Invalid hexadecimal value for 128 UUID format: '{in_value}'") | ||||
|                 f"Invalid hexadecimal value for 128 UUID format: '{in_value}'" | ||||
|             ) | ||||
|         return value | ||||
|     raise cv.Invalid( | ||||
|         "Service UUID must be in 16 bit '{}', 32 bit '{}', or 128 bit '{}' format".format( | ||||
|             bt_uuid16_format, bt_uuid32_format, bt_uuid128_format)) | ||||
|             bt_uuid16_format, bt_uuid32_format, bt_uuid128_format | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|  | ||||
| def as_hex(value): | ||||
|     return cg.RawExpression(f'0x{value}ULL') | ||||
|     return cg.RawExpression(f"0x{value}ULL") | ||||
|  | ||||
|  | ||||
| def as_hex_array(value): | ||||
|     value = value.replace("-", "") | ||||
|     cpp_array = [f'0x{part}' for part in [value[i:i+2] for i in range(0, len(value), 2)]] | ||||
|     cpp_array = [ | ||||
|         f"0x{part}" for part in [value[i : i + 2] for i in range(0, len(value), 2)] | ||||
|     ] | ||||
|     return cg.RawExpression( | ||||
|         '(uint8_t*)(const uint8_t[16]){{{}}}'.format(','.join(reversed(cpp_array)))) | ||||
|         "(uint8_t*)(const uint8_t[16]){{{}}}".format(",".join(reversed(cpp_array))) | ||||
|     ) | ||||
|  | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(ESP32BLETracker), | ||||
|     cv.Optional(CONF_SCAN_PARAMETERS, default={}): cv.All(cv.Schema({ | ||||
|         cv.Optional(CONF_DURATION, default='5min'): cv.positive_time_period_seconds, | ||||
|         cv.Optional(CONF_INTERVAL, default='320ms'): cv.positive_time_period_milliseconds, | ||||
|         cv.Optional(CONF_WINDOW, default='30ms'): cv.positive_time_period_milliseconds, | ||||
|         cv.Optional(CONF_ACTIVE, default=True): cv.boolean, | ||||
|     }), validate_scan_parameters), | ||||
|     cv.Optional(CONF_ON_BLE_ADVERTISE): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESPBTAdvertiseTrigger), | ||||
|         cv.Optional(CONF_MAC_ADDRESS): cv.mac_address, | ||||
|     }), | ||||
|     cv.Optional(CONF_ON_BLE_SERVICE_DATA_ADVERTISE): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(BLEServiceDataAdvertiseTrigger), | ||||
|         cv.Optional(CONF_MAC_ADDRESS): cv.mac_address, | ||||
|         cv.Required(CONF_SERVICE_UUID): bt_uuid, | ||||
|     }), | ||||
|     cv.Optional(CONF_ON_BLE_MANUFACTURER_DATA_ADVERTISE): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(BLEManufacturerDataAdvertiseTrigger), | ||||
|         cv.Optional(CONF_MAC_ADDRESS): cv.mac_address, | ||||
|         cv.Required(CONF_MANUFACTURER_ID): bt_uuid, | ||||
|     }), | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(ESP32BLETracker), | ||||
|         cv.Optional(CONF_SCAN_PARAMETERS, default={}): cv.All( | ||||
|             cv.Schema( | ||||
|                 { | ||||
|                     cv.Optional( | ||||
|                         CONF_DURATION, default="5min" | ||||
|                     ): cv.positive_time_period_seconds, | ||||
|                     cv.Optional( | ||||
|                         CONF_INTERVAL, default="320ms" | ||||
|                     ): cv.positive_time_period_milliseconds, | ||||
|                     cv.Optional( | ||||
|                         CONF_WINDOW, default="30ms" | ||||
|                     ): cv.positive_time_period_milliseconds, | ||||
|                     cv.Optional(CONF_ACTIVE, default=True): cv.boolean, | ||||
|                 } | ||||
|             ), | ||||
|             validate_scan_parameters, | ||||
|         ), | ||||
|         cv.Optional(CONF_ON_BLE_ADVERTISE): automation.validate_automation( | ||||
|             { | ||||
|                 cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESPBTAdvertiseTrigger), | ||||
|                 cv.Optional(CONF_MAC_ADDRESS): cv.mac_address, | ||||
|             } | ||||
|         ), | ||||
|         cv.Optional(CONF_ON_BLE_SERVICE_DATA_ADVERTISE): automation.validate_automation( | ||||
|             { | ||||
|                 cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( | ||||
|                     BLEServiceDataAdvertiseTrigger | ||||
|                 ), | ||||
|                 cv.Optional(CONF_MAC_ADDRESS): cv.mac_address, | ||||
|                 cv.Required(CONF_SERVICE_UUID): bt_uuid, | ||||
|             } | ||||
|         ), | ||||
|         cv.Optional( | ||||
|             CONF_ON_BLE_MANUFACTURER_DATA_ADVERTISE | ||||
|         ): automation.validate_automation( | ||||
|             { | ||||
|                 cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( | ||||
|                     BLEManufacturerDataAdvertiseTrigger | ||||
|                 ), | ||||
|                 cv.Optional(CONF_MAC_ADDRESS): cv.mac_address, | ||||
|                 cv.Required(CONF_MANUFACTURER_ID): bt_uuid, | ||||
|             } | ||||
|         ), | ||||
|         cv.Optional("scan_interval"): cv.invalid( | ||||
|             "This option has been removed in 1.14 (Reason: " "it never had an effect)" | ||||
|         ), | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|     cv.Optional('scan_interval'): cv.invalid("This option has been removed in 1.14 (Reason: " | ||||
|                                              "it never had an effect)"), | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
| ESP_BLE_DEVICE_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(CONF_ESP32_BLE_ID): cv.use_id(ESP32BLETracker), | ||||
| }) | ||||
| ESP_BLE_DEVICE_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(CONF_ESP32_BLE_ID): cv.use_id(ESP32BLETracker), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
| @@ -135,7 +188,7 @@ def to_code(config): | ||||
|         trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) | ||||
|         if CONF_MAC_ADDRESS in conf: | ||||
|             cg.add(trigger.set_address(conf[CONF_MAC_ADDRESS].as_hex)) | ||||
|         yield automation.build_automation(trigger, [(ESPBTDeviceConstRef, 'x')], conf) | ||||
|         yield automation.build_automation(trigger, [(ESPBTDeviceConstRef, "x")], conf) | ||||
|     for conf in config.get(CONF_ON_BLE_SERVICE_DATA_ADVERTISE, []): | ||||
|         trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) | ||||
|         if len(conf[CONF_SERVICE_UUID]) == len(bt_uuid16_format): | ||||
| @@ -147,7 +200,7 @@ def to_code(config): | ||||
|             cg.add(trigger.set_service_uuid128(uuid128)) | ||||
|         if CONF_MAC_ADDRESS in conf: | ||||
|             cg.add(trigger.set_address(conf[CONF_MAC_ADDRESS].as_hex)) | ||||
|         yield automation.build_automation(trigger, [(adv_data_t_const_ref, 'x')], conf) | ||||
|         yield automation.build_automation(trigger, [(adv_data_t_const_ref, "x")], conf) | ||||
|     for conf in config.get(CONF_ON_BLE_MANUFACTURER_DATA_ADVERTISE, []): | ||||
|         trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) | ||||
|         if len(conf[CONF_MANUFACTURER_ID]) == len(bt_uuid16_format): | ||||
| @@ -159,7 +212,7 @@ def to_code(config): | ||||
|             cg.add(trigger.set_manufacturer_uuid128(uuid128)) | ||||
|         if CONF_MAC_ADDRESS in conf: | ||||
|             cg.add(trigger.set_address(conf[CONF_MAC_ADDRESS].as_hex)) | ||||
|         yield automation.build_automation(trigger, [(adv_data_t_const_ref, 'x')], conf) | ||||
|         yield automation.build_automation(trigger, [(adv_data_t_const_ref, "x")], conf) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
|   | ||||
| @@ -1,105 +1,126 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.const import CONF_FREQUENCY, CONF_ID, CONF_NAME, CONF_PIN, CONF_SCL, CONF_SDA, \ | ||||
|     ESP_PLATFORM_ESP32, CONF_DATA_PINS, CONF_RESET_PIN, CONF_RESOLUTION, CONF_BRIGHTNESS, \ | ||||
|     CONF_CONTRAST | ||||
| from esphome.const import ( | ||||
|     CONF_FREQUENCY, | ||||
|     CONF_ID, | ||||
|     CONF_NAME, | ||||
|     CONF_PIN, | ||||
|     CONF_SCL, | ||||
|     CONF_SDA, | ||||
|     ESP_PLATFORM_ESP32, | ||||
|     CONF_DATA_PINS, | ||||
|     CONF_RESET_PIN, | ||||
|     CONF_RESOLUTION, | ||||
|     CONF_BRIGHTNESS, | ||||
|     CONF_CONTRAST, | ||||
| ) | ||||
|  | ||||
| ESP_PLATFORMS = [ESP_PLATFORM_ESP32] | ||||
| DEPENDENCIES = ['api'] | ||||
| DEPENDENCIES = ["api"] | ||||
|  | ||||
| esp32_camera_ns = cg.esphome_ns.namespace('esp32_camera') | ||||
| ESP32Camera = esp32_camera_ns.class_('ESP32Camera', cg.PollingComponent, cg.Nameable) | ||||
| ESP32CameraFrameSize = esp32_camera_ns.enum('ESP32CameraFrameSize') | ||||
| esp32_camera_ns = cg.esphome_ns.namespace("esp32_camera") | ||||
| ESP32Camera = esp32_camera_ns.class_("ESP32Camera", cg.PollingComponent, cg.Nameable) | ||||
| ESP32CameraFrameSize = esp32_camera_ns.enum("ESP32CameraFrameSize") | ||||
| FRAME_SIZES = { | ||||
|     '160X120': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_160X120, | ||||
|     'QQVGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_160X120, | ||||
|     '128X160': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_128X160, | ||||
|     'QQVGA2': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_128X160, | ||||
|     '176X144': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_176X144, | ||||
|     'QCIF': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_176X144, | ||||
|     '240X176': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_240X176, | ||||
|     'HQVGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_240X176, | ||||
|     '320X240': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_320X240, | ||||
|     'QVGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_320X240, | ||||
|     '400X296': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_400X296, | ||||
|     'CIF': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_400X296, | ||||
|     '640X480': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_640X480, | ||||
|     'VGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_640X480, | ||||
|     '800X600': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_800X600, | ||||
|     'SVGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_800X600, | ||||
|     '1024X768': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1024X768, | ||||
|     'XGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1024X768, | ||||
|     '1280X1024': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1280X1024, | ||||
|     'SXGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1280X1024, | ||||
|     '1600X1200': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1600X1200, | ||||
|     'UXGA': ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1600X1200, | ||||
|     "160X120": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_160X120, | ||||
|     "QQVGA": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_160X120, | ||||
|     "128X160": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_128X160, | ||||
|     "QQVGA2": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_128X160, | ||||
|     "176X144": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_176X144, | ||||
|     "QCIF": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_176X144, | ||||
|     "240X176": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_240X176, | ||||
|     "HQVGA": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_240X176, | ||||
|     "320X240": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_320X240, | ||||
|     "QVGA": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_320X240, | ||||
|     "400X296": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_400X296, | ||||
|     "CIF": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_400X296, | ||||
|     "640X480": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_640X480, | ||||
|     "VGA": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_640X480, | ||||
|     "800X600": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_800X600, | ||||
|     "SVGA": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_800X600, | ||||
|     "1024X768": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1024X768, | ||||
|     "XGA": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1024X768, | ||||
|     "1280X1024": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1280X1024, | ||||
|     "SXGA": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1280X1024, | ||||
|     "1600X1200": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1600X1200, | ||||
|     "UXGA": ESP32CameraFrameSize.ESP32_CAMERA_SIZE_1600X1200, | ||||
| } | ||||
|  | ||||
| CONF_VSYNC_PIN = 'vsync_pin' | ||||
| CONF_HREF_PIN = 'href_pin' | ||||
| CONF_PIXEL_CLOCK_PIN = 'pixel_clock_pin' | ||||
| CONF_EXTERNAL_CLOCK = 'external_clock' | ||||
| CONF_I2C_PINS = 'i2c_pins' | ||||
| CONF_POWER_DOWN_PIN = 'power_down_pin' | ||||
| CONF_VSYNC_PIN = "vsync_pin" | ||||
| CONF_HREF_PIN = "href_pin" | ||||
| CONF_PIXEL_CLOCK_PIN = "pixel_clock_pin" | ||||
| CONF_EXTERNAL_CLOCK = "external_clock" | ||||
| CONF_I2C_PINS = "i2c_pins" | ||||
| CONF_POWER_DOWN_PIN = "power_down_pin" | ||||
|  | ||||
| CONF_MAX_FRAMERATE = 'max_framerate' | ||||
| CONF_IDLE_FRAMERATE = 'idle_framerate' | ||||
| CONF_JPEG_QUALITY = 'jpeg_quality' | ||||
| CONF_VERTICAL_FLIP = 'vertical_flip' | ||||
| CONF_HORIZONTAL_MIRROR = 'horizontal_mirror' | ||||
| CONF_SATURATION = 'saturation' | ||||
| CONF_TEST_PATTERN = 'test_pattern' | ||||
| CONF_MAX_FRAMERATE = "max_framerate" | ||||
| CONF_IDLE_FRAMERATE = "idle_framerate" | ||||
| CONF_JPEG_QUALITY = "jpeg_quality" | ||||
| CONF_VERTICAL_FLIP = "vertical_flip" | ||||
| CONF_HORIZONTAL_MIRROR = "horizontal_mirror" | ||||
| CONF_SATURATION = "saturation" | ||||
| CONF_TEST_PATTERN = "test_pattern" | ||||
|  | ||||
| camera_range_param = cv.int_range(min=-2, max=2) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(ESP32Camera), | ||||
|     cv.Required(CONF_NAME): cv.string, | ||||
|     cv.Required(CONF_DATA_PINS): cv.All([pins.input_pin], cv.Length(min=8, max=8)), | ||||
|     cv.Required(CONF_VSYNC_PIN): pins.input_pin, | ||||
|     cv.Required(CONF_HREF_PIN): pins.input_pin, | ||||
|     cv.Required(CONF_PIXEL_CLOCK_PIN): pins.input_pin, | ||||
|     cv.Required(CONF_EXTERNAL_CLOCK): cv.Schema({ | ||||
|         cv.Required(CONF_PIN): pins.output_pin, | ||||
|         cv.Optional(CONF_FREQUENCY, default='20MHz'): cv.All(cv.frequency, cv.one_of(20e6, 10e6)), | ||||
|     }), | ||||
|     cv.Required(CONF_I2C_PINS): cv.Schema({ | ||||
|         cv.Required(CONF_SDA): pins.output_pin, | ||||
|         cv.Required(CONF_SCL): pins.output_pin, | ||||
|     }), | ||||
|     cv.Optional(CONF_RESET_PIN): pins.output_pin, | ||||
|     cv.Optional(CONF_POWER_DOWN_PIN): pins.output_pin, | ||||
|  | ||||
|     cv.Optional(CONF_MAX_FRAMERATE, default='10 fps'): cv.All(cv.framerate, | ||||
|                                                               cv.Range(min=0, min_included=False, | ||||
|                                                                        max=60)), | ||||
|     cv.Optional(CONF_IDLE_FRAMERATE, default='0.1 fps'): cv.All(cv.framerate, | ||||
|                                                                 cv.Range(min=0, max=1)), | ||||
|     cv.Optional(CONF_RESOLUTION, default='640X480'): cv.enum(FRAME_SIZES, upper=True), | ||||
|     cv.Optional(CONF_JPEG_QUALITY, default=10): cv.int_range(min=10, max=63), | ||||
|     cv.Optional(CONF_CONTRAST, default=0): camera_range_param, | ||||
|     cv.Optional(CONF_BRIGHTNESS, default=0): camera_range_param, | ||||
|     cv.Optional(CONF_SATURATION, default=0): camera_range_param, | ||||
|     cv.Optional(CONF_VERTICAL_FLIP, default=True): cv.boolean, | ||||
|     cv.Optional(CONF_HORIZONTAL_MIRROR, default=True): cv.boolean, | ||||
|     cv.Optional(CONF_TEST_PATTERN, default=False): cv.boolean, | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(ESP32Camera), | ||||
|         cv.Required(CONF_NAME): cv.string, | ||||
|         cv.Required(CONF_DATA_PINS): cv.All([pins.input_pin], cv.Length(min=8, max=8)), | ||||
|         cv.Required(CONF_VSYNC_PIN): pins.input_pin, | ||||
|         cv.Required(CONF_HREF_PIN): pins.input_pin, | ||||
|         cv.Required(CONF_PIXEL_CLOCK_PIN): pins.input_pin, | ||||
|         cv.Required(CONF_EXTERNAL_CLOCK): cv.Schema( | ||||
|             { | ||||
|                 cv.Required(CONF_PIN): pins.output_pin, | ||||
|                 cv.Optional(CONF_FREQUENCY, default="20MHz"): cv.All( | ||||
|                     cv.frequency, cv.one_of(20e6, 10e6) | ||||
|                 ), | ||||
|             } | ||||
|         ), | ||||
|         cv.Required(CONF_I2C_PINS): cv.Schema( | ||||
|             { | ||||
|                 cv.Required(CONF_SDA): pins.output_pin, | ||||
|                 cv.Required(CONF_SCL): pins.output_pin, | ||||
|             } | ||||
|         ), | ||||
|         cv.Optional(CONF_RESET_PIN): pins.output_pin, | ||||
|         cv.Optional(CONF_POWER_DOWN_PIN): pins.output_pin, | ||||
|         cv.Optional(CONF_MAX_FRAMERATE, default="10 fps"): cv.All( | ||||
|             cv.framerate, cv.Range(min=0, min_included=False, max=60) | ||||
|         ), | ||||
|         cv.Optional(CONF_IDLE_FRAMERATE, default="0.1 fps"): cv.All( | ||||
|             cv.framerate, cv.Range(min=0, max=1) | ||||
|         ), | ||||
|         cv.Optional(CONF_RESOLUTION, default="640X480"): cv.enum( | ||||
|             FRAME_SIZES, upper=True | ||||
|         ), | ||||
|         cv.Optional(CONF_JPEG_QUALITY, default=10): cv.int_range(min=10, max=63), | ||||
|         cv.Optional(CONF_CONTRAST, default=0): camera_range_param, | ||||
|         cv.Optional(CONF_BRIGHTNESS, default=0): camera_range_param, | ||||
|         cv.Optional(CONF_SATURATION, default=0): camera_range_param, | ||||
|         cv.Optional(CONF_VERTICAL_FLIP, default=True): cv.boolean, | ||||
|         cv.Optional(CONF_HORIZONTAL_MIRROR, default=True): cv.boolean, | ||||
|         cv.Optional(CONF_TEST_PATTERN, default=False): cv.boolean, | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
| SETTERS = { | ||||
|     CONF_DATA_PINS: 'set_data_pins', | ||||
|     CONF_VSYNC_PIN: 'set_vsync_pin', | ||||
|     CONF_HREF_PIN: 'set_href_pin', | ||||
|     CONF_PIXEL_CLOCK_PIN: 'set_pixel_clock_pin', | ||||
|     CONF_RESET_PIN: 'set_reset_pin', | ||||
|     CONF_POWER_DOWN_PIN: 'set_power_down_pin', | ||||
|     CONF_JPEG_QUALITY: 'set_jpeg_quality', | ||||
|     CONF_VERTICAL_FLIP: 'set_vertical_flip', | ||||
|     CONF_HORIZONTAL_MIRROR: 'set_horizontal_mirror', | ||||
|     CONF_CONTRAST: 'set_contrast', | ||||
|     CONF_BRIGHTNESS: 'set_brightness', | ||||
|     CONF_SATURATION: 'set_saturation', | ||||
|     CONF_TEST_PATTERN: 'set_test_pattern', | ||||
|     CONF_DATA_PINS: "set_data_pins", | ||||
|     CONF_VSYNC_PIN: "set_vsync_pin", | ||||
|     CONF_HREF_PIN: "set_href_pin", | ||||
|     CONF_PIXEL_CLOCK_PIN: "set_pixel_clock_pin", | ||||
|     CONF_RESET_PIN: "set_reset_pin", | ||||
|     CONF_POWER_DOWN_PIN: "set_power_down_pin", | ||||
|     CONF_JPEG_QUALITY: "set_jpeg_quality", | ||||
|     CONF_VERTICAL_FLIP: "set_vertical_flip", | ||||
|     CONF_HORIZONTAL_MIRROR: "set_horizontal_mirror", | ||||
|     CONF_CONTRAST: "set_contrast", | ||||
|     CONF_BRIGHTNESS: "set_brightness", | ||||
|     CONF_SATURATION: "set_saturation", | ||||
|     CONF_TEST_PATTERN: "set_test_pattern", | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -122,5 +143,5 @@ def to_code(config): | ||||
|         cg.add(var.set_idle_update_interval(1000 / config[CONF_IDLE_FRAMERATE])) | ||||
|     cg.add(var.set_frame_size(config[CONF_RESOLUTION])) | ||||
|  | ||||
|     cg.add_define('USE_ESP32_CAMERA') | ||||
|     cg.add_build_flag('-DBOARD_HAS_PSRAM') | ||||
|     cg.add_define("USE_ESP32_CAMERA") | ||||
|     cg.add_build_flag("-DBOARD_HAS_PSRAM") | ||||
|   | ||||
| @@ -13,13 +13,17 @@ def valid_dac_pin(value): | ||||
|     return value | ||||
|  | ||||
|  | ||||
| esp32_dac_ns = cg.esphome_ns.namespace('esp32_dac') | ||||
| ESP32DAC = esp32_dac_ns.class_('ESP32DAC', output.FloatOutput, cg.Component) | ||||
| esp32_dac_ns = cg.esphome_ns.namespace("esp32_dac") | ||||
| ESP32DAC = esp32_dac_ns.class_("ESP32DAC", output.FloatOutput, cg.Component) | ||||
|  | ||||
| CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend({ | ||||
|     cv.Required(CONF_ID): cv.declare_id(ESP32DAC), | ||||
|     cv.Required(CONF_PIN): cv.All(pins.internal_gpio_output_pin_schema, valid_dac_pin), | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( | ||||
|     { | ||||
|         cv.Required(CONF_ID): cv.declare_id(ESP32DAC), | ||||
|         cv.Required(CONF_PIN): cv.All( | ||||
|             pins.internal_gpio_output_pin_schema, valid_dac_pin | ||||
|         ), | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,17 +1,30 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor | ||||
| from esphome.const import CONF_ID, DEVICE_CLASS_EMPTY, ESP_PLATFORM_ESP32, UNIT_MICROTESLA, \ | ||||
|     ICON_MAGNET | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     DEVICE_CLASS_EMPTY, | ||||
|     ESP_PLATFORM_ESP32, | ||||
|     UNIT_MICROTESLA, | ||||
|     ICON_MAGNET, | ||||
| ) | ||||
|  | ||||
| ESP_PLATFORMS = [ESP_PLATFORM_ESP32] | ||||
|  | ||||
| esp32_hall_ns = cg.esphome_ns.namespace('esp32_hall') | ||||
| ESP32HallSensor = esp32_hall_ns.class_('ESP32HallSensor', sensor.Sensor, cg.PollingComponent) | ||||
| esp32_hall_ns = cg.esphome_ns.namespace("esp32_hall") | ||||
| ESP32HallSensor = esp32_hall_ns.class_( | ||||
|     "ESP32HallSensor", sensor.Sensor, cg.PollingComponent | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = sensor.sensor_schema(UNIT_MICROTESLA, ICON_MAGNET, 1, DEVICE_CLASS_EMPTY).extend({ | ||||
|     cv.GenerateID(): cv.declare_id(ESP32HallSensor), | ||||
| }).extend(cv.polling_component_schema('60s')) | ||||
| CONFIG_SCHEMA = ( | ||||
|     sensor.sensor_schema(UNIT_MICROTESLA, ICON_MAGNET, 1, DEVICE_CLASS_EMPTY) | ||||
|     .extend( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(ESP32HallSensor), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,15 +1,23 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.const import CONF_HIGH_VOLTAGE_REFERENCE, CONF_ID, CONF_IIR_FILTER, \ | ||||
|     CONF_LOW_VOLTAGE_REFERENCE, CONF_MEASUREMENT_DURATION, CONF_SETUP_MODE, CONF_SLEEP_DURATION, \ | ||||
|     CONF_VOLTAGE_ATTENUATION, ESP_PLATFORM_ESP32 | ||||
| from esphome.const import ( | ||||
|     CONF_HIGH_VOLTAGE_REFERENCE, | ||||
|     CONF_ID, | ||||
|     CONF_IIR_FILTER, | ||||
|     CONF_LOW_VOLTAGE_REFERENCE, | ||||
|     CONF_MEASUREMENT_DURATION, | ||||
|     CONF_SETUP_MODE, | ||||
|     CONF_SLEEP_DURATION, | ||||
|     CONF_VOLTAGE_ATTENUATION, | ||||
|     ESP_PLATFORM_ESP32, | ||||
| ) | ||||
| from esphome.core import TimePeriod | ||||
|  | ||||
| AUTO_LOAD = ['binary_sensor'] | ||||
| AUTO_LOAD = ["binary_sensor"] | ||||
| ESP_PLATFORMS = [ESP_PLATFORM_ESP32] | ||||
|  | ||||
| esp32_touch_ns = cg.esphome_ns.namespace('esp32_touch') | ||||
| ESP32TouchComponent = esp32_touch_ns.class_('ESP32TouchComponent', cg.Component) | ||||
| esp32_touch_ns = cg.esphome_ns.namespace("esp32_touch") | ||||
| ESP32TouchComponent = esp32_touch_ns.class_("ESP32TouchComponent", cg.Component) | ||||
|  | ||||
|  | ||||
| def validate_voltage(values): | ||||
| @@ -17,46 +25,56 @@ def validate_voltage(values): | ||||
|         if isinstance(value, float) and value.is_integer(): | ||||
|             value = int(value) | ||||
|         value = cv.string(value) | ||||
|         if not value.endswith('V'): | ||||
|             value += 'V' | ||||
|         if not value.endswith("V"): | ||||
|             value += "V" | ||||
|         return cv.one_of(*values)(value) | ||||
|  | ||||
|     return validator | ||||
|  | ||||
|  | ||||
| LOW_VOLTAGE_REFERENCE = { | ||||
|     '0.5V': cg.global_ns.TOUCH_LVOLT_0V5, | ||||
|     '0.6V': cg.global_ns.TOUCH_LVOLT_0V6, | ||||
|     '0.7V': cg.global_ns.TOUCH_LVOLT_0V7, | ||||
|     '0.8V': cg.global_ns.TOUCH_LVOLT_0V8, | ||||
|     "0.5V": cg.global_ns.TOUCH_LVOLT_0V5, | ||||
|     "0.6V": cg.global_ns.TOUCH_LVOLT_0V6, | ||||
|     "0.7V": cg.global_ns.TOUCH_LVOLT_0V7, | ||||
|     "0.8V": cg.global_ns.TOUCH_LVOLT_0V8, | ||||
| } | ||||
| HIGH_VOLTAGE_REFERENCE = { | ||||
|     '2.4V': cg.global_ns.TOUCH_HVOLT_2V4, | ||||
|     '2.5V': cg.global_ns.TOUCH_HVOLT_2V5, | ||||
|     '2.6V': cg.global_ns.TOUCH_HVOLT_2V6, | ||||
|     '2.7V': cg.global_ns.TOUCH_HVOLT_2V7, | ||||
|     "2.4V": cg.global_ns.TOUCH_HVOLT_2V4, | ||||
|     "2.5V": cg.global_ns.TOUCH_HVOLT_2V5, | ||||
|     "2.6V": cg.global_ns.TOUCH_HVOLT_2V6, | ||||
|     "2.7V": cg.global_ns.TOUCH_HVOLT_2V7, | ||||
| } | ||||
| VOLTAGE_ATTENUATION = { | ||||
|     '1.5V': cg.global_ns.TOUCH_HVOLT_ATTEN_1V5, | ||||
|     '1V': cg.global_ns.TOUCH_HVOLT_ATTEN_1V, | ||||
|     '0.5V': cg.global_ns.TOUCH_HVOLT_ATTEN_0V5, | ||||
|     '0V': cg.global_ns.TOUCH_HVOLT_ATTEN_0V, | ||||
|     "1.5V": cg.global_ns.TOUCH_HVOLT_ATTEN_1V5, | ||||
|     "1V": cg.global_ns.TOUCH_HVOLT_ATTEN_1V, | ||||
|     "0.5V": cg.global_ns.TOUCH_HVOLT_ATTEN_0V5, | ||||
|     "0V": cg.global_ns.TOUCH_HVOLT_ATTEN_0V, | ||||
| } | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(ESP32TouchComponent), | ||||
|     cv.Optional(CONF_SETUP_MODE, default=False): cv.boolean, | ||||
|     cv.Optional(CONF_IIR_FILTER, default='0ms'): cv.positive_time_period_milliseconds, | ||||
|     cv.Optional(CONF_SLEEP_DURATION, default='27306us'): | ||||
|         cv.All(cv.positive_time_period, cv.Range(max=TimePeriod(microseconds=436906))), | ||||
|     cv.Optional(CONF_MEASUREMENT_DURATION, default='8192us'): | ||||
|         cv.All(cv.positive_time_period, cv.Range(max=TimePeriod(microseconds=8192))), | ||||
|     cv.Optional(CONF_LOW_VOLTAGE_REFERENCE, default='0.5V'): | ||||
|         validate_voltage(LOW_VOLTAGE_REFERENCE), | ||||
|     cv.Optional(CONF_HIGH_VOLTAGE_REFERENCE, default='2.7V'): | ||||
|         validate_voltage(HIGH_VOLTAGE_REFERENCE), | ||||
|     cv.Optional(CONF_VOLTAGE_ATTENUATION, default='0V'): validate_voltage(VOLTAGE_ATTENUATION), | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(ESP32TouchComponent), | ||||
|         cv.Optional(CONF_SETUP_MODE, default=False): cv.boolean, | ||||
|         cv.Optional( | ||||
|             CONF_IIR_FILTER, default="0ms" | ||||
|         ): cv.positive_time_period_milliseconds, | ||||
|         cv.Optional(CONF_SLEEP_DURATION, default="27306us"): cv.All( | ||||
|             cv.positive_time_period, cv.Range(max=TimePeriod(microseconds=436906)) | ||||
|         ), | ||||
|         cv.Optional(CONF_MEASUREMENT_DURATION, default="8192us"): cv.All( | ||||
|             cv.positive_time_period, cv.Range(max=TimePeriod(microseconds=8192)) | ||||
|         ), | ||||
|         cv.Optional(CONF_LOW_VOLTAGE_REFERENCE, default="0.5V"): validate_voltage( | ||||
|             LOW_VOLTAGE_REFERENCE | ||||
|         ), | ||||
|         cv.Optional(CONF_HIGH_VOLTAGE_REFERENCE, default="2.7V"): validate_voltage( | ||||
|             HIGH_VOLTAGE_REFERENCE | ||||
|         ), | ||||
|         cv.Optional(CONF_VOLTAGE_ATTENUATION, default="0V"): validate_voltage( | ||||
|             VOLTAGE_ATTENUATION | ||||
|         ), | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
| @@ -69,12 +87,23 @@ def to_code(config): | ||||
|     sleep_duration = int(round(config[CONF_SLEEP_DURATION].total_microseconds * 0.15)) | ||||
|     cg.add(touch.set_sleep_duration(sleep_duration)) | ||||
|  | ||||
|     measurement_duration = int(round(config[CONF_MEASUREMENT_DURATION].total_microseconds * | ||||
|                                      7.99987793)) | ||||
|     measurement_duration = int( | ||||
|         round(config[CONF_MEASUREMENT_DURATION].total_microseconds * 7.99987793) | ||||
|     ) | ||||
|     cg.add(touch.set_measurement_duration(measurement_duration)) | ||||
|  | ||||
|     cg.add(touch.set_low_voltage_reference( | ||||
|         LOW_VOLTAGE_REFERENCE[config[CONF_LOW_VOLTAGE_REFERENCE]])) | ||||
|     cg.add(touch.set_high_voltage_reference( | ||||
|         HIGH_VOLTAGE_REFERENCE[config[CONF_HIGH_VOLTAGE_REFERENCE]])) | ||||
|     cg.add(touch.set_voltage_attenuation(VOLTAGE_ATTENUATION[config[CONF_VOLTAGE_ATTENUATION]])) | ||||
|     cg.add( | ||||
|         touch.set_low_voltage_reference( | ||||
|             LOW_VOLTAGE_REFERENCE[config[CONF_LOW_VOLTAGE_REFERENCE]] | ||||
|         ) | ||||
|     ) | ||||
|     cg.add( | ||||
|         touch.set_high_voltage_reference( | ||||
|             HIGH_VOLTAGE_REFERENCE[config[CONF_HIGH_VOLTAGE_REFERENCE]] | ||||
|         ) | ||||
|     ) | ||||
|     cg.add( | ||||
|         touch.set_voltage_attenuation( | ||||
|             VOLTAGE_ATTENUATION[config[CONF_VOLTAGE_ATTENUATION]] | ||||
|         ) | ||||
|     ) | ||||
|   | ||||
| @@ -1,14 +1,20 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import binary_sensor | ||||
| from esphome.const import CONF_NAME, CONF_PIN, CONF_THRESHOLD, ESP_PLATFORM_ESP32, CONF_ID | ||||
| from esphome.const import ( | ||||
|     CONF_NAME, | ||||
|     CONF_PIN, | ||||
|     CONF_THRESHOLD, | ||||
|     ESP_PLATFORM_ESP32, | ||||
|     CONF_ID, | ||||
| ) | ||||
| from esphome.pins import validate_gpio_pin | ||||
| from . import esp32_touch_ns, ESP32TouchComponent | ||||
|  | ||||
| ESP_PLATFORMS = [ESP_PLATFORM_ESP32] | ||||
| DEPENDENCIES = ['esp32_touch'] | ||||
| DEPENDENCIES = ["esp32_touch"] | ||||
|  | ||||
| CONF_ESP32_TOUCH_ID = 'esp32_touch_id' | ||||
| CONF_ESP32_TOUCH_ID = "esp32_touch_id" | ||||
|  | ||||
| TOUCH_PADS = { | ||||
|     4: cg.global_ns.TOUCH_PAD_NUM0, | ||||
| @@ -31,19 +37,27 @@ def validate_touch_pad(value): | ||||
|     return value | ||||
|  | ||||
|  | ||||
| ESP32TouchBinarySensor = esp32_touch_ns.class_('ESP32TouchBinarySensor', binary_sensor.BinarySensor) | ||||
| ESP32TouchBinarySensor = esp32_touch_ns.class_( | ||||
|     "ESP32TouchBinarySensor", binary_sensor.BinarySensor | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(ESP32TouchBinarySensor), | ||||
|     cv.GenerateID(CONF_ESP32_TOUCH_ID): cv.use_id(ESP32TouchComponent), | ||||
|     cv.Required(CONF_PIN): validate_touch_pad, | ||||
|     cv.Required(CONF_THRESHOLD): cv.uint16_t, | ||||
| }) | ||||
| CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(ESP32TouchBinarySensor), | ||||
|         cv.GenerateID(CONF_ESP32_TOUCH_ID): cv.use_id(ESP32TouchComponent), | ||||
|         cv.Required(CONF_PIN): validate_touch_pad, | ||||
|         cv.Required(CONF_THRESHOLD): cv.uint16_t, | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     hub = yield cg.get_variable(config[CONF_ESP32_TOUCH_ID]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME], TOUCH_PADS[config[CONF_PIN]], | ||||
|                            config[CONF_THRESHOLD]) | ||||
|     var = cg.new_Pvariable( | ||||
|         config[CONF_ID], | ||||
|         config[CONF_NAME], | ||||
|         TOUCH_PADS[config[CONF_PIN]], | ||||
|         config[CONF_THRESHOLD], | ||||
|     ) | ||||
|     yield binary_sensor.register_binary_sensor(var, config) | ||||
|     cg.add(hub.register_touch_pad(var)) | ||||
|   | ||||
| @@ -2,7 +2,13 @@ from esphome import pins, automation | ||||
| from esphome.components import output | ||||
| import esphome.config_validation as cv | ||||
| import esphome.codegen as cg | ||||
| from esphome.const import CONF_FREQUENCY, CONF_ID, CONF_NUMBER, CONF_PIN, ESP_PLATFORM_ESP8266 | ||||
| from esphome.const import ( | ||||
|     CONF_FREQUENCY, | ||||
|     CONF_ID, | ||||
|     CONF_NUMBER, | ||||
|     CONF_PIN, | ||||
|     ESP_PLATFORM_ESP8266, | ||||
| ) | ||||
|  | ||||
| ESP_PLATFORMS = [ESP_PLATFORM_ESP8266] | ||||
|  | ||||
| @@ -13,16 +19,20 @@ def valid_pwm_pin(value): | ||||
|     return value | ||||
|  | ||||
|  | ||||
| esp8266_pwm_ns = cg.esphome_ns.namespace('esp8266_pwm') | ||||
| ESP8266PWM = esp8266_pwm_ns.class_('ESP8266PWM', output.FloatOutput, cg.Component) | ||||
| SetFrequencyAction = esp8266_pwm_ns.class_('SetFrequencyAction', automation.Action) | ||||
| esp8266_pwm_ns = cg.esphome_ns.namespace("esp8266_pwm") | ||||
| ESP8266PWM = esp8266_pwm_ns.class_("ESP8266PWM", output.FloatOutput, cg.Component) | ||||
| SetFrequencyAction = esp8266_pwm_ns.class_("SetFrequencyAction", automation.Action) | ||||
| validate_frequency = cv.All(cv.frequency, cv.Range(min=1.0e-6)) | ||||
|  | ||||
| CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend({ | ||||
|     cv.Required(CONF_ID): cv.declare_id(ESP8266PWM), | ||||
|     cv.Required(CONF_PIN): cv.All(pins.internal_gpio_output_pin_schema, valid_pwm_pin), | ||||
|     cv.Optional(CONF_FREQUENCY, default='1kHz'): validate_frequency, | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( | ||||
|     { | ||||
|         cv.Required(CONF_ID): cv.declare_id(ESP8266PWM), | ||||
|         cv.Required(CONF_PIN): cv.All( | ||||
|             pins.internal_gpio_output_pin_schema, valid_pwm_pin | ||||
|         ), | ||||
|         cv.Optional(CONF_FREQUENCY, default="1kHz"): validate_frequency, | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
| @@ -36,10 +46,16 @@ def to_code(config): | ||||
|     cg.add(var.set_frequency(config[CONF_FREQUENCY])) | ||||
|  | ||||
|  | ||||
| @automation.register_action('output.esp8266_pwm.set_frequency', SetFrequencyAction, cv.Schema({ | ||||
|     cv.Required(CONF_ID): cv.use_id(ESP8266PWM), | ||||
|     cv.Required(CONF_FREQUENCY): cv.templatable(validate_frequency), | ||||
| })) | ||||
| @automation.register_action( | ||||
|     "output.esp8266_pwm.set_frequency", | ||||
|     SetFrequencyAction, | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.Required(CONF_ID): cv.use_id(ESP8266PWM), | ||||
|             cv.Required(CONF_FREQUENCY): cv.templatable(validate_frequency), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def esp8266_set_frequency_to_code(config, action_id, template_arg, args): | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, paren) | ||||
|   | ||||
| @@ -1,47 +1,60 @@ | ||||
| from esphome import pins | ||||
| import esphome.config_validation as cv | ||||
| import esphome.codegen as cg | ||||
| from esphome.const import CONF_DOMAIN, CONF_ID, CONF_MANUAL_IP, CONF_STATIC_IP, CONF_TYPE, \ | ||||
|     CONF_USE_ADDRESS, ESP_PLATFORM_ESP32, CONF_GATEWAY, CONF_SUBNET, CONF_DNS1, CONF_DNS2 | ||||
| from esphome.const import ( | ||||
|     CONF_DOMAIN, | ||||
|     CONF_ID, | ||||
|     CONF_MANUAL_IP, | ||||
|     CONF_STATIC_IP, | ||||
|     CONF_TYPE, | ||||
|     CONF_USE_ADDRESS, | ||||
|     ESP_PLATFORM_ESP32, | ||||
|     CONF_GATEWAY, | ||||
|     CONF_SUBNET, | ||||
|     CONF_DNS1, | ||||
|     CONF_DNS2, | ||||
| ) | ||||
| from esphome.core import CORE, coroutine_with_priority | ||||
|  | ||||
| CONFLICTS_WITH = ['wifi'] | ||||
| CONFLICTS_WITH = ["wifi"] | ||||
| ESP_PLATFORMS = [ESP_PLATFORM_ESP32] | ||||
| AUTO_LOAD = ['network'] | ||||
| AUTO_LOAD = ["network"] | ||||
|  | ||||
| ethernet_ns = cg.esphome_ns.namespace('ethernet') | ||||
| CONF_PHY_ADDR = 'phy_addr' | ||||
| CONF_MDC_PIN = 'mdc_pin' | ||||
| CONF_MDIO_PIN = 'mdio_pin' | ||||
| CONF_CLK_MODE = 'clk_mode' | ||||
| CONF_POWER_PIN = 'power_pin' | ||||
| ethernet_ns = cg.esphome_ns.namespace("ethernet") | ||||
| CONF_PHY_ADDR = "phy_addr" | ||||
| CONF_MDC_PIN = "mdc_pin" | ||||
| CONF_MDIO_PIN = "mdio_pin" | ||||
| CONF_CLK_MODE = "clk_mode" | ||||
| CONF_POWER_PIN = "power_pin" | ||||
|  | ||||
| EthernetType = ethernet_ns.enum('EthernetType') | ||||
| EthernetType = ethernet_ns.enum("EthernetType") | ||||
| ETHERNET_TYPES = { | ||||
|     'LAN8720': EthernetType.ETHERNET_TYPE_LAN8720, | ||||
|     'TLK110': EthernetType.ETHERNET_TYPE_TLK110, | ||||
|     "LAN8720": EthernetType.ETHERNET_TYPE_LAN8720, | ||||
|     "TLK110": EthernetType.ETHERNET_TYPE_TLK110, | ||||
| } | ||||
|  | ||||
| eth_clock_mode_t = cg.global_ns.enum('eth_clock_mode_t') | ||||
| eth_clock_mode_t = cg.global_ns.enum("eth_clock_mode_t") | ||||
| CLK_MODES = { | ||||
|     'GPIO0_IN': eth_clock_mode_t.ETH_CLOCK_GPIO0_IN, | ||||
|     'GPIO0_OUT': eth_clock_mode_t.ETH_CLOCK_GPIO0_OUT, | ||||
|     'GPIO16_OUT': eth_clock_mode_t.ETH_CLOCK_GPIO16_OUT, | ||||
|     'GPIO17_OUT': eth_clock_mode_t.ETH_CLOCK_GPIO17_OUT, | ||||
|     "GPIO0_IN": eth_clock_mode_t.ETH_CLOCK_GPIO0_IN, | ||||
|     "GPIO0_OUT": eth_clock_mode_t.ETH_CLOCK_GPIO0_OUT, | ||||
|     "GPIO16_OUT": eth_clock_mode_t.ETH_CLOCK_GPIO16_OUT, | ||||
|     "GPIO17_OUT": eth_clock_mode_t.ETH_CLOCK_GPIO17_OUT, | ||||
| } | ||||
|  | ||||
|  | ||||
| MANUAL_IP_SCHEMA = cv.Schema({ | ||||
|     cv.Required(CONF_STATIC_IP): cv.ipv4, | ||||
|     cv.Required(CONF_GATEWAY): cv.ipv4, | ||||
|     cv.Required(CONF_SUBNET): cv.ipv4, | ||||
|     cv.Optional(CONF_DNS1, default="0.0.0.0"): cv.ipv4, | ||||
|     cv.Optional(CONF_DNS2, default="0.0.0.0"): cv.ipv4, | ||||
| }) | ||||
| MANUAL_IP_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.Required(CONF_STATIC_IP): cv.ipv4, | ||||
|         cv.Required(CONF_GATEWAY): cv.ipv4, | ||||
|         cv.Required(CONF_SUBNET): cv.ipv4, | ||||
|         cv.Optional(CONF_DNS1, default="0.0.0.0"): cv.ipv4, | ||||
|         cv.Optional(CONF_DNS2, default="0.0.0.0"): cv.ipv4, | ||||
|     } | ||||
| ) | ||||
|  | ||||
| EthernetComponent = ethernet_ns.class_('EthernetComponent', cg.Component) | ||||
| IPAddress = cg.global_ns.class_('IPAddress') | ||||
| ManualIP = ethernet_ns.struct('ManualIP') | ||||
| EthernetComponent = ethernet_ns.class_("EthernetComponent", cg.Component) | ||||
| IPAddress = cg.global_ns.class_("IPAddress") | ||||
| ManualIP = ethernet_ns.struct("ManualIP") | ||||
|  | ||||
|  | ||||
| def validate(config): | ||||
| @@ -54,30 +67,38 @@ def validate(config): | ||||
|     return config | ||||
|  | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All(cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_id(EthernetComponent), | ||||
|     cv.Required(CONF_TYPE): cv.enum(ETHERNET_TYPES, upper=True), | ||||
|     cv.Required(CONF_MDC_PIN): pins.output_pin, | ||||
|     cv.Required(CONF_MDIO_PIN): pins.input_output_pin, | ||||
|     cv.Optional(CONF_CLK_MODE, default='GPIO0_IN'): cv.enum(CLK_MODES, upper=True, space='_'), | ||||
|     cv.Optional(CONF_PHY_ADDR, default=0): cv.int_range(min=0, max=31), | ||||
|     cv.Optional(CONF_POWER_PIN): pins.gpio_output_pin_schema, | ||||
|     cv.Optional(CONF_MANUAL_IP): MANUAL_IP_SCHEMA, | ||||
|     cv.Optional(CONF_DOMAIN, default='.local'): cv.domain_name, | ||||
|     cv.Optional(CONF_USE_ADDRESS): cv.string_strict, | ||||
|  | ||||
|     cv.Optional('hostname'): cv.invalid("The hostname option has been removed in 1.11.0"), | ||||
| }).extend(cv.COMPONENT_SCHEMA), validate) | ||||
| CONFIG_SCHEMA = cv.All( | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(EthernetComponent), | ||||
|             cv.Required(CONF_TYPE): cv.enum(ETHERNET_TYPES, upper=True), | ||||
|             cv.Required(CONF_MDC_PIN): pins.output_pin, | ||||
|             cv.Required(CONF_MDIO_PIN): pins.input_output_pin, | ||||
|             cv.Optional(CONF_CLK_MODE, default="GPIO0_IN"): cv.enum( | ||||
|                 CLK_MODES, upper=True, space="_" | ||||
|             ), | ||||
|             cv.Optional(CONF_PHY_ADDR, default=0): cv.int_range(min=0, max=31), | ||||
|             cv.Optional(CONF_POWER_PIN): pins.gpio_output_pin_schema, | ||||
|             cv.Optional(CONF_MANUAL_IP): MANUAL_IP_SCHEMA, | ||||
|             cv.Optional(CONF_DOMAIN, default=".local"): cv.domain_name, | ||||
|             cv.Optional(CONF_USE_ADDRESS): cv.string_strict, | ||||
|             cv.Optional("hostname"): cv.invalid( | ||||
|                 "The hostname option has been removed in 1.11.0" | ||||
|             ), | ||||
|         } | ||||
|     ).extend(cv.COMPONENT_SCHEMA), | ||||
|     validate, | ||||
| ) | ||||
|  | ||||
|  | ||||
| def manual_ip(config): | ||||
|     return cg.StructInitializer( | ||||
|         ManualIP, | ||||
|         ('static_ip', IPAddress(*config[CONF_STATIC_IP].args)), | ||||
|         ('gateway', IPAddress(*config[CONF_GATEWAY].args)), | ||||
|         ('subnet', IPAddress(*config[CONF_SUBNET].args)), | ||||
|         ('dns1', IPAddress(*config[CONF_DNS1].args)), | ||||
|         ('dns2', IPAddress(*config[CONF_DNS2].args)), | ||||
|         ("static_ip", IPAddress(*config[CONF_STATIC_IP].args)), | ||||
|         ("gateway", IPAddress(*config[CONF_GATEWAY].args)), | ||||
|         ("subnet", IPAddress(*config[CONF_SUBNET].args)), | ||||
|         ("dns1", IPAddress(*config[CONF_DNS1].args)), | ||||
|         ("dns2", IPAddress(*config[CONF_DNS2].args)), | ||||
|     ) | ||||
|  | ||||
|  | ||||
| @@ -100,4 +121,4 @@ def to_code(config): | ||||
|     if CONF_MANUAL_IP in config: | ||||
|         cg.add(var.set_manual_ip(manual_ip(config[CONF_MANUAL_IP]))) | ||||
|  | ||||
|     cg.add_define('USE_ETHERNET') | ||||
|     cg.add_define("USE_ETHERNET") | ||||
|   | ||||
| @@ -4,26 +4,36 @@ import esphome.config_validation as cv | ||||
| from esphome.components import esp32_ble_tracker | ||||
| from esphome.const import CONF_TRIGGER_ID | ||||
|  | ||||
| CODEOWNERS = ['@OttoWinter'] | ||||
| DEPENDENCIES = ['esp32_ble_tracker'] | ||||
| CODEOWNERS = ["@OttoWinter"] | ||||
| DEPENDENCIES = ["esp32_ble_tracker"] | ||||
|  | ||||
| exposure_notifications_ns = cg.esphome_ns.namespace('exposure_notifications') | ||||
| ExposureNotification = exposure_notifications_ns.struct('ExposureNotification') | ||||
| exposure_notifications_ns = cg.esphome_ns.namespace("exposure_notifications") | ||||
| ExposureNotification = exposure_notifications_ns.struct("ExposureNotification") | ||||
| ExposureNotificationTrigger = exposure_notifications_ns.class_( | ||||
|     'ExposureNotificationTrigger', esp32_ble_tracker.ESPBTDeviceListener, | ||||
|     automation.Trigger.template(ExposureNotification)) | ||||
|     "ExposureNotificationTrigger", | ||||
|     esp32_ble_tracker.ESPBTDeviceListener, | ||||
|     automation.Trigger.template(ExposureNotification), | ||||
| ) | ||||
|  | ||||
| CONF_ON_EXPOSURE_NOTIFICATION = 'on_exposure_notification' | ||||
| CONF_ON_EXPOSURE_NOTIFICATION = "on_exposure_notification" | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.Required(CONF_ON_EXPOSURE_NOTIFICATION): automation.validate_automation(cv.Schema({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ExposureNotificationTrigger), | ||||
|     }).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA)), | ||||
| }) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.Required(CONF_ON_EXPOSURE_NOTIFICATION): automation.validate_automation( | ||||
|             cv.Schema( | ||||
|                 { | ||||
|                     cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( | ||||
|                         ExposureNotificationTrigger | ||||
|                     ), | ||||
|                 } | ||||
|             ).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) | ||||
|         ), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     for conf in config.get(CONF_ON_EXPOSURE_NOTIFICATION, []): | ||||
|         trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID]) | ||||
|         yield automation.build_automation(trigger, [(ExposureNotification, 'x')], conf) | ||||
|         yield automation.build_automation(trigger, [(ExposureNotification, "x")], conf) | ||||
|         yield esp32_ble_tracker.register_ble_device(trigger, conf) | ||||
|   | ||||
| @@ -3,17 +3,25 @@ import esphome.config_validation as cv | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.const import CONF_ID | ||||
|  | ||||
| CODEOWNERS = ['@ssieb'] | ||||
| CODEOWNERS = ["@ssieb"] | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| DEPENDENCIES = ["i2c"] | ||||
|  | ||||
| ezo_ns = cg.esphome_ns.namespace('ezo') | ||||
| ezo_ns = cg.esphome_ns.namespace("ezo") | ||||
|  | ||||
| EZOSensor = ezo_ns.class_('EZOSensor', sensor.Sensor, cg.PollingComponent, i2c.I2CDevice) | ||||
| EZOSensor = ezo_ns.class_( | ||||
|     "EZOSensor", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(EZOSensor), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(None)) | ||||
| CONFIG_SCHEMA = ( | ||||
|     sensor.SENSOR_SCHEMA.extend( | ||||
|         { | ||||
|             cv.GenerateID(): cv.declare_id(EZOSensor), | ||||
|         } | ||||
|     ) | ||||
|     .extend(cv.polling_component_schema("60s")) | ||||
|     .extend(i2c.i2c_device_schema(None)) | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -3,42 +3,57 @@ import esphome.config_validation as cv | ||||
| from esphome import automation | ||||
| from esphome.automation import maybe_simple_id | ||||
| from esphome.components import mqtt | ||||
| from esphome.const import CONF_ID, CONF_INTERNAL, CONF_MQTT_ID, CONF_OSCILLATING, \ | ||||
|     CONF_OSCILLATION_COMMAND_TOPIC, CONF_OSCILLATION_STATE_TOPIC, CONF_SPEED, \ | ||||
|     CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_STATE_TOPIC, CONF_NAME | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     CONF_INTERNAL, | ||||
|     CONF_MQTT_ID, | ||||
|     CONF_OSCILLATING, | ||||
|     CONF_OSCILLATION_COMMAND_TOPIC, | ||||
|     CONF_OSCILLATION_STATE_TOPIC, | ||||
|     CONF_SPEED, | ||||
|     CONF_SPEED_COMMAND_TOPIC, | ||||
|     CONF_SPEED_STATE_TOPIC, | ||||
|     CONF_NAME, | ||||
| ) | ||||
| from esphome.core import CORE, coroutine, coroutine_with_priority | ||||
|  | ||||
| IS_PLATFORM_COMPONENT = True | ||||
|  | ||||
| fan_ns = cg.esphome_ns.namespace('fan') | ||||
| FanState = fan_ns.class_('FanState', cg.Nameable, cg.Component) | ||||
| MakeFan = cg.Application.struct('MakeFan') | ||||
| fan_ns = cg.esphome_ns.namespace("fan") | ||||
| FanState = fan_ns.class_("FanState", cg.Nameable, cg.Component) | ||||
| MakeFan = cg.Application.struct("MakeFan") | ||||
|  | ||||
| # Actions | ||||
| TurnOnAction = fan_ns.class_('TurnOnAction', automation.Action) | ||||
| TurnOffAction = fan_ns.class_('TurnOffAction', automation.Action) | ||||
| ToggleAction = fan_ns.class_('ToggleAction', automation.Action) | ||||
| TurnOnAction = fan_ns.class_("TurnOnAction", automation.Action) | ||||
| TurnOffAction = fan_ns.class_("TurnOffAction", automation.Action) | ||||
| ToggleAction = fan_ns.class_("ToggleAction", automation.Action) | ||||
|  | ||||
| FanSpeed = fan_ns.enum('FanSpeed') | ||||
| FanSpeed = fan_ns.enum("FanSpeed") | ||||
| FAN_SPEEDS = { | ||||
|     'OFF': FanSpeed.FAN_SPEED_OFF, | ||||
|     'LOW': FanSpeed.FAN_SPEED_LOW, | ||||
|     'MEDIUM': FanSpeed.FAN_SPEED_MEDIUM, | ||||
|     'HIGH': FanSpeed.FAN_SPEED_HIGH, | ||||
|     "OFF": FanSpeed.FAN_SPEED_OFF, | ||||
|     "LOW": FanSpeed.FAN_SPEED_LOW, | ||||
|     "MEDIUM": FanSpeed.FAN_SPEED_MEDIUM, | ||||
|     "HIGH": FanSpeed.FAN_SPEED_HIGH, | ||||
| } | ||||
|  | ||||
| FAN_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(FanState), | ||||
|     cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTFanComponent), | ||||
|     cv.Optional(CONF_OSCILLATION_STATE_TOPIC): cv.All(cv.requires_component('mqtt'), | ||||
|                                                       cv.publish_topic), | ||||
|     cv.Optional(CONF_OSCILLATION_COMMAND_TOPIC): cv.All(cv.requires_component('mqtt'), | ||||
|                                                         cv.subscribe_topic), | ||||
|     cv.Optional(CONF_SPEED_STATE_TOPIC): cv.All(cv.requires_component('mqtt'), | ||||
|                                                 cv.publish_topic), | ||||
|     cv.Optional(CONF_SPEED_COMMAND_TOPIC): cv.All(cv.requires_component('mqtt'), | ||||
|                                                   cv.subscribe_topic), | ||||
| }) | ||||
| FAN_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(FanState), | ||||
|         cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTFanComponent), | ||||
|         cv.Optional(CONF_OSCILLATION_STATE_TOPIC): cv.All( | ||||
|             cv.requires_component("mqtt"), cv.publish_topic | ||||
|         ), | ||||
|         cv.Optional(CONF_OSCILLATION_COMMAND_TOPIC): cv.All( | ||||
|             cv.requires_component("mqtt"), cv.subscribe_topic | ||||
|         ), | ||||
|         cv.Optional(CONF_SPEED_STATE_TOPIC): cv.All( | ||||
|             cv.requires_component("mqtt"), cv.publish_topic | ||||
|         ), | ||||
|         cv.Optional(CONF_SPEED_COMMAND_TOPIC): cv.All( | ||||
|             cv.requires_component("mqtt"), cv.subscribe_topic | ||||
|         ), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| @@ -52,14 +67,23 @@ def setup_fan_core_(var, config): | ||||
|         yield mqtt.register_mqtt_component(mqtt_, config) | ||||
|  | ||||
|         if CONF_OSCILLATION_STATE_TOPIC in config: | ||||
|             cg.add(mqtt_.set_custom_oscillation_state_topic(config[CONF_OSCILLATION_STATE_TOPIC])) | ||||
|             cg.add( | ||||
|                 mqtt_.set_custom_oscillation_state_topic( | ||||
|                     config[CONF_OSCILLATION_STATE_TOPIC] | ||||
|                 ) | ||||
|             ) | ||||
|         if CONF_OSCILLATION_COMMAND_TOPIC in config: | ||||
|             cg.add(mqtt_.set_custom_oscillation_command_topic( | ||||
|                 config[CONF_OSCILLATION_COMMAND_TOPIC])) | ||||
|             cg.add( | ||||
|                 mqtt_.set_custom_oscillation_command_topic( | ||||
|                     config[CONF_OSCILLATION_COMMAND_TOPIC] | ||||
|                 ) | ||||
|             ) | ||||
|         if CONF_SPEED_STATE_TOPIC in config: | ||||
|             cg.add(mqtt_.set_custom_speed_state_topic(config[CONF_SPEED_STATE_TOPIC])) | ||||
|         if CONF_SPEED_COMMAND_TOPIC in config: | ||||
|             cg.add(mqtt_.set_custom_speed_command_topic(config[CONF_SPEED_COMMAND_TOPIC])) | ||||
|             cg.add( | ||||
|                 mqtt_.set_custom_speed_command_topic(config[CONF_SPEED_COMMAND_TOPIC]) | ||||
|             ) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| @@ -78,28 +102,36 @@ def create_fan_state(config): | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| FAN_ACTION_SCHEMA = maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.use_id(FanState), | ||||
| }) | ||||
| FAN_ACTION_SCHEMA = maybe_simple_id( | ||||
|     { | ||||
|         cv.Required(CONF_ID): cv.use_id(FanState), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @automation.register_action('fan.toggle', ToggleAction, FAN_ACTION_SCHEMA) | ||||
| @automation.register_action("fan.toggle", ToggleAction, FAN_ACTION_SCHEMA) | ||||
| def fan_toggle_to_code(config, action_id, template_arg, args): | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|  | ||||
|  | ||||
| @automation.register_action('fan.turn_off', TurnOffAction, FAN_ACTION_SCHEMA) | ||||
| @automation.register_action("fan.turn_off", TurnOffAction, FAN_ACTION_SCHEMA) | ||||
| def fan_turn_off_to_code(config, action_id, template_arg, args): | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|  | ||||
|  | ||||
| @automation.register_action('fan.turn_on', TurnOnAction, maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.use_id(FanState), | ||||
|     cv.Optional(CONF_OSCILLATING): cv.templatable(cv.boolean), | ||||
|     cv.Optional(CONF_SPEED): cv.templatable(cv.enum(FAN_SPEEDS, upper=True)), | ||||
| })) | ||||
| @automation.register_action( | ||||
|     "fan.turn_on", | ||||
|     TurnOnAction, | ||||
|     maybe_simple_id( | ||||
|         { | ||||
|             cv.Required(CONF_ID): cv.use_id(FanState), | ||||
|             cv.Optional(CONF_OSCILLATING): cv.templatable(cv.boolean), | ||||
|             cv.Optional(CONF_SPEED): cv.templatable(cv.enum(FAN_SPEEDS, upper=True)), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def fan_turn_on_to_code(config, action_id, template_arg, args): | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, paren) | ||||
| @@ -114,5 +146,5 @@ def fan_turn_on_to_code(config, action_id, template_arg, args): | ||||
|  | ||||
| @coroutine_with_priority(100.0) | ||||
| def to_code(config): | ||||
|     cg.add_define('USE_FAN') | ||||
|     cg.add_define("USE_FAN") | ||||
|     cg.add_global(fan_ns.using) | ||||
|   | ||||
| @@ -1,29 +1,37 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import light | ||||
| from esphome.const import CONF_OUTPUT_ID, CONF_NUM_LEDS, CONF_RGB_ORDER, CONF_MAX_REFRESH_RATE | ||||
| from esphome.const import ( | ||||
|     CONF_OUTPUT_ID, | ||||
|     CONF_NUM_LEDS, | ||||
|     CONF_RGB_ORDER, | ||||
|     CONF_MAX_REFRESH_RATE, | ||||
| ) | ||||
| from esphome.core import coroutine | ||||
|  | ||||
| CODEOWNERS = ['@OttoWinter'] | ||||
| fastled_base_ns = cg.esphome_ns.namespace('fastled_base') | ||||
| FastLEDLightOutput = fastled_base_ns.class_('FastLEDLightOutput', light.AddressableLight) | ||||
| CODEOWNERS = ["@OttoWinter"] | ||||
| fastled_base_ns = cg.esphome_ns.namespace("fastled_base") | ||||
| FastLEDLightOutput = fastled_base_ns.class_( | ||||
|     "FastLEDLightOutput", light.AddressableLight | ||||
| ) | ||||
|  | ||||
| RGB_ORDERS = [ | ||||
|     'RGB', | ||||
|     'RBG', | ||||
|     'GRB', | ||||
|     'GBR', | ||||
|     'BRG', | ||||
|     'BGR', | ||||
|     "RGB", | ||||
|     "RBG", | ||||
|     "GRB", | ||||
|     "GBR", | ||||
|     "BRG", | ||||
|     "BGR", | ||||
| ] | ||||
|  | ||||
| BASE_SCHEMA = light.ADDRESSABLE_LIGHT_SCHEMA.extend({ | ||||
|     cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(FastLEDLightOutput), | ||||
|  | ||||
|     cv.Required(CONF_NUM_LEDS): cv.positive_not_null_int, | ||||
|     cv.Optional(CONF_RGB_ORDER): cv.one_of(*RGB_ORDERS, upper=True), | ||||
|     cv.Optional(CONF_MAX_REFRESH_RATE): cv.positive_time_period_microseconds, | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| BASE_SCHEMA = light.ADDRESSABLE_LIGHT_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(FastLEDLightOutput), | ||||
|         cv.Required(CONF_NUM_LEDS): cv.positive_not_null_int, | ||||
|         cv.Optional(CONF_RGB_ORDER): cv.one_of(*RGB_ORDERS, upper=True), | ||||
|         cv.Optional(CONF_MAX_REFRESH_RATE): cv.positive_time_period_microseconds, | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| @@ -38,5 +46,5 @@ def new_fastled_light(config): | ||||
|     # https://github.com/FastLED/FastLED/blob/master/library.json | ||||
|     # 3.3.3 has an issue on ESP32 with RMT and fastled_clockless: | ||||
|     # https://github.com/esphome/issues/issues/1375 | ||||
|     cg.add_library('FastLED', '3.3.2') | ||||
|     cg.add_library("FastLED", "3.3.2") | ||||
|     yield var | ||||
|   | ||||
| @@ -4,46 +4,51 @@ from esphome import pins | ||||
| from esphome.components import fastled_base | ||||
| from esphome.const import CONF_CHIPSET, CONF_NUM_LEDS, CONF_PIN, CONF_RGB_ORDER | ||||
|  | ||||
| AUTO_LOAD = ['fastled_base'] | ||||
| AUTO_LOAD = ["fastled_base"] | ||||
|  | ||||
| CHIPSETS = [ | ||||
|     'NEOPIXEL', | ||||
|     'TM1829', | ||||
|     'TM1809', | ||||
|     'TM1804', | ||||
|     'TM1803', | ||||
|     'UCS1903', | ||||
|     'UCS1903B', | ||||
|     'UCS1904', | ||||
|     'UCS2903', | ||||
|     'WS2812', | ||||
|     'WS2852', | ||||
|     'WS2812B', | ||||
|     'SK6812', | ||||
|     'SK6822', | ||||
|     'APA106', | ||||
|     'PL9823', | ||||
|     'WS2811', | ||||
|     'WS2813', | ||||
|     'APA104', | ||||
|     'WS2811_400', | ||||
|     'GW6205', | ||||
|     'GW6205_400', | ||||
|     'LPD1886', | ||||
|     'LPD1886_8BIT', | ||||
|     "NEOPIXEL", | ||||
|     "TM1829", | ||||
|     "TM1809", | ||||
|     "TM1804", | ||||
|     "TM1803", | ||||
|     "UCS1903", | ||||
|     "UCS1903B", | ||||
|     "UCS1904", | ||||
|     "UCS2903", | ||||
|     "WS2812", | ||||
|     "WS2852", | ||||
|     "WS2812B", | ||||
|     "SK6812", | ||||
|     "SK6822", | ||||
|     "APA106", | ||||
|     "PL9823", | ||||
|     "WS2811", | ||||
|     "WS2813", | ||||
|     "APA104", | ||||
|     "WS2811_400", | ||||
|     "GW6205", | ||||
|     "GW6205_400", | ||||
|     "LPD1886", | ||||
|     "LPD1886_8BIT", | ||||
| ] | ||||
|  | ||||
|  | ||||
| def validate(value): | ||||
|     if value[CONF_CHIPSET] == 'NEOPIXEL' and CONF_RGB_ORDER in value: | ||||
|     if value[CONF_CHIPSET] == "NEOPIXEL" and CONF_RGB_ORDER in value: | ||||
|         raise cv.Invalid("NEOPIXEL doesn't support RGB order") | ||||
|     return value | ||||
|  | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All(fastled_base.BASE_SCHEMA.extend({ | ||||
|     cv.Required(CONF_CHIPSET): cv.one_of(*CHIPSETS, upper=True), | ||||
|     cv.Required(CONF_PIN): pins.output_pin, | ||||
| }), validate) | ||||
| CONFIG_SCHEMA = cv.All( | ||||
|     fastled_base.BASE_SCHEMA.extend( | ||||
|         { | ||||
|             cv.Required(CONF_CHIPSET): cv.one_of(*CHIPSETS, upper=True), | ||||
|             cv.Required(CONF_PIN): pins.output_pin, | ||||
|         } | ||||
|     ), | ||||
|     validate, | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
| @@ -52,6 +57,7 @@ def to_code(config): | ||||
|     rgb_order = None | ||||
|     if CONF_RGB_ORDER in config: | ||||
|         rgb_order = cg.RawExpression(config[CONF_RGB_ORDER]) | ||||
|     template_args = cg.TemplateArguments(cg.RawExpression(config[CONF_CHIPSET]), | ||||
|                                          config[CONF_PIN], rgb_order) | ||||
|     template_args = cg.TemplateArguments( | ||||
|         cg.RawExpression(config[CONF_CHIPSET]), config[CONF_PIN], rgb_order | ||||
|     ) | ||||
|     cg.add(var.add_leds(template_args, config[CONF_NUM_LEDS])) | ||||
|   | ||||
| @@ -2,34 +2,44 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.components import fastled_base | ||||
| from esphome.const import CONF_CHIPSET, CONF_CLOCK_PIN, CONF_DATA_PIN, CONF_DATA_RATE, \ | ||||
|         CONF_NUM_LEDS, CONF_RGB_ORDER | ||||
| from esphome.const import ( | ||||
|     CONF_CHIPSET, | ||||
|     CONF_CLOCK_PIN, | ||||
|     CONF_DATA_PIN, | ||||
|     CONF_DATA_RATE, | ||||
|     CONF_NUM_LEDS, | ||||
|     CONF_RGB_ORDER, | ||||
| ) | ||||
|  | ||||
| AUTO_LOAD = ['fastled_base'] | ||||
| AUTO_LOAD = ["fastled_base"] | ||||
|  | ||||
| CHIPSETS = [ | ||||
|     'LPD8806', | ||||
|     'WS2801', | ||||
|     'WS2803', | ||||
|     'SM16716', | ||||
|     'P9813', | ||||
|     'APA102', | ||||
|     'SK9822', | ||||
|     'DOTSTAR', | ||||
|     "LPD8806", | ||||
|     "WS2801", | ||||
|     "WS2803", | ||||
|     "SM16716", | ||||
|     "P9813", | ||||
|     "APA102", | ||||
|     "SK9822", | ||||
|     "DOTSTAR", | ||||
| ] | ||||
|  | ||||
| CONFIG_SCHEMA = fastled_base.BASE_SCHEMA.extend({ | ||||
|     cv.Required(CONF_CHIPSET): cv.one_of(*CHIPSETS, upper=True), | ||||
|     cv.Required(CONF_DATA_PIN): pins.output_pin, | ||||
|     cv.Required(CONF_CLOCK_PIN): pins.output_pin, | ||||
|     cv.Optional(CONF_DATA_RATE): cv.frequency, | ||||
| }) | ||||
| CONFIG_SCHEMA = fastled_base.BASE_SCHEMA.extend( | ||||
|     { | ||||
|         cv.Required(CONF_CHIPSET): cv.one_of(*CHIPSETS, upper=True), | ||||
|         cv.Required(CONF_DATA_PIN): pins.output_pin, | ||||
|         cv.Required(CONF_CLOCK_PIN): pins.output_pin, | ||||
|         cv.Optional(CONF_DATA_RATE): cv.frequency, | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     var = yield fastled_base.new_fastled_light(config) | ||||
|  | ||||
|     rgb_order = cg.RawExpression(config[CONF_RGB_ORDER] if CONF_RGB_ORDER in config else "RGB") | ||||
|     rgb_order = cg.RawExpression( | ||||
|         config[CONF_RGB_ORDER] if CONF_RGB_ORDER in config else "RGB" | ||||
|     ) | ||||
|     data_rate = None | ||||
|  | ||||
|     if CONF_DATA_RATE in config: | ||||
| @@ -39,7 +49,11 @@ def to_code(config): | ||||
|         else: | ||||
|             data_rate_mhz = int(data_rate_khz / 1000) | ||||
|             data_rate = cg.RawExpression(f"DATA_RATE_MHZ({data_rate_mhz})") | ||||
|     template_args = cg.TemplateArguments(cg.RawExpression(config[CONF_CHIPSET]), | ||||
|                                          config[CONF_DATA_PIN], config[CONF_CLOCK_PIN], rgb_order, | ||||
|                                          data_rate) | ||||
|     template_args = cg.TemplateArguments( | ||||
|         cg.RawExpression(config[CONF_CHIPSET]), | ||||
|         config[CONF_DATA_PIN], | ||||
|         config[CONF_CLOCK_PIN], | ||||
|         rgb_order, | ||||
|         data_rate, | ||||
|     ) | ||||
|     cg.add(var.add_leds(template_args, config[CONF_NUM_LEDS])) | ||||
|   | ||||
| @@ -7,11 +7,11 @@ import esphome.codegen as cg | ||||
| from esphome.const import CONF_FILE, CONF_GLYPHS, CONF_ID, CONF_SIZE | ||||
| from esphome.core import CORE, HexInt | ||||
|  | ||||
| DEPENDENCIES = ['display'] | ||||
| DEPENDENCIES = ["display"] | ||||
| MULTI_CONF = True | ||||
|  | ||||
| Font = display.display_ns.class_('Font') | ||||
| Glyph = display.display_ns.class_('Glyph') | ||||
| Font = display.display_ns.class_("Font") | ||||
| Glyph = display.display_ns.class_("Glyph") | ||||
|  | ||||
|  | ||||
| def validate_glyphs(value): | ||||
| @@ -20,8 +20,8 @@ def validate_glyphs(value): | ||||
|     value = cv.Schema([cv.string])(list(value)) | ||||
|  | ||||
|     def comparator(x, y): | ||||
|         x_ = x.encode('utf-8') | ||||
|         y_ = y.encode('utf-8') | ||||
|         x_ = x.encode("utf-8") | ||||
|         y_ = y.encode("utf-8") | ||||
|  | ||||
|         for c in range(min(len(x_), len(y_))): | ||||
|             if x_[c] < y_[c]: | ||||
| @@ -43,36 +43,48 @@ def validate_pillow_installed(value): | ||||
|     try: | ||||
|         import PIL | ||||
|     except ImportError as err: | ||||
|         raise cv.Invalid("Please install the pillow python package to use this feature. " | ||||
|                          "(pip install pillow)") from err | ||||
|         raise cv.Invalid( | ||||
|             "Please install the pillow python package to use this feature. " | ||||
|             "(pip install pillow)" | ||||
|         ) from err | ||||
|  | ||||
|     if PIL.__version__[0] < '4': | ||||
|         raise cv.Invalid("Please update your pillow installation to at least 4.0.x. " | ||||
|                          "(pip install -U pillow)") | ||||
|     if PIL.__version__[0] < "4": | ||||
|         raise cv.Invalid( | ||||
|             "Please update your pillow installation to at least 4.0.x. " | ||||
|             "(pip install -U pillow)" | ||||
|         ) | ||||
|  | ||||
|     return value | ||||
|  | ||||
|  | ||||
| def validate_truetype_file(value): | ||||
|     if value.endswith('.zip'):  # for Google Fonts downloads | ||||
|         raise cv.Invalid("Please unzip the font archive '{}' first and then use the .ttf files " | ||||
|                          "inside.".format(value)) | ||||
|     if not value.endswith('.ttf'): | ||||
|         raise cv.Invalid("Only truetype (.ttf) files are supported. Please make sure you're " | ||||
|                          "using the correct format or rename the extension to .ttf") | ||||
|     if value.endswith(".zip"):  # for Google Fonts downloads | ||||
|         raise cv.Invalid( | ||||
|             "Please unzip the font archive '{}' first and then use the .ttf files " | ||||
|             "inside.".format(value) | ||||
|         ) | ||||
|     if not value.endswith(".ttf"): | ||||
|         raise cv.Invalid( | ||||
|             "Only truetype (.ttf) files are supported. Please make sure you're " | ||||
|             "using the correct format or rename the extension to .ttf" | ||||
|         ) | ||||
|     return cv.file_(value) | ||||
|  | ||||
|  | ||||
| DEFAULT_GLYPHS = ' !"%()+,-.:0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz°' | ||||
| CONF_RAW_DATA_ID = 'raw_data_id' | ||||
| DEFAULT_GLYPHS = ( | ||||
|     ' !"%()+,-.:0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz°' | ||||
| ) | ||||
| CONF_RAW_DATA_ID = "raw_data_id" | ||||
|  | ||||
| FONT_SCHEMA = cv.Schema({ | ||||
|     cv.Required(CONF_ID): cv.declare_id(Font), | ||||
|     cv.Required(CONF_FILE): validate_truetype_file, | ||||
|     cv.Optional(CONF_GLYPHS, default=DEFAULT_GLYPHS): validate_glyphs, | ||||
|     cv.Optional(CONF_SIZE, default=20): cv.int_range(min=1), | ||||
|     cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8), | ||||
| }) | ||||
| FONT_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.Required(CONF_ID): cv.declare_id(Font), | ||||
|         cv.Required(CONF_FILE): validate_truetype_file, | ||||
|         cv.Optional(CONF_GLYPHS, default=DEFAULT_GLYPHS): validate_glyphs, | ||||
|         cv.Optional(CONF_SIZE, default=20): cv.int_range(min=1), | ||||
|         cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8), | ||||
|     } | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All(validate_pillow_installed, FONT_SCHEMA) | ||||
|  | ||||
| @@ -91,7 +103,7 @@ def to_code(config): | ||||
|     glyph_args = {} | ||||
|     data = [] | ||||
|     for glyph in config[CONF_GLYPHS]: | ||||
|         mask = font.getmask(glyph, mode='1') | ||||
|         mask = font.getmask(glyph, mode="1") | ||||
|         _, (offset_x, offset_y) = font.font.getsize(glyph) | ||||
|         width, height = mask.size | ||||
|         width8 = ((width + 7) // 8) * 8 | ||||
|   | ||||
| @@ -3,14 +3,18 @@ import esphome.config_validation as cv | ||||
| from esphome.components import climate_ir | ||||
| from esphome.const import CONF_ID | ||||
|  | ||||
| AUTO_LOAD = ['climate_ir'] | ||||
| AUTO_LOAD = ["climate_ir"] | ||||
|  | ||||
| fujitsu_general_ns = cg.esphome_ns.namespace('fujitsu_general') | ||||
| FujitsuGeneralClimate = fujitsu_general_ns.class_('FujitsuGeneralClimate', climate_ir.ClimateIR) | ||||
| fujitsu_general_ns = cg.esphome_ns.namespace("fujitsu_general") | ||||
| FujitsuGeneralClimate = fujitsu_general_ns.class_( | ||||
|     "FujitsuGeneralClimate", climate_ir.ClimateIR | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = climate_ir.CLIMATE_IR_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(FujitsuGeneralClimate), | ||||
| }) | ||||
| CONFIG_SCHEMA = climate_ir.CLIMATE_IR_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(FujitsuGeneralClimate), | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -2,21 +2,29 @@ import hashlib | ||||
|  | ||||
| from esphome import config_validation as cv, automation | ||||
| from esphome import codegen as cg | ||||
| from esphome.const import CONF_ID, CONF_INITIAL_VALUE, CONF_RESTORE_VALUE, CONF_TYPE, CONF_VALUE | ||||
| from esphome.const import ( | ||||
|     CONF_ID, | ||||
|     CONF_INITIAL_VALUE, | ||||
|     CONF_RESTORE_VALUE, | ||||
|     CONF_TYPE, | ||||
|     CONF_VALUE, | ||||
| ) | ||||
| from esphome.core import coroutine_with_priority | ||||
|  | ||||
| CODEOWNERS = ['@esphome/core'] | ||||
| globals_ns = cg.esphome_ns.namespace('globals') | ||||
| GlobalsComponent = globals_ns.class_('GlobalsComponent', cg.Component) | ||||
| GlobalVarSetAction = globals_ns.class_('GlobalVarSetAction', automation.Action) | ||||
| CODEOWNERS = ["@esphome/core"] | ||||
| globals_ns = cg.esphome_ns.namespace("globals") | ||||
| GlobalsComponent = globals_ns.class_("GlobalsComponent", cg.Component) | ||||
| GlobalVarSetAction = globals_ns.class_("GlobalVarSetAction", automation.Action) | ||||
|  | ||||
| MULTI_CONF = True | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.Required(CONF_ID): cv.declare_id(GlobalsComponent), | ||||
|     cv.Required(CONF_TYPE): cv.string_strict, | ||||
|     cv.Optional(CONF_INITIAL_VALUE): cv.string_strict, | ||||
|     cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean, | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| CONFIG_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.Required(CONF_ID): cv.declare_id(GlobalsComponent), | ||||
|         cv.Required(CONF_TYPE): cv.string_strict, | ||||
|         cv.Optional(CONF_INITIAL_VALUE): cv.string_strict, | ||||
|         cv.Optional(CONF_RESTORE_VALUE, default=False): cv.boolean, | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| # Run with low priority so that namespaces are registered first | ||||
| @@ -42,15 +50,22 @@ def to_code(config): | ||||
|         cg.add(glob.set_restore_value(hash_)) | ||||
|  | ||||
|  | ||||
| @automation.register_action('globals.set', GlobalVarSetAction, cv.Schema({ | ||||
|     cv.Required(CONF_ID): cv.use_id(GlobalsComponent), | ||||
|     cv.Required(CONF_VALUE): cv.templatable(cv.string_strict), | ||||
| })) | ||||
| @automation.register_action( | ||||
|     "globals.set", | ||||
|     GlobalVarSetAction, | ||||
|     cv.Schema( | ||||
|         { | ||||
|             cv.Required(CONF_ID): cv.use_id(GlobalsComponent), | ||||
|             cv.Required(CONF_VALUE): cv.templatable(cv.string_strict), | ||||
|         } | ||||
|     ), | ||||
| ) | ||||
| def globals_set_to_code(config, action_id, template_arg, args): | ||||
|     full_id, paren = yield cg.get_variable_with_full_id(config[CONF_ID]) | ||||
|     template_arg = cg.TemplateArguments(full_id.type, *template_arg) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, paren) | ||||
|     templ = yield cg.templatable(config[CONF_VALUE], args, None, | ||||
|                                  to_exp=cg.RawExpression) | ||||
|     templ = yield cg.templatable( | ||||
|         config[CONF_VALUE], args, None, to_exp=cg.RawExpression | ||||
|     ) | ||||
|     cg.add(var.set_value(templ)) | ||||
|     yield var | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import esphome.codegen as cg | ||||
|  | ||||
| CODEOWNERS = ['@esphome/core'] | ||||
| gpio_ns = cg.esphome_ns.namespace('gpio') | ||||
| CODEOWNERS = ["@esphome/core"] | ||||
| gpio_ns = cg.esphome_ns.namespace("gpio") | ||||
|   | ||||
| @@ -5,12 +5,16 @@ from esphome.components import binary_sensor | ||||
| from esphome.const import CONF_ID, CONF_PIN | ||||
| from .. import gpio_ns | ||||
|  | ||||
| GPIOBinarySensor = gpio_ns.class_('GPIOBinarySensor', binary_sensor.BinarySensor, cg.Component) | ||||
| GPIOBinarySensor = gpio_ns.class_( | ||||
|     "GPIOBinarySensor", binary_sensor.BinarySensor, cg.Component | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(GPIOBinarySensor), | ||||
|     cv.Required(CONF_PIN): pins.gpio_input_pin_schema | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(GPIOBinarySensor), | ||||
|         cv.Required(CONF_PIN): pins.gpio_input_pin_schema, | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user