From 69879920eb21d92a8e06a16d559a5729a538456a Mon Sep 17 00:00:00 2001 From: Guillermo Ruffino Date: Sun, 7 Mar 2021 16:03:16 -0300 Subject: [PATCH] add-black (#1593) * Add black Update pre commit Update pre commit add empty line * Format with black --- .pre-commit-config.yaml | 30 +- esphome/__main__.py | 436 +- esphome/api/api_pb2.py | 5858 +++++++++++------ esphome/api/client.py | 73 +- esphome/automation.py | 167 +- esphome/codegen.py | 78 +- esphome/components/a4988/stepper.py | 18 +- esphome/components/ac_dimmer/output.py | 38 +- esphome/components/adalight/__init__.py | 16 +- esphome/components/adc/__init__.py | 2 +- esphome/components/adc/sensor.py | 52 +- esphome/components/ade7953/sensor.py | 78 +- esphome/components/ads1115/__init__.py | 24 +- esphome/components/ads1115/sensor.py | 71 +- esphome/components/aht10/sensor.py | 40 +- esphome/components/am2320/sensor.py | 42 +- esphome/components/animation/__init__.py | 54 +- esphome/components/apds9960/__init__.py | 22 +- esphome/components/apds9960/binary_sensor.py | 24 +- esphome/components/apds9960/sensor.py | 24 +- esphome/components/api/__init__.py | 176 +- esphome/components/as3935/__init__.py | 52 +- esphome/components/as3935/binary_sensor.py | 10 +- esphome/components/as3935/sensor.py | 31 +- esphome/components/as3935_i2c/__init__.py | 20 +- esphome/components/as3935_spi/__init__.py | 20 +- esphome/components/async_tcp/__init__.py | 6 +- .../components/atc_mithermometer/sensor.py | 66 +- esphome/components/atm90e32/sensor.py | 138 +- esphome/components/bang_bang/__init__.py | 2 +- esphome/components/bang_bang/climate.py | 68 +- esphome/components/bh1750/sensor.py | 41 +- esphome/components/binary/__init__.py | 2 +- esphome/components/binary/fan/__init__.py | 24 +- esphome/components/binary/light/__init__.py | 12 +- esphome/components/binary_sensor/__init__.py | 378 +- .../components/binary_sensor_map/sensor.py | 46 +- .../components/ble_presence/binary_sensor.py | 42 +- esphome/components/ble_rssi/sensor.py | 50 +- esphome/components/ble_scanner/text_sensor.py | 25 +- esphome/components/bme280/sensor.py | 110 +- esphome/components/bme680/sensor.py | 151 +- esphome/components/bmp085/sensor.py | 42 +- esphome/components/bmp280/sensor.py | 93 +- esphome/components/canbus/__init__.py | 121 +- esphome/components/captive_portal/__init__.py | 24 +- esphome/components/ccs811/sensor.py | 54 +- esphome/components/climate/__init__.py | 141 +- esphome/components/climate_ir/__init__.py | 45 +- esphome/components/climate_ir_lg/climate.py | 44 +- esphome/components/color/__init__.py | 34 +- esphome/components/coolix/climate.py | 16 +- esphome/components/cover/__init__.py | 106 +- esphome/components/cse7766/sensor.py | 49 +- esphome/components/ct_clamp/sensor.py | 36 +- esphome/components/custom/__init__.py | 2 +- .../custom/binary_sensor/__init__.py | 21 +- esphome/components/custom/climate/__init__.py | 22 +- esphome/components/custom/cover/__init__.py | 22 +- esphome/components/custom/light/__init__.py | 22 +- esphome/components/custom/output/__init__.py | 62 +- esphome/components/custom/sensor/__init__.py | 17 +- esphome/components/custom/switch/__init__.py | 26 +- .../components/custom/text_sensor/__init__.py | 28 +- .../components/custom_component/__init__.py | 25 +- esphome/components/cwww/light.py | 33 +- esphome/components/daikin/climate.py | 14 +- esphome/components/dallas/__init__.py | 22 +- esphome/components/dallas/sensor.py | 36 +- esphome/components/debug/__init__.py | 16 +- esphome/components/deep_sleep/__init__.py | 127 +- esphome/components/dfplayer/__init__.py | 277 +- esphome/components/dht/__init__.py | 2 +- esphome/components/dht/sensor.py | 58 +- esphome/components/dht12/sensor.py | 40 +- esphome/components/display/__init__.py | 91 +- esphome/components/ds1307/time.py | 44 +- esphome/components/duty_cycle/sensor.py | 31 +- esphome/components/e131/__init__.py | 48 +- esphome/components/endstop/cover.py | 57 +- .../components/esp32_ble_beacon/__init__.py | 30 +- .../components/esp32_ble_tracker/__init__.py | 183 +- esphome/components/esp32_camera/__init__.py | 199 +- esphome/components/esp32_dac/output.py | 16 +- esphome/components/esp32_hall/sensor.py | 27 +- esphome/components/esp32_touch/__init__.py | 111 +- .../components/esp32_touch/binary_sensor.py | 38 +- esphome/components/esp8266_pwm/output.py | 42 +- esphome/components/ethernet/__init__.py | 117 +- .../exposure_notifications/__init__.py | 36 +- esphome/components/ezo/sensor.py | 22 +- esphome/components/fan/__init__.py | 114 +- esphome/components/fastled_base/__init__.py | 44 +- esphome/components/fastled_clockless/light.py | 70 +- esphome/components/fastled_spi/light.py | 56 +- esphome/components/font/__init__.py | 64 +- esphome/components/fujitsu_general/climate.py | 16 +- esphome/components/globals/__init__.py | 49 +- esphome/components/gpio/__init__.py | 4 +- .../components/gpio/binary_sensor/__init__.py | 14 +- esphome/components/gpio/output/__init__.py | 13 +- esphome/components/gpio/switch/__init__.py | 35 +- esphome/components/gps/__init__.py | 24 +- esphome/components/gps/time/__init__.py | 16 +- esphome/components/hbridge/light.py | 18 +- esphome/components/hdc1080/sensor.py | 42 +- esphome/components/hitachi_ac344/climate.py | 14 +- esphome/components/hlw8012/sensor.py | 89 +- esphome/components/hm3301/sensor.py | 87 +- esphome/components/hmc5883l/sensor.py | 80 +- esphome/components/homeassistant/__init__.py | 4 +- .../homeassistant/binary_sensor/__init__.py | 18 +- .../homeassistant/sensor/__init__.py | 27 +- .../homeassistant/text_sensor/__init__.py | 17 +- .../components/homeassistant/time/__init__.py | 14 +- esphome/components/http_request/__init__.py | 173 +- esphome/components/htu21d/sensor.py | 42 +- esphome/components/hx711/sensor.py | 36 +- esphome/components/i2c/__init__.py | 40 +- esphome/components/ili9341/display.py | 62 +- esphome/components/image/__init__.py | 59 +- esphome/components/ina219/sensor.py | 72 +- esphome/components/ina226/sensor.py | 66 +- esphome/components/ina3221/sensor.py | 80 +- .../components/inkbird_ibsth1_mini/sensor.py | 54 +- esphome/components/inkplate6/__init__.py | 2 +- esphome/components/inkplate6/display.py | 142 +- esphome/components/integration/__init__.py | 2 +- esphome/components/integration/sensor.py | 63 +- esphome/components/interval/__init__.py | 21 +- esphome/components/json/__init__.py | 8 +- esphome/components/lcd_base/__init__.py | 12 +- esphome/components/lcd_gpio/display.py | 48 +- esphome/components/lcd_pcf8574/display.py | 26 +- esphome/components/ledc/__init__.py | 2 +- esphome/components/ledc/output.py | 69 +- esphome/components/light/__init__.py | 140 +- esphome/components/light/automation.py | 214 +- esphome/components/light/effects.py | 425 +- esphome/components/light/types.py | 87 +- esphome/components/logger/__init__.py | 220 +- esphome/components/max31855/sensor.py | 34 +- esphome/components/max31856/sensor.py | 39 +- esphome/components/max31865/sensor.py | 52 +- esphome/components/max6675/sensor.py | 20 +- esphome/components/max7219/display.py | 36 +- esphome/components/mcp23008/__init__.py | 81 +- esphome/components/mcp23016/__init__.py | 69 +- esphome/components/mcp23017/__init__.py | 81 +- esphome/components/mcp23s08/__init__.py | 75 +- esphome/components/mcp23s17/__init__.py | 75 +- esphome/components/mcp2515/canbus.py | 38 +- esphome/components/mcp3008/__init__.py | 18 +- esphome/components/mcp3008/sensor.py | 36 +- esphome/components/mcp4725/output.py | 18 +- esphome/components/mcp9808/sensor.py | 24 +- esphome/components/mhz19/sensor.py | 76 +- esphome/components/mitsubishi/climate.py | 14 +- esphome/components/modbus/__init__.py | 22 +- esphome/components/monochromatic/light.py | 16 +- esphome/components/mpr121/__init__.py | 34 +- esphome/components/mpr121/binary_sensor.py | 29 +- esphome/components/mpu6050/sensor.py | 85 +- esphome/components/mqtt/__init__.py | 318 +- esphome/components/mqtt_subscribe/__init__.py | 2 +- .../mqtt_subscribe/sensor/__init__.py | 35 +- .../mqtt_subscribe/text_sensor/__init__.py | 23 +- esphome/components/ms5611/sensor.py | 44 +- esphome/components/my9231/__init__.py | 34 +- esphome/components/my9231/output.py | 19 +- esphome/components/neopixelbus/light.py | 176 +- esphome/components/network/__init__.py | 2 +- esphome/components/nextion/__init__.py | 2 +- esphome/components/nextion/binary_sensor.py | 23 +- esphome/components/nextion/display.py | 27 +- esphome/components/nfc/__init__.py | 6 +- esphome/components/ntc/sensor.py | 109 +- esphome/components/ota/__init__.py | 45 +- esphome/components/output/__init__.py | 76 +- esphome/components/output/switch/__init__.py | 12 +- esphome/components/packages/__init__.py | 7 +- esphome/components/partition/light.py | 45 +- esphome/components/pca9685/__init__.py | 23 +- esphome/components/pca9685/output.py | 19 +- esphome/components/pcd8544/display.py | 43 +- esphome/components/pcf8574/__init__.py | 76 +- esphome/components/pid/__init__.py | 2 +- esphome/components/pid/climate.py | 121 +- esphome/components/pid/sensor/__init__.py | 51 +- esphome/components/pmsx003/sensor.py | 103 +- esphome/components/pn532/__init__.py | 75 +- esphome/components/pn532/binary_sensor.py | 34 +- esphome/components/pn532_i2c/__init__.py | 20 +- esphome/components/pn532_spi/__init__.py | 20 +- esphome/components/power_supply/__init__.py | 26 +- esphome/components/prometheus/__init__.py | 20 +- esphome/components/pulse_counter/sensor.py | 89 +- esphome/components/pulse_width/sensor.py | 23 +- esphome/components/pzem004t/sensor.py | 56 +- esphome/components/pzemac/sensor.py | 74 +- esphome/components/pzemdc/sensor.py | 47 +- esphome/components/qmc5883l/sensor.py | 79 +- esphome/components/rc522/__init__.py | 34 +- esphome/components/rc522/binary_sensor.py | 34 +- esphome/components/rc522_i2c/__init__.py | 20 +- esphome/components/rc522_spi/__init__.py | 20 +- esphome/components/rc522_spi/binary_sensor.py | 2 +- esphome/components/rdm6300/__init__.py | 34 +- esphome/components/rdm6300/binary_sensor.py | 20 +- esphome/components/remote_base/__init__.py | 820 ++- .../components/remote_receiver/__init__.py | 57 +- .../remote_receiver/binary_sensor.py | 2 +- .../components/remote_transmitter/__init__.py | 24 +- .../components/remote_transmitter/switch.py | 27 +- esphome/components/resistance/sensor.py | 36 +- esphome/components/restart/__init__.py | 2 +- esphome/components/restart/switch.py | 19 +- esphome/components/rf_bridge/__init__.py | 131 +- esphome/components/rgb/light.py | 18 +- esphome/components/rgbw/light.py | 24 +- esphome/components/rgbww/light.py | 47 +- esphome/components/rotary_encoder/sensor.py | 119 +- esphome/components/rtttl/__init__.py | 78 +- esphome/components/ruuvi_ble/__init__.py | 16 +- esphome/components/ruuvitag/sensor.py | 120 +- esphome/components/scd30/sensor.py | 79 +- esphome/components/script/__init__.py | 93 +- esphome/components/sds011/sensor.py | 61 +- esphome/components/senseair/sensor.py | 34 +- esphome/components/sensor/__init__.py | 470 +- esphome/components/servo/__init__.py | 74 +- esphome/components/sgp30/sensor.py | 75 +- esphome/components/sht3xd/sensor.py | 42 +- esphome/components/shtcx/sensor.py | 42 +- esphome/components/shutdown/__init__.py | 2 +- esphome/components/shutdown/switch.py | 20 +- esphome/components/sim800l/__init__.py | 80 +- esphome/components/sm16716/__init__.py | 31 +- esphome/components/sm16716/output.py | 18 +- esphome/components/sm300d2/sensor.py | 85 +- esphome/components/sn74hc595/__init__.py | 57 +- esphome/components/sntp/time.py | 23 +- esphome/components/speed/__init__.py | 2 +- esphome/components/speed/fan/__init__.py | 40 +- esphome/components/spi/__init__.py | 35 +- esphome/components/sps30/sensor.py | 104 +- esphome/components/ssd1306_base/__init__.py | 48 +- esphome/components/ssd1306_i2c/display.py | 22 +- esphome/components/ssd1306_spi/display.py | 24 +- esphome/components/ssd1322_base/__init__.py | 36 +- esphome/components/ssd1322_spi/display.py | 26 +- esphome/components/ssd1325_base/__init__.py | 44 +- esphome/components/ssd1325_spi/display.py | 26 +- esphome/components/ssd1327_base/__init__.py | 25 +- esphome/components/ssd1327_i2c/display.py | 24 +- esphome/components/ssd1327_spi/display.py | 26 +- esphome/components/ssd1331_base/__init__.py | 19 +- esphome/components/ssd1331_spi/display.py | 26 +- esphome/components/ssd1351_base/__init__.py | 27 +- esphome/components/ssd1351_spi/display.py | 26 +- esphome/components/st7735/__init__.py | 3 +- esphome/components/st7789v/__init__.py | 2 +- esphome/components/st7789v/display.py | 47 +- esphome/components/status/binary_sensor.py | 20 +- esphome/components/status_led/__init__.py | 16 +- esphome/components/stepper/__init__.py | 87 +- esphome/components/sts3x/sensor.py | 22 +- esphome/components/substitutions/__init__.py | 45 +- esphome/components/sun/__init__.py | 105 +- esphome/components/sun/sensor/__init__.py | 36 +- .../components/sun/text_sensor/__init__.py | 43 +- esphome/components/switch/__init__.py | 88 +- esphome/components/sx1509/__init__.py | 108 +- .../sx1509/binary_sensor/__init__.py | 22 +- esphome/components/sx1509/output/__init__.py | 19 +- esphome/components/tcl112/climate.py | 16 +- esphome/components/tcs34725/sensor.py | 102 +- esphome/components/teleinfo/__init__.py | 2 +- esphome/components/teleinfo/sensor.py | 43 +- esphome/components/template/__init__.py | 2 +- .../template/binary_sensor/__init__.py | 36 +- esphome/components/template/cover/__init__.py | 123 +- .../components/template/output/__init__.py | 49 +- .../components/template/sensor/__init__.py | 48 +- .../components/template/switch/__init__.py | 63 +- .../template/text_sensor/__init__.py | 34 +- esphome/components/text_sensor/__init__.py | 67 +- esphome/components/thermostat/climate.py | 408 +- esphome/components/time/__init__.py | 269 +- esphome/components/time_based/cover.py | 54 +- esphome/components/tlc59208f/__init__.py | 18 +- esphome/components/tlc59208f/output.py | 19 +- esphome/components/tm1637/display.py | 38 +- esphome/components/tm1651/__init__.py | 96 +- esphome/components/tmp102/sensor.py | 24 +- esphome/components/tmp117/sensor.py | 33 +- esphome/components/toshiba/climate.py | 14 +- .../components/total_daily_energy/sensor.py | 22 +- esphome/components/tsl2561/sensor.py | 50 +- esphome/components/ttp229_bsf/__init__.py | 22 +- .../components/ttp229_bsf/binary_sensor.py | 16 +- esphome/components/ttp229_lsf/__init__.py | 24 +- .../components/ttp229_lsf/binary_sensor.py | 16 +- esphome/components/tuya/__init__.py | 26 +- .../components/tuya/binary_sensor/__init__.py | 20 +- esphome/components/tuya/climate/__init__.py | 111 +- esphome/components/tuya/fan/__init__.py | 24 +- esphome/components/tuya/light/__init__.py | 49 +- esphome/components/tuya/sensor/__init__.py | 18 +- esphome/components/tuya/switch/__init__.py | 18 +- esphome/components/tx20/sensor.py | 41 +- esphome/components/uart/__init__.py | 97 +- esphome/components/uart/switch/__init__.py | 24 +- esphome/components/uln2003/stepper.py | 45 +- esphome/components/ultrasonic/__init__.py | 2 +- esphome/components/ultrasonic/sensor.py | 57 +- esphome/components/uptime/sensor.py | 16 +- esphome/components/version/__init__.py | 2 +- esphome/components/version/text_sensor.py | 18 +- esphome/components/vl53l0x/sensor.py | 48 +- .../components/voltage_sampler/__init__.py | 4 +- .../components/waveshare_epaper/display.py | 120 +- esphome/components/web_server/__init__.py | 61 +- .../components/web_server_base/__init__.py | 24 +- esphome/components/whirlpool/climate.py | 24 +- esphome/components/wifi/__init__.py | 242 +- esphome/components/wifi/wpa2_eap.py | 49 +- esphome/components/wifi_info/text_sensor.py | 64 +- esphome/components/wifi_signal/sensor.py | 29 +- esphome/components/wled/__init__.py | 15 +- esphome/components/xiaomi_ble/__init__.py | 16 +- esphome/components/xiaomi_cgd1/sensor.py | 59 +- esphome/components/xiaomi_cgg1/sensor.py | 54 +- esphome/components/xiaomi_gcls002/sensor.py | 67 +- esphome/components/xiaomi_hhccjcy01/sensor.py | 75 +- .../components/xiaomi_hhccpot002/sensor.py | 48 +- esphome/components/xiaomi_jqjcy01ym/sensor.py | 70 +- esphome/components/xiaomi_lywsd02/sensor.py | 56 +- .../components/xiaomi_lywsd03mmc/sensor.py | 62 +- esphome/components/xiaomi_lywsdcgq/sensor.py | 56 +- esphome/components/xiaomi_mhoc401/sensor.py | 62 +- esphome/components/xiaomi_miscale/sensor.py | 39 +- esphome/components/xiaomi_miscale2/sensor.py | 47 +- .../xiaomi_mjyd02yla/binary_sensor.py | 81 +- .../xiaomi_mue4094rt/binary_sensor.py | 36 +- .../components/xiaomi_wx08zm/binary_sensor.py | 50 +- esphome/components/yashima/climate.py | 26 +- esphome/components/zyaura/sensor.py | 56 +- esphome/config.py | 290 +- esphome/config_helpers.py | 21 +- esphome/config_validation.py | 713 +- esphome/const.py | 1360 ++-- esphome/core.py | 207 +- esphome/core_config.py | 246 +- esphome/cpp_generator.py | 237 +- esphome/cpp_helpers.py | 20 +- esphome/cpp_types.py | 56 +- esphome/dashboard/dashboard.py | 327 +- esphome/espota2.py | 117 +- esphome/helpers.py | 79 +- esphome/legacy.py | 2 +- esphome/mqtt.py | 66 +- esphome/pins.py | 1215 +++- esphome/platformio_api.py | 123 +- esphome/storage_json.py | 133 +- esphome/util.py | 60 +- esphome/voluptuous_schema.py | 53 +- esphome/vscode.py | 46 +- esphome/wizard.py | 243 +- esphome/writer.py | 233 +- esphome/yaml_util.py | 144 +- esphome/zeroconf.py | 144 +- pylintrc | 1 + pyproject.toml | 3 + requirements_test.txt | 2 + script/api_protobuf/api_options_pb2.py | 300 +- script/api_protobuf/api_protobuf.py | 542 +- script/build_codeowners.py | 37 +- script/build_compile_commands.py | 2 +- script/bump-docker-base-version.py | 20 +- script/bump-version.py | 29 +- script/ci-custom.py | 463 +- script/helpers.py | 95 +- script/lint-python | 46 +- script/setup | 2 + setup.cfg | 39 + .../binary_sensor/test_binary_sensor.py | 16 +- tests/component_tests/sensor/test_sensor.py | 4 +- tests/unit_tests/conftest.py | 1 - tests/unit_tests/strategies.py | 4 +- tests/unit_tests/test_codegen.py | 88 +- tests/unit_tests/test_config_validation.py | 24 +- tests/unit_tests/test_core.py | 371 +- tests/unit_tests/test_cpp_generator.py | 150 +- tests/unit_tests/test_cpp_helpers.py | 19 +- tests/unit_tests/test_helpers.py | 139 +- tests/unit_tests/test_pins.py | 87 +- tests/unit_tests/test_wizard.py | 42 +- 398 files changed, 21624 insertions(+), 12644 deletions(-) create mode 100644 pyproject.toml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d57da791f..1e56aa17c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -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 diff --git a/esphome/__main__.py b/esphome/__main__.py index 200ab2d7d..2acd16cf9 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -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: diff --git a/esphome/api/api_pb2.py b/esphome/api/api_pb2.py index c6c8741f0..6262b752c 100644 --- a/esphome/api/api_pb2.py +++ b/esphome/api/api_pb2.py @@ -3,93 +3,85 @@ # source: api.proto import sys -_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) + +_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode("latin1")) from google.protobuf.internal import enum_type_wrapper from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database + # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() - - DESCRIPTOR = _descriptor.FileDescriptor( - name='api.proto', - package='', - syntax='proto3', - serialized_options=None, - serialized_pb=_b('\n\tapi.proto\"#\n\x0cHelloRequest\x12\x13\n\x0b\x63lient_info\x18\x01 \x01(\t\"Z\n\rHelloResponse\x12\x19\n\x11\x61pi_version_major\x18\x01 \x01(\r\x12\x19\n\x11\x61pi_version_minor\x18\x02 \x01(\r\x12\x13\n\x0bserver_info\x18\x03 \x01(\t\"\"\n\x0e\x43onnectRequest\x12\x10\n\x08password\x18\x01 \x01(\t\"+\n\x0f\x43onnectResponse\x12\x18\n\x10invalid_password\x18\x01 \x01(\x08\"\x13\n\x11\x44isconnectRequest\"\x14\n\x12\x44isconnectResponse\"\r\n\x0bPingRequest\"\x0e\n\x0cPingResponse\"\x13\n\x11\x44\x65viceInfoRequest\"\xad\x01\n\x12\x44\x65viceInfoResponse\x12\x15\n\ruses_password\x18\x01 \x01(\x08\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0bmac_address\x18\x03 \x01(\t\x12\x1c\n\x14\x65sphome_core_version\x18\x04 \x01(\t\x12\x18\n\x10\x63ompilation_time\x18\x05 \x01(\t\x12\r\n\x05model\x18\x06 \x01(\t\x12\x16\n\x0ehas_deep_sleep\x18\x07 \x01(\x08\"\x15\n\x13ListEntitiesRequest\"\x9a\x01\n ListEntitiesBinarySensorResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x14\n\x0c\x64\x65vice_class\x18\x05 \x01(\t\x12\x1f\n\x17is_status_binary_sensor\x18\x06 \x01(\x08\"s\n\x19ListEntitiesCoverResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x15\n\ris_optimistic\x18\x05 \x01(\x08\"\x90\x01\n\x17ListEntitiesFanResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x1c\n\x14supports_oscillation\x18\x05 \x01(\x08\x12\x16\n\x0esupports_speed\x18\x06 \x01(\x08\"\x8a\x02\n\x19ListEntitiesLightResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x1b\n\x13supports_brightness\x18\x05 \x01(\x08\x12\x14\n\x0csupports_rgb\x18\x06 \x01(\x08\x12\x1c\n\x14supports_white_value\x18\x07 \x01(\x08\x12\"\n\x1asupports_color_temperature\x18\x08 \x01(\x08\x12\x12\n\nmin_mireds\x18\t \x01(\x02\x12\x12\n\nmax_mireds\x18\n \x01(\x02\x12\x0f\n\x07\x65\x66\x66\x65\x63ts\x18\x0b \x03(\t\"\xa3\x01\n\x1aListEntitiesSensorResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x0c\n\x04icon\x18\x05 \x01(\t\x12\x1b\n\x13unit_of_measurement\x18\x06 \x01(\t\x12\x19\n\x11\x61\x63\x63uracy_decimals\x18\x07 \x01(\x05\"\x7f\n\x1aListEntitiesSwitchResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x0c\n\x04icon\x18\x05 \x01(\t\x12\x12\n\noptimistic\x18\x06 \x01(\x08\"o\n\x1eListEntitiesTextSensorResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x0c\n\x04icon\x18\x05 \x01(\t\"\x1a\n\x18ListEntitiesDoneResponse\"\x18\n\x16SubscribeStatesRequest\"7\n\x19\x42inarySensorStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x08\"t\n\x12\x43overStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12-\n\x05state\x18\x02 \x01(\x0e\x32\x1e.CoverStateResponse.CoverState\"\"\n\nCoverState\x12\x08\n\x04OPEN\x10\x00\x12\n\n\x06\x43LOSED\x10\x01\"]\n\x10\x46\x61nStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x08\x12\x13\n\x0boscillating\x18\x03 \x01(\x08\x12\x18\n\x05speed\x18\x04 \x01(\x0e\x32\t.FanSpeed\"\xa8\x01\n\x12LightStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x08\x12\x12\n\nbrightness\x18\x03 \x01(\x02\x12\x0b\n\x03red\x18\x04 \x01(\x02\x12\r\n\x05green\x18\x05 \x01(\x02\x12\x0c\n\x04\x62lue\x18\x06 \x01(\x02\x12\r\n\x05white\x18\x07 \x01(\x02\x12\x19\n\x11\x63olor_temperature\x18\x08 \x01(\x02\x12\x0e\n\x06\x65\x66\x66\x65\x63t\x18\t \x01(\t\"1\n\x13SensorStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x02\"1\n\x13SwitchStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x08\"5\n\x17TextSensorStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\t\"\x98\x01\n\x13\x43overCommandRequest\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\x11\n\thas_state\x18\x02 \x01(\x08\x12\x32\n\x07\x63ommand\x18\x03 \x01(\x0e\x32!.CoverCommandRequest.CoverCommand\"-\n\x0c\x43overCommand\x12\x08\n\x04OPEN\x10\x00\x12\t\n\x05\x43LOSE\x10\x01\x12\x08\n\x04STOP\x10\x02\"\x9d\x01\n\x11\x46\x61nCommandRequest\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\x11\n\thas_state\x18\x02 \x01(\x08\x12\r\n\x05state\x18\x03 \x01(\x08\x12\x11\n\thas_speed\x18\x04 \x01(\x08\x12\x18\n\x05speed\x18\x05 \x01(\x0e\x32\t.FanSpeed\x12\x17\n\x0fhas_oscillating\x18\x06 \x01(\x08\x12\x13\n\x0boscillating\x18\x07 \x01(\x08\"\x95\x03\n\x13LightCommandRequest\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\x11\n\thas_state\x18\x02 \x01(\x08\x12\r\n\x05state\x18\x03 \x01(\x08\x12\x16\n\x0ehas_brightness\x18\x04 \x01(\x08\x12\x12\n\nbrightness\x18\x05 \x01(\x02\x12\x0f\n\x07has_rgb\x18\x06 \x01(\x08\x12\x0b\n\x03red\x18\x07 \x01(\x02\x12\r\n\x05green\x18\x08 \x01(\x02\x12\x0c\n\x04\x62lue\x18\t \x01(\x02\x12\x11\n\thas_white\x18\n \x01(\x08\x12\r\n\x05white\x18\x0b \x01(\x02\x12\x1d\n\x15has_color_temperature\x18\x0c \x01(\x08\x12\x19\n\x11\x63olor_temperature\x18\r \x01(\x02\x12\x1d\n\x15has_transition_length\x18\x0e \x01(\x08\x12\x19\n\x11transition_length\x18\x0f \x01(\r\x12\x18\n\x10has_flash_length\x18\x10 \x01(\x08\x12\x14\n\x0c\x66lash_length\x18\x11 \x01(\r\x12\x12\n\nhas_effect\x18\x12 \x01(\x08\x12\x0e\n\x06\x65\x66\x66\x65\x63t\x18\x13 \x01(\t\"2\n\x14SwitchCommandRequest\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x08\"E\n\x14SubscribeLogsRequest\x12\x18\n\x05level\x18\x01 \x01(\x0e\x32\t.LogLevel\x12\x13\n\x0b\x64ump_config\x18\x02 \x01(\x08\"d\n\x15SubscribeLogsResponse\x12\x18\n\x05level\x18\x01 \x01(\x0e\x32\t.LogLevel\x12\x0b\n\x03tag\x18\x02 \x01(\t\x12\x0f\n\x07message\x18\x03 \x01(\t\x12\x13\n\x0bsend_failed\x18\x04 \x01(\x08\"\x1e\n\x1cSubscribeServiceCallsRequest\"\xdf\x02\n\x13ServiceCallResponse\x12\x0f\n\x07service\x18\x01 \x01(\t\x12,\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32\x1e.ServiceCallResponse.DataEntry\x12=\n\rdata_template\x18\x03 \x03(\x0b\x32&.ServiceCallResponse.DataTemplateEntry\x12\x36\n\tvariables\x18\x04 \x03(\x0b\x32#.ServiceCallResponse.VariablesEntry\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x33\n\x11\x44\x61taTemplateEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x30\n\x0eVariablesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"%\n#SubscribeHomeAssistantStatesRequest\"8\n#SubscribeHomeAssistantStateResponse\x12\x11\n\tentity_id\x18\x01 \x01(\t\">\n\x1aHomeAssistantStateResponse\x12\x11\n\tentity_id\x18\x01 \x01(\t\x12\r\n\x05state\x18\x02 \x01(\t\"\x10\n\x0eGetTimeRequest\"(\n\x0fGetTimeResponse\x12\x15\n\repoch_seconds\x18\x01 \x01(\x07*)\n\x08\x46\x61nSpeed\x12\x07\n\x03LOW\x10\x00\x12\n\n\x06MEDIUM\x10\x01\x12\x08\n\x04HIGH\x10\x02*]\n\x08LogLevel\x12\x08\n\x04NONE\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x08\n\x04WARN\x10\x02\x12\x08\n\x04INFO\x10\x03\x12\t\n\x05\x44\x45\x42UG\x10\x04\x12\x0b\n\x07VERBOSE\x10\x05\x12\x10\n\x0cVERY_VERBOSE\x10\x06\x62\x06proto3') + name="api.proto", + package="", + syntax="proto3", + serialized_options=None, + serialized_pb=_b( + '\n\tapi.proto"#\n\x0cHelloRequest\x12\x13\n\x0b\x63lient_info\x18\x01 \x01(\t"Z\n\rHelloResponse\x12\x19\n\x11\x61pi_version_major\x18\x01 \x01(\r\x12\x19\n\x11\x61pi_version_minor\x18\x02 \x01(\r\x12\x13\n\x0bserver_info\x18\x03 \x01(\t""\n\x0e\x43onnectRequest\x12\x10\n\x08password\x18\x01 \x01(\t"+\n\x0f\x43onnectResponse\x12\x18\n\x10invalid_password\x18\x01 \x01(\x08"\x13\n\x11\x44isconnectRequest"\x14\n\x12\x44isconnectResponse"\r\n\x0bPingRequest"\x0e\n\x0cPingResponse"\x13\n\x11\x44\x65viceInfoRequest"\xad\x01\n\x12\x44\x65viceInfoResponse\x12\x15\n\ruses_password\x18\x01 \x01(\x08\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x13\n\x0bmac_address\x18\x03 \x01(\t\x12\x1c\n\x14\x65sphome_core_version\x18\x04 \x01(\t\x12\x18\n\x10\x63ompilation_time\x18\x05 \x01(\t\x12\r\n\x05model\x18\x06 \x01(\t\x12\x16\n\x0ehas_deep_sleep\x18\x07 \x01(\x08"\x15\n\x13ListEntitiesRequest"\x9a\x01\n ListEntitiesBinarySensorResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x14\n\x0c\x64\x65vice_class\x18\x05 \x01(\t\x12\x1f\n\x17is_status_binary_sensor\x18\x06 \x01(\x08"s\n\x19ListEntitiesCoverResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x15\n\ris_optimistic\x18\x05 \x01(\x08"\x90\x01\n\x17ListEntitiesFanResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x1c\n\x14supports_oscillation\x18\x05 \x01(\x08\x12\x16\n\x0esupports_speed\x18\x06 \x01(\x08"\x8a\x02\n\x19ListEntitiesLightResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x1b\n\x13supports_brightness\x18\x05 \x01(\x08\x12\x14\n\x0csupports_rgb\x18\x06 \x01(\x08\x12\x1c\n\x14supports_white_value\x18\x07 \x01(\x08\x12"\n\x1asupports_color_temperature\x18\x08 \x01(\x08\x12\x12\n\nmin_mireds\x18\t \x01(\x02\x12\x12\n\nmax_mireds\x18\n \x01(\x02\x12\x0f\n\x07\x65\x66\x66\x65\x63ts\x18\x0b \x03(\t"\xa3\x01\n\x1aListEntitiesSensorResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x0c\n\x04icon\x18\x05 \x01(\t\x12\x1b\n\x13unit_of_measurement\x18\x06 \x01(\t\x12\x19\n\x11\x61\x63\x63uracy_decimals\x18\x07 \x01(\x05"\x7f\n\x1aListEntitiesSwitchResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x0c\n\x04icon\x18\x05 \x01(\t\x12\x12\n\noptimistic\x18\x06 \x01(\x08"o\n\x1eListEntitiesTextSensorResponse\x12\x11\n\tobject_id\x18\x01 \x01(\t\x12\x0b\n\x03key\x18\x02 \x01(\x07\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x11\n\tunique_id\x18\x04 \x01(\t\x12\x0c\n\x04icon\x18\x05 \x01(\t"\x1a\n\x18ListEntitiesDoneResponse"\x18\n\x16SubscribeStatesRequest"7\n\x19\x42inarySensorStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x08"t\n\x12\x43overStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12-\n\x05state\x18\x02 \x01(\x0e\x32\x1e.CoverStateResponse.CoverState""\n\nCoverState\x12\x08\n\x04OPEN\x10\x00\x12\n\n\x06\x43LOSED\x10\x01"]\n\x10\x46\x61nStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x08\x12\x13\n\x0boscillating\x18\x03 \x01(\x08\x12\x18\n\x05speed\x18\x04 \x01(\x0e\x32\t.FanSpeed"\xa8\x01\n\x12LightStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x08\x12\x12\n\nbrightness\x18\x03 \x01(\x02\x12\x0b\n\x03red\x18\x04 \x01(\x02\x12\r\n\x05green\x18\x05 \x01(\x02\x12\x0c\n\x04\x62lue\x18\x06 \x01(\x02\x12\r\n\x05white\x18\x07 \x01(\x02\x12\x19\n\x11\x63olor_temperature\x18\x08 \x01(\x02\x12\x0e\n\x06\x65\x66\x66\x65\x63t\x18\t \x01(\t"1\n\x13SensorStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x02"1\n\x13SwitchStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x08"5\n\x17TextSensorStateResponse\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\t"\x98\x01\n\x13\x43overCommandRequest\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\x11\n\thas_state\x18\x02 \x01(\x08\x12\x32\n\x07\x63ommand\x18\x03 \x01(\x0e\x32!.CoverCommandRequest.CoverCommand"-\n\x0c\x43overCommand\x12\x08\n\x04OPEN\x10\x00\x12\t\n\x05\x43LOSE\x10\x01\x12\x08\n\x04STOP\x10\x02"\x9d\x01\n\x11\x46\x61nCommandRequest\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\x11\n\thas_state\x18\x02 \x01(\x08\x12\r\n\x05state\x18\x03 \x01(\x08\x12\x11\n\thas_speed\x18\x04 \x01(\x08\x12\x18\n\x05speed\x18\x05 \x01(\x0e\x32\t.FanSpeed\x12\x17\n\x0fhas_oscillating\x18\x06 \x01(\x08\x12\x13\n\x0boscillating\x18\x07 \x01(\x08"\x95\x03\n\x13LightCommandRequest\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\x11\n\thas_state\x18\x02 \x01(\x08\x12\r\n\x05state\x18\x03 \x01(\x08\x12\x16\n\x0ehas_brightness\x18\x04 \x01(\x08\x12\x12\n\nbrightness\x18\x05 \x01(\x02\x12\x0f\n\x07has_rgb\x18\x06 \x01(\x08\x12\x0b\n\x03red\x18\x07 \x01(\x02\x12\r\n\x05green\x18\x08 \x01(\x02\x12\x0c\n\x04\x62lue\x18\t \x01(\x02\x12\x11\n\thas_white\x18\n \x01(\x08\x12\r\n\x05white\x18\x0b \x01(\x02\x12\x1d\n\x15has_color_temperature\x18\x0c \x01(\x08\x12\x19\n\x11\x63olor_temperature\x18\r \x01(\x02\x12\x1d\n\x15has_transition_length\x18\x0e \x01(\x08\x12\x19\n\x11transition_length\x18\x0f \x01(\r\x12\x18\n\x10has_flash_length\x18\x10 \x01(\x08\x12\x14\n\x0c\x66lash_length\x18\x11 \x01(\r\x12\x12\n\nhas_effect\x18\x12 \x01(\x08\x12\x0e\n\x06\x65\x66\x66\x65\x63t\x18\x13 \x01(\t"2\n\x14SwitchCommandRequest\x12\x0b\n\x03key\x18\x01 \x01(\x07\x12\r\n\x05state\x18\x02 \x01(\x08"E\n\x14SubscribeLogsRequest\x12\x18\n\x05level\x18\x01 \x01(\x0e\x32\t.LogLevel\x12\x13\n\x0b\x64ump_config\x18\x02 \x01(\x08"d\n\x15SubscribeLogsResponse\x12\x18\n\x05level\x18\x01 \x01(\x0e\x32\t.LogLevel\x12\x0b\n\x03tag\x18\x02 \x01(\t\x12\x0f\n\x07message\x18\x03 \x01(\t\x12\x13\n\x0bsend_failed\x18\x04 \x01(\x08"\x1e\n\x1cSubscribeServiceCallsRequest"\xdf\x02\n\x13ServiceCallResponse\x12\x0f\n\x07service\x18\x01 \x01(\t\x12,\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32\x1e.ServiceCallResponse.DataEntry\x12=\n\rdata_template\x18\x03 \x03(\x0b\x32&.ServiceCallResponse.DataTemplateEntry\x12\x36\n\tvariables\x18\x04 \x03(\x0b\x32#.ServiceCallResponse.VariablesEntry\x1a+\n\tDataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x33\n\x11\x44\x61taTemplateEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\x1a\x30\n\x0eVariablesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01"%\n#SubscribeHomeAssistantStatesRequest"8\n#SubscribeHomeAssistantStateResponse\x12\x11\n\tentity_id\x18\x01 \x01(\t">\n\x1aHomeAssistantStateResponse\x12\x11\n\tentity_id\x18\x01 \x01(\t\x12\r\n\x05state\x18\x02 \x01(\t"\x10\n\x0eGetTimeRequest"(\n\x0fGetTimeResponse\x12\x15\n\repoch_seconds\x18\x01 \x01(\x07*)\n\x08\x46\x61nSpeed\x12\x07\n\x03LOW\x10\x00\x12\n\n\x06MEDIUM\x10\x01\x12\x08\n\x04HIGH\x10\x02*]\n\x08LogLevel\x12\x08\n\x04NONE\x10\x00\x12\t\n\x05\x45RROR\x10\x01\x12\x08\n\x04WARN\x10\x02\x12\x08\n\x04INFO\x10\x03\x12\t\n\x05\x44\x45\x42UG\x10\x04\x12\x0b\n\x07VERBOSE\x10\x05\x12\x10\n\x0cVERY_VERBOSE\x10\x06\x62\x06proto3' + ), ) _FANSPEED = _descriptor.EnumDescriptor( - name='FanSpeed', - full_name='FanSpeed', - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name='LOW', index=0, number=0, - serialized_options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='MEDIUM', index=1, number=1, - serialized_options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='HIGH', index=2, number=2, - serialized_options=None, - type=None), - ], - containing_type=None, - serialized_options=None, - serialized_start=3822, - serialized_end=3863, + name="FanSpeed", + full_name="FanSpeed", + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name="LOW", index=0, number=0, serialized_options=None, type=None + ), + _descriptor.EnumValueDescriptor( + name="MEDIUM", index=1, number=1, serialized_options=None, type=None + ), + _descriptor.EnumValueDescriptor( + name="HIGH", index=2, number=2, serialized_options=None, type=None + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=3822, + serialized_end=3863, ) _sym_db.RegisterEnumDescriptor(_FANSPEED) FanSpeed = enum_type_wrapper.EnumTypeWrapper(_FANSPEED) _LOGLEVEL = _descriptor.EnumDescriptor( - name='LogLevel', - full_name='LogLevel', - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name='NONE', index=0, number=0, - serialized_options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='ERROR', index=1, number=1, - serialized_options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='WARN', index=2, number=2, - serialized_options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='INFO', index=3, number=3, - serialized_options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='DEBUG', index=4, number=4, - serialized_options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='VERBOSE', index=5, number=5, - serialized_options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='VERY_VERBOSE', index=6, number=6, - serialized_options=None, - type=None), - ], - containing_type=None, - serialized_options=None, - serialized_start=3865, - serialized_end=3958, + name="LogLevel", + full_name="LogLevel", + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name="NONE", index=0, number=0, serialized_options=None, type=None + ), + _descriptor.EnumValueDescriptor( + name="ERROR", index=1, number=1, serialized_options=None, type=None + ), + _descriptor.EnumValueDescriptor( + name="WARN", index=2, number=2, serialized_options=None, type=None + ), + _descriptor.EnumValueDescriptor( + name="INFO", index=3, number=3, serialized_options=None, type=None + ), + _descriptor.EnumValueDescriptor( + name="DEBUG", index=4, number=4, serialized_options=None, type=None + ), + _descriptor.EnumValueDescriptor( + name="VERBOSE", index=5, number=5, serialized_options=None, type=None + ), + _descriptor.EnumValueDescriptor( + name="VERY_VERBOSE", index=6, number=6, serialized_options=None, type=None + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=3865, + serialized_end=3958, ) _sym_db.RegisterEnumDescriptor(_LOGLEVEL) @@ -107,2375 +99,3895 @@ VERY_VERBOSE = 6 _COVERSTATERESPONSE_COVERSTATE = _descriptor.EnumDescriptor( - name='CoverState', - full_name='CoverStateResponse.CoverState', - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name='OPEN', index=0, number=0, - serialized_options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='CLOSED', index=1, number=1, - serialized_options=None, - type=None), - ], - containing_type=None, - serialized_options=None, - serialized_start=1808, - serialized_end=1842, + name="CoverState", + full_name="CoverStateResponse.CoverState", + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name="OPEN", index=0, number=0, serialized_options=None, type=None + ), + _descriptor.EnumValueDescriptor( + name="CLOSED", index=1, number=1, serialized_options=None, type=None + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=1808, + serialized_end=1842, ) _sym_db.RegisterEnumDescriptor(_COVERSTATERESPONSE_COVERSTATE) _COVERCOMMANDREQUEST_COVERCOMMAND = _descriptor.EnumDescriptor( - name='CoverCommand', - full_name='CoverCommandRequest.CoverCommand', - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name='OPEN', index=0, number=0, - serialized_options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='CLOSE', index=1, number=1, - serialized_options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='STOP', index=2, number=2, - serialized_options=None, - type=None), - ], - containing_type=None, - serialized_options=None, - serialized_start=2375, - serialized_end=2420, + name="CoverCommand", + full_name="CoverCommandRequest.CoverCommand", + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name="OPEN", index=0, number=0, serialized_options=None, type=None + ), + _descriptor.EnumValueDescriptor( + name="CLOSE", index=1, number=1, serialized_options=None, type=None + ), + _descriptor.EnumValueDescriptor( + name="STOP", index=2, number=2, serialized_options=None, type=None + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=2375, + serialized_end=2420, ) _sym_db.RegisterEnumDescriptor(_COVERCOMMANDREQUEST_COVERCOMMAND) _HELLOREQUEST = _descriptor.Descriptor( - name='HelloRequest', - full_name='HelloRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='client_info', full_name='HelloRequest.client_info', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=13, - serialized_end=48, + name="HelloRequest", + full_name="HelloRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="client_info", + full_name="HelloRequest.client_info", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=13, + serialized_end=48, ) _HELLORESPONSE = _descriptor.Descriptor( - name='HelloResponse', - full_name='HelloResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='api_version_major', full_name='HelloResponse.api_version_major', index=0, - number=1, type=13, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='api_version_minor', full_name='HelloResponse.api_version_minor', index=1, - number=2, type=13, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='server_info', full_name='HelloResponse.server_info', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=50, - serialized_end=140, + name="HelloResponse", + full_name="HelloResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="api_version_major", + full_name="HelloResponse.api_version_major", + index=0, + number=1, + type=13, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="api_version_minor", + full_name="HelloResponse.api_version_minor", + index=1, + number=2, + type=13, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="server_info", + full_name="HelloResponse.server_info", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=50, + serialized_end=140, ) _CONNECTREQUEST = _descriptor.Descriptor( - name='ConnectRequest', - full_name='ConnectRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='password', full_name='ConnectRequest.password', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=142, - serialized_end=176, + name="ConnectRequest", + full_name="ConnectRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="password", + full_name="ConnectRequest.password", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=142, + serialized_end=176, ) _CONNECTRESPONSE = _descriptor.Descriptor( - name='ConnectResponse', - full_name='ConnectResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='invalid_password', full_name='ConnectResponse.invalid_password', index=0, - number=1, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=178, - serialized_end=221, + name="ConnectResponse", + full_name="ConnectResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="invalid_password", + full_name="ConnectResponse.invalid_password", + index=0, + number=1, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=178, + serialized_end=221, ) _DISCONNECTREQUEST = _descriptor.Descriptor( - name='DisconnectRequest', - full_name='DisconnectRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=223, - serialized_end=242, + name="DisconnectRequest", + full_name="DisconnectRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=223, + serialized_end=242, ) _DISCONNECTRESPONSE = _descriptor.Descriptor( - name='DisconnectResponse', - full_name='DisconnectResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=244, - serialized_end=264, + name="DisconnectResponse", + full_name="DisconnectResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=244, + serialized_end=264, ) _PINGREQUEST = _descriptor.Descriptor( - name='PingRequest', - full_name='PingRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=266, - serialized_end=279, + name="PingRequest", + full_name="PingRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=266, + serialized_end=279, ) _PINGRESPONSE = _descriptor.Descriptor( - name='PingResponse', - full_name='PingResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=281, - serialized_end=295, + name="PingResponse", + full_name="PingResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=281, + serialized_end=295, ) _DEVICEINFOREQUEST = _descriptor.Descriptor( - name='DeviceInfoRequest', - full_name='DeviceInfoRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=297, - serialized_end=316, + name="DeviceInfoRequest", + full_name="DeviceInfoRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=297, + serialized_end=316, ) _DEVICEINFORESPONSE = _descriptor.Descriptor( - name='DeviceInfoResponse', - full_name='DeviceInfoResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='uses_password', full_name='DeviceInfoResponse.uses_password', index=0, - number=1, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='name', full_name='DeviceInfoResponse.name', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='mac_address', full_name='DeviceInfoResponse.mac_address', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='esphome_core_version', full_name='DeviceInfoResponse.esphome_core_version', index=3, - number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='compilation_time', full_name='DeviceInfoResponse.compilation_time', index=4, - number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='model', full_name='DeviceInfoResponse.model', index=5, - number=6, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='has_deep_sleep', full_name='DeviceInfoResponse.has_deep_sleep', index=6, - number=7, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=319, - serialized_end=492, + name="DeviceInfoResponse", + full_name="DeviceInfoResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="uses_password", + full_name="DeviceInfoResponse.uses_password", + index=0, + number=1, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="name", + full_name="DeviceInfoResponse.name", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="mac_address", + full_name="DeviceInfoResponse.mac_address", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="esphome_core_version", + full_name="DeviceInfoResponse.esphome_core_version", + index=3, + number=4, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="compilation_time", + full_name="DeviceInfoResponse.compilation_time", + index=4, + number=5, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="model", + full_name="DeviceInfoResponse.model", + index=5, + number=6, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="has_deep_sleep", + full_name="DeviceInfoResponse.has_deep_sleep", + index=6, + number=7, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=319, + serialized_end=492, ) _LISTENTITIESREQUEST = _descriptor.Descriptor( - name='ListEntitiesRequest', - full_name='ListEntitiesRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=494, - serialized_end=515, + name="ListEntitiesRequest", + full_name="ListEntitiesRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=494, + serialized_end=515, ) _LISTENTITIESBINARYSENSORRESPONSE = _descriptor.Descriptor( - name='ListEntitiesBinarySensorResponse', - full_name='ListEntitiesBinarySensorResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='object_id', full_name='ListEntitiesBinarySensorResponse.object_id', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='key', full_name='ListEntitiesBinarySensorResponse.key', index=1, - number=2, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='name', full_name='ListEntitiesBinarySensorResponse.name', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='unique_id', full_name='ListEntitiesBinarySensorResponse.unique_id', index=3, - number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='device_class', full_name='ListEntitiesBinarySensorResponse.device_class', index=4, - number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='is_status_binary_sensor', full_name='ListEntitiesBinarySensorResponse.is_status_binary_sensor', index=5, - number=6, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=518, - serialized_end=672, + name="ListEntitiesBinarySensorResponse", + full_name="ListEntitiesBinarySensorResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="object_id", + full_name="ListEntitiesBinarySensorResponse.object_id", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="key", + full_name="ListEntitiesBinarySensorResponse.key", + index=1, + number=2, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="name", + full_name="ListEntitiesBinarySensorResponse.name", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="unique_id", + full_name="ListEntitiesBinarySensorResponse.unique_id", + index=3, + number=4, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="device_class", + full_name="ListEntitiesBinarySensorResponse.device_class", + index=4, + number=5, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="is_status_binary_sensor", + full_name="ListEntitiesBinarySensorResponse.is_status_binary_sensor", + index=5, + number=6, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=518, + serialized_end=672, ) _LISTENTITIESCOVERRESPONSE = _descriptor.Descriptor( - name='ListEntitiesCoverResponse', - full_name='ListEntitiesCoverResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='object_id', full_name='ListEntitiesCoverResponse.object_id', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='key', full_name='ListEntitiesCoverResponse.key', index=1, - number=2, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='name', full_name='ListEntitiesCoverResponse.name', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='unique_id', full_name='ListEntitiesCoverResponse.unique_id', index=3, - number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='is_optimistic', full_name='ListEntitiesCoverResponse.is_optimistic', index=4, - number=5, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=674, - serialized_end=789, + name="ListEntitiesCoverResponse", + full_name="ListEntitiesCoverResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="object_id", + full_name="ListEntitiesCoverResponse.object_id", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="key", + full_name="ListEntitiesCoverResponse.key", + index=1, + number=2, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="name", + full_name="ListEntitiesCoverResponse.name", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="unique_id", + full_name="ListEntitiesCoverResponse.unique_id", + index=3, + number=4, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="is_optimistic", + full_name="ListEntitiesCoverResponse.is_optimistic", + index=4, + number=5, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=674, + serialized_end=789, ) _LISTENTITIESFANRESPONSE = _descriptor.Descriptor( - name='ListEntitiesFanResponse', - full_name='ListEntitiesFanResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='object_id', full_name='ListEntitiesFanResponse.object_id', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='key', full_name='ListEntitiesFanResponse.key', index=1, - number=2, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='name', full_name='ListEntitiesFanResponse.name', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='unique_id', full_name='ListEntitiesFanResponse.unique_id', index=3, - number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='supports_oscillation', full_name='ListEntitiesFanResponse.supports_oscillation', index=4, - number=5, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='supports_speed', full_name='ListEntitiesFanResponse.supports_speed', index=5, - number=6, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=792, - serialized_end=936, + name="ListEntitiesFanResponse", + full_name="ListEntitiesFanResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="object_id", + full_name="ListEntitiesFanResponse.object_id", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="key", + full_name="ListEntitiesFanResponse.key", + index=1, + number=2, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="name", + full_name="ListEntitiesFanResponse.name", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="unique_id", + full_name="ListEntitiesFanResponse.unique_id", + index=3, + number=4, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="supports_oscillation", + full_name="ListEntitiesFanResponse.supports_oscillation", + index=4, + number=5, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="supports_speed", + full_name="ListEntitiesFanResponse.supports_speed", + index=5, + number=6, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=792, + serialized_end=936, ) _LISTENTITIESLIGHTRESPONSE = _descriptor.Descriptor( - name='ListEntitiesLightResponse', - full_name='ListEntitiesLightResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='object_id', full_name='ListEntitiesLightResponse.object_id', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='key', full_name='ListEntitiesLightResponse.key', index=1, - number=2, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='name', full_name='ListEntitiesLightResponse.name', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='unique_id', full_name='ListEntitiesLightResponse.unique_id', index=3, - number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='supports_brightness', full_name='ListEntitiesLightResponse.supports_brightness', index=4, - number=5, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='supports_rgb', full_name='ListEntitiesLightResponse.supports_rgb', index=5, - number=6, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='supports_white_value', full_name='ListEntitiesLightResponse.supports_white_value', index=6, - number=7, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='supports_color_temperature', full_name='ListEntitiesLightResponse.supports_color_temperature', index=7, - number=8, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='min_mireds', full_name='ListEntitiesLightResponse.min_mireds', index=8, - number=9, type=2, cpp_type=6, label=1, - has_default_value=False, default_value=float(0), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='max_mireds', full_name='ListEntitiesLightResponse.max_mireds', index=9, - number=10, type=2, cpp_type=6, label=1, - has_default_value=False, default_value=float(0), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='effects', full_name='ListEntitiesLightResponse.effects', index=10, - number=11, type=9, cpp_type=9, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=939, - serialized_end=1205, + name="ListEntitiesLightResponse", + full_name="ListEntitiesLightResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="object_id", + full_name="ListEntitiesLightResponse.object_id", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="key", + full_name="ListEntitiesLightResponse.key", + index=1, + number=2, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="name", + full_name="ListEntitiesLightResponse.name", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="unique_id", + full_name="ListEntitiesLightResponse.unique_id", + index=3, + number=4, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="supports_brightness", + full_name="ListEntitiesLightResponse.supports_brightness", + index=4, + number=5, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="supports_rgb", + full_name="ListEntitiesLightResponse.supports_rgb", + index=5, + number=6, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="supports_white_value", + full_name="ListEntitiesLightResponse.supports_white_value", + index=6, + number=7, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="supports_color_temperature", + full_name="ListEntitiesLightResponse.supports_color_temperature", + index=7, + number=8, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="min_mireds", + full_name="ListEntitiesLightResponse.min_mireds", + index=8, + number=9, + type=2, + cpp_type=6, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="max_mireds", + full_name="ListEntitiesLightResponse.max_mireds", + index=9, + number=10, + type=2, + cpp_type=6, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="effects", + full_name="ListEntitiesLightResponse.effects", + index=10, + number=11, + type=9, + cpp_type=9, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=939, + serialized_end=1205, ) _LISTENTITIESSENSORRESPONSE = _descriptor.Descriptor( - name='ListEntitiesSensorResponse', - full_name='ListEntitiesSensorResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='object_id', full_name='ListEntitiesSensorResponse.object_id', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='key', full_name='ListEntitiesSensorResponse.key', index=1, - number=2, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='name', full_name='ListEntitiesSensorResponse.name', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='unique_id', full_name='ListEntitiesSensorResponse.unique_id', index=3, - number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='icon', full_name='ListEntitiesSensorResponse.icon', index=4, - number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='unit_of_measurement', full_name='ListEntitiesSensorResponse.unit_of_measurement', index=5, - number=6, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='accuracy_decimals', full_name='ListEntitiesSensorResponse.accuracy_decimals', index=6, - number=7, type=5, cpp_type=1, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1208, - serialized_end=1371, + name="ListEntitiesSensorResponse", + full_name="ListEntitiesSensorResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="object_id", + full_name="ListEntitiesSensorResponse.object_id", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="key", + full_name="ListEntitiesSensorResponse.key", + index=1, + number=2, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="name", + full_name="ListEntitiesSensorResponse.name", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="unique_id", + full_name="ListEntitiesSensorResponse.unique_id", + index=3, + number=4, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="icon", + full_name="ListEntitiesSensorResponse.icon", + index=4, + number=5, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="unit_of_measurement", + full_name="ListEntitiesSensorResponse.unit_of_measurement", + index=5, + number=6, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="accuracy_decimals", + full_name="ListEntitiesSensorResponse.accuracy_decimals", + index=6, + number=7, + type=5, + cpp_type=1, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1208, + serialized_end=1371, ) _LISTENTITIESSWITCHRESPONSE = _descriptor.Descriptor( - name='ListEntitiesSwitchResponse', - full_name='ListEntitiesSwitchResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='object_id', full_name='ListEntitiesSwitchResponse.object_id', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='key', full_name='ListEntitiesSwitchResponse.key', index=1, - number=2, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='name', full_name='ListEntitiesSwitchResponse.name', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='unique_id', full_name='ListEntitiesSwitchResponse.unique_id', index=3, - number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='icon', full_name='ListEntitiesSwitchResponse.icon', index=4, - number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='optimistic', full_name='ListEntitiesSwitchResponse.optimistic', index=5, - number=6, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1373, - serialized_end=1500, + name="ListEntitiesSwitchResponse", + full_name="ListEntitiesSwitchResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="object_id", + full_name="ListEntitiesSwitchResponse.object_id", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="key", + full_name="ListEntitiesSwitchResponse.key", + index=1, + number=2, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="name", + full_name="ListEntitiesSwitchResponse.name", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="unique_id", + full_name="ListEntitiesSwitchResponse.unique_id", + index=3, + number=4, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="icon", + full_name="ListEntitiesSwitchResponse.icon", + index=4, + number=5, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="optimistic", + full_name="ListEntitiesSwitchResponse.optimistic", + index=5, + number=6, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1373, + serialized_end=1500, ) _LISTENTITIESTEXTSENSORRESPONSE = _descriptor.Descriptor( - name='ListEntitiesTextSensorResponse', - full_name='ListEntitiesTextSensorResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='object_id', full_name='ListEntitiesTextSensorResponse.object_id', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='key', full_name='ListEntitiesTextSensorResponse.key', index=1, - number=2, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='name', full_name='ListEntitiesTextSensorResponse.name', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='unique_id', full_name='ListEntitiesTextSensorResponse.unique_id', index=3, - number=4, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='icon', full_name='ListEntitiesTextSensorResponse.icon', index=4, - number=5, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1502, - serialized_end=1613, + name="ListEntitiesTextSensorResponse", + full_name="ListEntitiesTextSensorResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="object_id", + full_name="ListEntitiesTextSensorResponse.object_id", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="key", + full_name="ListEntitiesTextSensorResponse.key", + index=1, + number=2, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="name", + full_name="ListEntitiesTextSensorResponse.name", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="unique_id", + full_name="ListEntitiesTextSensorResponse.unique_id", + index=3, + number=4, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="icon", + full_name="ListEntitiesTextSensorResponse.icon", + index=4, + number=5, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1502, + serialized_end=1613, ) _LISTENTITIESDONERESPONSE = _descriptor.Descriptor( - name='ListEntitiesDoneResponse', - full_name='ListEntitiesDoneResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1615, - serialized_end=1641, + name="ListEntitiesDoneResponse", + full_name="ListEntitiesDoneResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1615, + serialized_end=1641, ) _SUBSCRIBESTATESREQUEST = _descriptor.Descriptor( - name='SubscribeStatesRequest', - full_name='SubscribeStatesRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1643, - serialized_end=1667, + name="SubscribeStatesRequest", + full_name="SubscribeStatesRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1643, + serialized_end=1667, ) _BINARYSENSORSTATERESPONSE = _descriptor.Descriptor( - name='BinarySensorStateResponse', - full_name='BinarySensorStateResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='BinarySensorStateResponse.key', index=0, - number=1, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='state', full_name='BinarySensorStateResponse.state', index=1, - number=2, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1669, - serialized_end=1724, + name="BinarySensorStateResponse", + full_name="BinarySensorStateResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="BinarySensorStateResponse.key", + index=0, + number=1, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="state", + full_name="BinarySensorStateResponse.state", + index=1, + number=2, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1669, + serialized_end=1724, ) _COVERSTATERESPONSE = _descriptor.Descriptor( - name='CoverStateResponse', - full_name='CoverStateResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='CoverStateResponse.key', index=0, - number=1, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='state', full_name='CoverStateResponse.state', index=1, - number=2, type=14, cpp_type=8, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - _COVERSTATERESPONSE_COVERSTATE, - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1726, - serialized_end=1842, + name="CoverStateResponse", + full_name="CoverStateResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="CoverStateResponse.key", + index=0, + number=1, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="state", + full_name="CoverStateResponse.state", + index=1, + number=2, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[ + _COVERSTATERESPONSE_COVERSTATE, + ], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1726, + serialized_end=1842, ) _FANSTATERESPONSE = _descriptor.Descriptor( - name='FanStateResponse', - full_name='FanStateResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='FanStateResponse.key', index=0, - number=1, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='state', full_name='FanStateResponse.state', index=1, - number=2, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='oscillating', full_name='FanStateResponse.oscillating', index=2, - number=3, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='speed', full_name='FanStateResponse.speed', index=3, - number=4, type=14, cpp_type=8, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1844, - serialized_end=1937, + name="FanStateResponse", + full_name="FanStateResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="FanStateResponse.key", + index=0, + number=1, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="state", + full_name="FanStateResponse.state", + index=1, + number=2, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="oscillating", + full_name="FanStateResponse.oscillating", + index=2, + number=3, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="speed", + full_name="FanStateResponse.speed", + index=3, + number=4, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1844, + serialized_end=1937, ) _LIGHTSTATERESPONSE = _descriptor.Descriptor( - name='LightStateResponse', - full_name='LightStateResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='LightStateResponse.key', index=0, - number=1, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='state', full_name='LightStateResponse.state', index=1, - number=2, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='brightness', full_name='LightStateResponse.brightness', index=2, - number=3, type=2, cpp_type=6, label=1, - has_default_value=False, default_value=float(0), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='red', full_name='LightStateResponse.red', index=3, - number=4, type=2, cpp_type=6, label=1, - has_default_value=False, default_value=float(0), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='green', full_name='LightStateResponse.green', index=4, - number=5, type=2, cpp_type=6, label=1, - has_default_value=False, default_value=float(0), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='blue', full_name='LightStateResponse.blue', index=5, - number=6, type=2, cpp_type=6, label=1, - has_default_value=False, default_value=float(0), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='white', full_name='LightStateResponse.white', index=6, - number=7, type=2, cpp_type=6, label=1, - has_default_value=False, default_value=float(0), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='color_temperature', full_name='LightStateResponse.color_temperature', index=7, - number=8, type=2, cpp_type=6, label=1, - has_default_value=False, default_value=float(0), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='effect', full_name='LightStateResponse.effect', index=8, - number=9, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=1940, - serialized_end=2108, + name="LightStateResponse", + full_name="LightStateResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="LightStateResponse.key", + index=0, + number=1, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="state", + full_name="LightStateResponse.state", + index=1, + number=2, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="brightness", + full_name="LightStateResponse.brightness", + index=2, + number=3, + type=2, + cpp_type=6, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="red", + full_name="LightStateResponse.red", + index=3, + number=4, + type=2, + cpp_type=6, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="green", + full_name="LightStateResponse.green", + index=4, + number=5, + type=2, + cpp_type=6, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="blue", + full_name="LightStateResponse.blue", + index=5, + number=6, + type=2, + cpp_type=6, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="white", + full_name="LightStateResponse.white", + index=6, + number=7, + type=2, + cpp_type=6, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="color_temperature", + full_name="LightStateResponse.color_temperature", + index=7, + number=8, + type=2, + cpp_type=6, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="effect", + full_name="LightStateResponse.effect", + index=8, + number=9, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=1940, + serialized_end=2108, ) _SENSORSTATERESPONSE = _descriptor.Descriptor( - name='SensorStateResponse', - full_name='SensorStateResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='SensorStateResponse.key', index=0, - number=1, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='state', full_name='SensorStateResponse.state', index=1, - number=2, type=2, cpp_type=6, label=1, - has_default_value=False, default_value=float(0), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=2110, - serialized_end=2159, + name="SensorStateResponse", + full_name="SensorStateResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="SensorStateResponse.key", + index=0, + number=1, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="state", + full_name="SensorStateResponse.state", + index=1, + number=2, + type=2, + cpp_type=6, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=2110, + serialized_end=2159, ) _SWITCHSTATERESPONSE = _descriptor.Descriptor( - name='SwitchStateResponse', - full_name='SwitchStateResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='SwitchStateResponse.key', index=0, - number=1, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='state', full_name='SwitchStateResponse.state', index=1, - number=2, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=2161, - serialized_end=2210, + name="SwitchStateResponse", + full_name="SwitchStateResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="SwitchStateResponse.key", + index=0, + number=1, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="state", + full_name="SwitchStateResponse.state", + index=1, + number=2, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=2161, + serialized_end=2210, ) _TEXTSENSORSTATERESPONSE = _descriptor.Descriptor( - name='TextSensorStateResponse', - full_name='TextSensorStateResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='TextSensorStateResponse.key', index=0, - number=1, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='state', full_name='TextSensorStateResponse.state', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=2212, - serialized_end=2265, + name="TextSensorStateResponse", + full_name="TextSensorStateResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="TextSensorStateResponse.key", + index=0, + number=1, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="state", + full_name="TextSensorStateResponse.state", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=2212, + serialized_end=2265, ) _COVERCOMMANDREQUEST = _descriptor.Descriptor( - name='CoverCommandRequest', - full_name='CoverCommandRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='CoverCommandRequest.key', index=0, - number=1, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='has_state', full_name='CoverCommandRequest.has_state', index=1, - number=2, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='command', full_name='CoverCommandRequest.command', index=2, - number=3, type=14, cpp_type=8, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - _COVERCOMMANDREQUEST_COVERCOMMAND, - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=2268, - serialized_end=2420, + name="CoverCommandRequest", + full_name="CoverCommandRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="CoverCommandRequest.key", + index=0, + number=1, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="has_state", + full_name="CoverCommandRequest.has_state", + index=1, + number=2, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="command", + full_name="CoverCommandRequest.command", + index=2, + number=3, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[ + _COVERCOMMANDREQUEST_COVERCOMMAND, + ], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=2268, + serialized_end=2420, ) _FANCOMMANDREQUEST = _descriptor.Descriptor( - name='FanCommandRequest', - full_name='FanCommandRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='FanCommandRequest.key', index=0, - number=1, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='has_state', full_name='FanCommandRequest.has_state', index=1, - number=2, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='state', full_name='FanCommandRequest.state', index=2, - number=3, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='has_speed', full_name='FanCommandRequest.has_speed', index=3, - number=4, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='speed', full_name='FanCommandRequest.speed', index=4, - number=5, type=14, cpp_type=8, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='has_oscillating', full_name='FanCommandRequest.has_oscillating', index=5, - number=6, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='oscillating', full_name='FanCommandRequest.oscillating', index=6, - number=7, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=2423, - serialized_end=2580, + name="FanCommandRequest", + full_name="FanCommandRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="FanCommandRequest.key", + index=0, + number=1, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="has_state", + full_name="FanCommandRequest.has_state", + index=1, + number=2, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="state", + full_name="FanCommandRequest.state", + index=2, + number=3, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="has_speed", + full_name="FanCommandRequest.has_speed", + index=3, + number=4, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="speed", + full_name="FanCommandRequest.speed", + index=4, + number=5, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="has_oscillating", + full_name="FanCommandRequest.has_oscillating", + index=5, + number=6, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="oscillating", + full_name="FanCommandRequest.oscillating", + index=6, + number=7, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=2423, + serialized_end=2580, ) _LIGHTCOMMANDREQUEST = _descriptor.Descriptor( - name='LightCommandRequest', - full_name='LightCommandRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='LightCommandRequest.key', index=0, - number=1, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='has_state', full_name='LightCommandRequest.has_state', index=1, - number=2, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='state', full_name='LightCommandRequest.state', index=2, - number=3, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='has_brightness', full_name='LightCommandRequest.has_brightness', index=3, - number=4, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='brightness', full_name='LightCommandRequest.brightness', index=4, - number=5, type=2, cpp_type=6, label=1, - has_default_value=False, default_value=float(0), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='has_rgb', full_name='LightCommandRequest.has_rgb', index=5, - number=6, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='red', full_name='LightCommandRequest.red', index=6, - number=7, type=2, cpp_type=6, label=1, - has_default_value=False, default_value=float(0), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='green', full_name='LightCommandRequest.green', index=7, - number=8, type=2, cpp_type=6, label=1, - has_default_value=False, default_value=float(0), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='blue', full_name='LightCommandRequest.blue', index=8, - number=9, type=2, cpp_type=6, label=1, - has_default_value=False, default_value=float(0), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='has_white', full_name='LightCommandRequest.has_white', index=9, - number=10, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='white', full_name='LightCommandRequest.white', index=10, - number=11, type=2, cpp_type=6, label=1, - has_default_value=False, default_value=float(0), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='has_color_temperature', full_name='LightCommandRequest.has_color_temperature', index=11, - number=12, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='color_temperature', full_name='LightCommandRequest.color_temperature', index=12, - number=13, type=2, cpp_type=6, label=1, - has_default_value=False, default_value=float(0), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='has_transition_length', full_name='LightCommandRequest.has_transition_length', index=13, - number=14, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='transition_length', full_name='LightCommandRequest.transition_length', index=14, - number=15, type=13, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='has_flash_length', full_name='LightCommandRequest.has_flash_length', index=15, - number=16, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='flash_length', full_name='LightCommandRequest.flash_length', index=16, - number=17, type=13, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='has_effect', full_name='LightCommandRequest.has_effect', index=17, - number=18, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='effect', full_name='LightCommandRequest.effect', index=18, - number=19, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=2583, - serialized_end=2988, + name="LightCommandRequest", + full_name="LightCommandRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="LightCommandRequest.key", + index=0, + number=1, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="has_state", + full_name="LightCommandRequest.has_state", + index=1, + number=2, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="state", + full_name="LightCommandRequest.state", + index=2, + number=3, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="has_brightness", + full_name="LightCommandRequest.has_brightness", + index=3, + number=4, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="brightness", + full_name="LightCommandRequest.brightness", + index=4, + number=5, + type=2, + cpp_type=6, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="has_rgb", + full_name="LightCommandRequest.has_rgb", + index=5, + number=6, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="red", + full_name="LightCommandRequest.red", + index=6, + number=7, + type=2, + cpp_type=6, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="green", + full_name="LightCommandRequest.green", + index=7, + number=8, + type=2, + cpp_type=6, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="blue", + full_name="LightCommandRequest.blue", + index=8, + number=9, + type=2, + cpp_type=6, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="has_white", + full_name="LightCommandRequest.has_white", + index=9, + number=10, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="white", + full_name="LightCommandRequest.white", + index=10, + number=11, + type=2, + cpp_type=6, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="has_color_temperature", + full_name="LightCommandRequest.has_color_temperature", + index=11, + number=12, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="color_temperature", + full_name="LightCommandRequest.color_temperature", + index=12, + number=13, + type=2, + cpp_type=6, + label=1, + has_default_value=False, + default_value=float(0), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="has_transition_length", + full_name="LightCommandRequest.has_transition_length", + index=13, + number=14, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="transition_length", + full_name="LightCommandRequest.transition_length", + index=14, + number=15, + type=13, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="has_flash_length", + full_name="LightCommandRequest.has_flash_length", + index=15, + number=16, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="flash_length", + full_name="LightCommandRequest.flash_length", + index=16, + number=17, + type=13, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="has_effect", + full_name="LightCommandRequest.has_effect", + index=17, + number=18, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="effect", + full_name="LightCommandRequest.effect", + index=18, + number=19, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=2583, + serialized_end=2988, ) _SWITCHCOMMANDREQUEST = _descriptor.Descriptor( - name='SwitchCommandRequest', - full_name='SwitchCommandRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='SwitchCommandRequest.key', index=0, - number=1, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='state', full_name='SwitchCommandRequest.state', index=1, - number=2, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=2990, - serialized_end=3040, + name="SwitchCommandRequest", + full_name="SwitchCommandRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="SwitchCommandRequest.key", + index=0, + number=1, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="state", + full_name="SwitchCommandRequest.state", + index=1, + number=2, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=2990, + serialized_end=3040, ) _SUBSCRIBELOGSREQUEST = _descriptor.Descriptor( - name='SubscribeLogsRequest', - full_name='SubscribeLogsRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='level', full_name='SubscribeLogsRequest.level', index=0, - number=1, type=14, cpp_type=8, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='dump_config', full_name='SubscribeLogsRequest.dump_config', index=1, - number=2, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=3042, - serialized_end=3111, + name="SubscribeLogsRequest", + full_name="SubscribeLogsRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="level", + full_name="SubscribeLogsRequest.level", + index=0, + number=1, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="dump_config", + full_name="SubscribeLogsRequest.dump_config", + index=1, + number=2, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=3042, + serialized_end=3111, ) _SUBSCRIBELOGSRESPONSE = _descriptor.Descriptor( - name='SubscribeLogsResponse', - full_name='SubscribeLogsResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='level', full_name='SubscribeLogsResponse.level', index=0, - number=1, type=14, cpp_type=8, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='tag', full_name='SubscribeLogsResponse.tag', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='message', full_name='SubscribeLogsResponse.message', index=2, - number=3, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='send_failed', full_name='SubscribeLogsResponse.send_failed', index=3, - number=4, type=8, cpp_type=7, label=1, - has_default_value=False, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=3113, - serialized_end=3213, + name="SubscribeLogsResponse", + full_name="SubscribeLogsResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="level", + full_name="SubscribeLogsResponse.level", + index=0, + number=1, + type=14, + cpp_type=8, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="tag", + full_name="SubscribeLogsResponse.tag", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="message", + full_name="SubscribeLogsResponse.message", + index=2, + number=3, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="send_failed", + full_name="SubscribeLogsResponse.send_failed", + index=3, + number=4, + type=8, + cpp_type=7, + label=1, + has_default_value=False, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=3113, + serialized_end=3213, ) _SUBSCRIBESERVICECALLSREQUEST = _descriptor.Descriptor( - name='SubscribeServiceCallsRequest', - full_name='SubscribeServiceCallsRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=3215, - serialized_end=3245, + name="SubscribeServiceCallsRequest", + full_name="SubscribeServiceCallsRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=3215, + serialized_end=3245, ) _SERVICECALLRESPONSE_DATAENTRY = _descriptor.Descriptor( - name='DataEntry', - full_name='ServiceCallResponse.DataEntry', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='ServiceCallResponse.DataEntry.key', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='value', full_name='ServiceCallResponse.DataEntry.value', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=_b('8\001'), - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=3453, - serialized_end=3496, + name="DataEntry", + full_name="ServiceCallResponse.DataEntry", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="ServiceCallResponse.DataEntry.key", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="value", + full_name="ServiceCallResponse.DataEntry.value", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=_b("8\001"), + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=3453, + serialized_end=3496, ) _SERVICECALLRESPONSE_DATATEMPLATEENTRY = _descriptor.Descriptor( - name='DataTemplateEntry', - full_name='ServiceCallResponse.DataTemplateEntry', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='ServiceCallResponse.DataTemplateEntry.key', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='value', full_name='ServiceCallResponse.DataTemplateEntry.value', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=_b('8\001'), - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=3498, - serialized_end=3549, + name="DataTemplateEntry", + full_name="ServiceCallResponse.DataTemplateEntry", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="ServiceCallResponse.DataTemplateEntry.key", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="value", + full_name="ServiceCallResponse.DataTemplateEntry.value", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=_b("8\001"), + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=3498, + serialized_end=3549, ) _SERVICECALLRESPONSE_VARIABLESENTRY = _descriptor.Descriptor( - name='VariablesEntry', - full_name='ServiceCallResponse.VariablesEntry', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='key', full_name='ServiceCallResponse.VariablesEntry.key', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='value', full_name='ServiceCallResponse.VariablesEntry.value', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=_b('8\001'), - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=3551, - serialized_end=3599, + name="VariablesEntry", + full_name="ServiceCallResponse.VariablesEntry", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="key", + full_name="ServiceCallResponse.VariablesEntry.key", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="value", + full_name="ServiceCallResponse.VariablesEntry.value", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=_b("8\001"), + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=3551, + serialized_end=3599, ) _SERVICECALLRESPONSE = _descriptor.Descriptor( - name='ServiceCallResponse', - full_name='ServiceCallResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='service', full_name='ServiceCallResponse.service', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='data', full_name='ServiceCallResponse.data', index=1, - number=2, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='data_template', full_name='ServiceCallResponse.data_template', index=2, - number=3, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='variables', full_name='ServiceCallResponse.variables', index=3, - number=4, type=11, cpp_type=10, label=3, - has_default_value=False, default_value=[], - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[_SERVICECALLRESPONSE_DATAENTRY, _SERVICECALLRESPONSE_DATATEMPLATEENTRY, _SERVICECALLRESPONSE_VARIABLESENTRY, ], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=3248, - serialized_end=3599, + name="ServiceCallResponse", + full_name="ServiceCallResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="service", + full_name="ServiceCallResponse.service", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="data", + full_name="ServiceCallResponse.data", + index=1, + number=2, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="data_template", + full_name="ServiceCallResponse.data_template", + index=2, + number=3, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="variables", + full_name="ServiceCallResponse.variables", + index=3, + number=4, + type=11, + cpp_type=10, + label=3, + has_default_value=False, + default_value=[], + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[ + _SERVICECALLRESPONSE_DATAENTRY, + _SERVICECALLRESPONSE_DATATEMPLATEENTRY, + _SERVICECALLRESPONSE_VARIABLESENTRY, + ], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=3248, + serialized_end=3599, ) _SUBSCRIBEHOMEASSISTANTSTATESREQUEST = _descriptor.Descriptor( - name='SubscribeHomeAssistantStatesRequest', - full_name='SubscribeHomeAssistantStatesRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=3601, - serialized_end=3638, + name="SubscribeHomeAssistantStatesRequest", + full_name="SubscribeHomeAssistantStatesRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=3601, + serialized_end=3638, ) _SUBSCRIBEHOMEASSISTANTSTATERESPONSE = _descriptor.Descriptor( - name='SubscribeHomeAssistantStateResponse', - full_name='SubscribeHomeAssistantStateResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='entity_id', full_name='SubscribeHomeAssistantStateResponse.entity_id', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=3640, - serialized_end=3696, + name="SubscribeHomeAssistantStateResponse", + full_name="SubscribeHomeAssistantStateResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="entity_id", + full_name="SubscribeHomeAssistantStateResponse.entity_id", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=3640, + serialized_end=3696, ) _HOMEASSISTANTSTATERESPONSE = _descriptor.Descriptor( - name='HomeAssistantStateResponse', - full_name='HomeAssistantStateResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='entity_id', full_name='HomeAssistantStateResponse.entity_id', index=0, - number=1, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - _descriptor.FieldDescriptor( - name='state', full_name='HomeAssistantStateResponse.state', index=1, - number=2, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=3698, - serialized_end=3760, + name="HomeAssistantStateResponse", + full_name="HomeAssistantStateResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="entity_id", + full_name="HomeAssistantStateResponse.entity_id", + index=0, + number=1, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + _descriptor.FieldDescriptor( + name="state", + full_name="HomeAssistantStateResponse.state", + index=1, + number=2, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=3698, + serialized_end=3760, ) _GETTIMEREQUEST = _descriptor.Descriptor( - name='GetTimeRequest', - full_name='GetTimeRequest', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=3762, - serialized_end=3778, + name="GetTimeRequest", + full_name="GetTimeRequest", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=3762, + serialized_end=3778, ) _GETTIMERESPONSE = _descriptor.Descriptor( - name='GetTimeResponse', - full_name='GetTimeResponse', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - _descriptor.FieldDescriptor( - name='epoch_seconds', full_name='GetTimeResponse.epoch_seconds', index=0, - number=1, type=7, cpp_type=3, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR), - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto3', - extension_ranges=[], - oneofs=[ - ], - serialized_start=3780, - serialized_end=3820, + name="GetTimeResponse", + full_name="GetTimeResponse", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[ + _descriptor.FieldDescriptor( + name="epoch_seconds", + full_name="GetTimeResponse.epoch_seconds", + index=0, + number=1, + type=7, + cpp_type=3, + label=1, + has_default_value=False, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=False, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, + ), + ], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto3", + extension_ranges=[], + oneofs=[], + serialized_start=3780, + serialized_end=3820, ) -_COVERSTATERESPONSE.fields_by_name['state'].enum_type = _COVERSTATERESPONSE_COVERSTATE +_COVERSTATERESPONSE.fields_by_name["state"].enum_type = _COVERSTATERESPONSE_COVERSTATE _COVERSTATERESPONSE_COVERSTATE.containing_type = _COVERSTATERESPONSE -_FANSTATERESPONSE.fields_by_name['speed'].enum_type = _FANSPEED -_COVERCOMMANDREQUEST.fields_by_name['command'].enum_type = _COVERCOMMANDREQUEST_COVERCOMMAND +_FANSTATERESPONSE.fields_by_name["speed"].enum_type = _FANSPEED +_COVERCOMMANDREQUEST.fields_by_name[ + "command" +].enum_type = _COVERCOMMANDREQUEST_COVERCOMMAND _COVERCOMMANDREQUEST_COVERCOMMAND.containing_type = _COVERCOMMANDREQUEST -_FANCOMMANDREQUEST.fields_by_name['speed'].enum_type = _FANSPEED -_SUBSCRIBELOGSREQUEST.fields_by_name['level'].enum_type = _LOGLEVEL -_SUBSCRIBELOGSRESPONSE.fields_by_name['level'].enum_type = _LOGLEVEL +_FANCOMMANDREQUEST.fields_by_name["speed"].enum_type = _FANSPEED +_SUBSCRIBELOGSREQUEST.fields_by_name["level"].enum_type = _LOGLEVEL +_SUBSCRIBELOGSRESPONSE.fields_by_name["level"].enum_type = _LOGLEVEL _SERVICECALLRESPONSE_DATAENTRY.containing_type = _SERVICECALLRESPONSE _SERVICECALLRESPONSE_DATATEMPLATEENTRY.containing_type = _SERVICECALLRESPONSE _SERVICECALLRESPONSE_VARIABLESENTRY.containing_type = _SERVICECALLRESPONSE -_SERVICECALLRESPONSE.fields_by_name['data'].message_type = _SERVICECALLRESPONSE_DATAENTRY -_SERVICECALLRESPONSE.fields_by_name['data_template'].message_type = _SERVICECALLRESPONSE_DATATEMPLATEENTRY -_SERVICECALLRESPONSE.fields_by_name['variables'].message_type = _SERVICECALLRESPONSE_VARIABLESENTRY -DESCRIPTOR.message_types_by_name['HelloRequest'] = _HELLOREQUEST -DESCRIPTOR.message_types_by_name['HelloResponse'] = _HELLORESPONSE -DESCRIPTOR.message_types_by_name['ConnectRequest'] = _CONNECTREQUEST -DESCRIPTOR.message_types_by_name['ConnectResponse'] = _CONNECTRESPONSE -DESCRIPTOR.message_types_by_name['DisconnectRequest'] = _DISCONNECTREQUEST -DESCRIPTOR.message_types_by_name['DisconnectResponse'] = _DISCONNECTRESPONSE -DESCRIPTOR.message_types_by_name['PingRequest'] = _PINGREQUEST -DESCRIPTOR.message_types_by_name['PingResponse'] = _PINGRESPONSE -DESCRIPTOR.message_types_by_name['DeviceInfoRequest'] = _DEVICEINFOREQUEST -DESCRIPTOR.message_types_by_name['DeviceInfoResponse'] = _DEVICEINFORESPONSE -DESCRIPTOR.message_types_by_name['ListEntitiesRequest'] = _LISTENTITIESREQUEST -DESCRIPTOR.message_types_by_name['ListEntitiesBinarySensorResponse'] = _LISTENTITIESBINARYSENSORRESPONSE -DESCRIPTOR.message_types_by_name['ListEntitiesCoverResponse'] = _LISTENTITIESCOVERRESPONSE -DESCRIPTOR.message_types_by_name['ListEntitiesFanResponse'] = _LISTENTITIESFANRESPONSE -DESCRIPTOR.message_types_by_name['ListEntitiesLightResponse'] = _LISTENTITIESLIGHTRESPONSE -DESCRIPTOR.message_types_by_name['ListEntitiesSensorResponse'] = _LISTENTITIESSENSORRESPONSE -DESCRIPTOR.message_types_by_name['ListEntitiesSwitchResponse'] = _LISTENTITIESSWITCHRESPONSE -DESCRIPTOR.message_types_by_name['ListEntitiesTextSensorResponse'] = _LISTENTITIESTEXTSENSORRESPONSE -DESCRIPTOR.message_types_by_name['ListEntitiesDoneResponse'] = _LISTENTITIESDONERESPONSE -DESCRIPTOR.message_types_by_name['SubscribeStatesRequest'] = _SUBSCRIBESTATESREQUEST -DESCRIPTOR.message_types_by_name['BinarySensorStateResponse'] = _BINARYSENSORSTATERESPONSE -DESCRIPTOR.message_types_by_name['CoverStateResponse'] = _COVERSTATERESPONSE -DESCRIPTOR.message_types_by_name['FanStateResponse'] = _FANSTATERESPONSE -DESCRIPTOR.message_types_by_name['LightStateResponse'] = _LIGHTSTATERESPONSE -DESCRIPTOR.message_types_by_name['SensorStateResponse'] = _SENSORSTATERESPONSE -DESCRIPTOR.message_types_by_name['SwitchStateResponse'] = _SWITCHSTATERESPONSE -DESCRIPTOR.message_types_by_name['TextSensorStateResponse'] = _TEXTSENSORSTATERESPONSE -DESCRIPTOR.message_types_by_name['CoverCommandRequest'] = _COVERCOMMANDREQUEST -DESCRIPTOR.message_types_by_name['FanCommandRequest'] = _FANCOMMANDREQUEST -DESCRIPTOR.message_types_by_name['LightCommandRequest'] = _LIGHTCOMMANDREQUEST -DESCRIPTOR.message_types_by_name['SwitchCommandRequest'] = _SWITCHCOMMANDREQUEST -DESCRIPTOR.message_types_by_name['SubscribeLogsRequest'] = _SUBSCRIBELOGSREQUEST -DESCRIPTOR.message_types_by_name['SubscribeLogsResponse'] = _SUBSCRIBELOGSRESPONSE -DESCRIPTOR.message_types_by_name['SubscribeServiceCallsRequest'] = _SUBSCRIBESERVICECALLSREQUEST -DESCRIPTOR.message_types_by_name['ServiceCallResponse'] = _SERVICECALLRESPONSE -DESCRIPTOR.message_types_by_name['SubscribeHomeAssistantStatesRequest'] = _SUBSCRIBEHOMEASSISTANTSTATESREQUEST -DESCRIPTOR.message_types_by_name['SubscribeHomeAssistantStateResponse'] = _SUBSCRIBEHOMEASSISTANTSTATERESPONSE -DESCRIPTOR.message_types_by_name['HomeAssistantStateResponse'] = _HOMEASSISTANTSTATERESPONSE -DESCRIPTOR.message_types_by_name['GetTimeRequest'] = _GETTIMEREQUEST -DESCRIPTOR.message_types_by_name['GetTimeResponse'] = _GETTIMERESPONSE -DESCRIPTOR.enum_types_by_name['FanSpeed'] = _FANSPEED -DESCRIPTOR.enum_types_by_name['LogLevel'] = _LOGLEVEL +_SERVICECALLRESPONSE.fields_by_name[ + "data" +].message_type = _SERVICECALLRESPONSE_DATAENTRY +_SERVICECALLRESPONSE.fields_by_name[ + "data_template" +].message_type = _SERVICECALLRESPONSE_DATATEMPLATEENTRY +_SERVICECALLRESPONSE.fields_by_name[ + "variables" +].message_type = _SERVICECALLRESPONSE_VARIABLESENTRY +DESCRIPTOR.message_types_by_name["HelloRequest"] = _HELLOREQUEST +DESCRIPTOR.message_types_by_name["HelloResponse"] = _HELLORESPONSE +DESCRIPTOR.message_types_by_name["ConnectRequest"] = _CONNECTREQUEST +DESCRIPTOR.message_types_by_name["ConnectResponse"] = _CONNECTRESPONSE +DESCRIPTOR.message_types_by_name["DisconnectRequest"] = _DISCONNECTREQUEST +DESCRIPTOR.message_types_by_name["DisconnectResponse"] = _DISCONNECTRESPONSE +DESCRIPTOR.message_types_by_name["PingRequest"] = _PINGREQUEST +DESCRIPTOR.message_types_by_name["PingResponse"] = _PINGRESPONSE +DESCRIPTOR.message_types_by_name["DeviceInfoRequest"] = _DEVICEINFOREQUEST +DESCRIPTOR.message_types_by_name["DeviceInfoResponse"] = _DEVICEINFORESPONSE +DESCRIPTOR.message_types_by_name["ListEntitiesRequest"] = _LISTENTITIESREQUEST +DESCRIPTOR.message_types_by_name[ + "ListEntitiesBinarySensorResponse" +] = _LISTENTITIESBINARYSENSORRESPONSE +DESCRIPTOR.message_types_by_name[ + "ListEntitiesCoverResponse" +] = _LISTENTITIESCOVERRESPONSE +DESCRIPTOR.message_types_by_name["ListEntitiesFanResponse"] = _LISTENTITIESFANRESPONSE +DESCRIPTOR.message_types_by_name[ + "ListEntitiesLightResponse" +] = _LISTENTITIESLIGHTRESPONSE +DESCRIPTOR.message_types_by_name[ + "ListEntitiesSensorResponse" +] = _LISTENTITIESSENSORRESPONSE +DESCRIPTOR.message_types_by_name[ + "ListEntitiesSwitchResponse" +] = _LISTENTITIESSWITCHRESPONSE +DESCRIPTOR.message_types_by_name[ + "ListEntitiesTextSensorResponse" +] = _LISTENTITIESTEXTSENSORRESPONSE +DESCRIPTOR.message_types_by_name["ListEntitiesDoneResponse"] = _LISTENTITIESDONERESPONSE +DESCRIPTOR.message_types_by_name["SubscribeStatesRequest"] = _SUBSCRIBESTATESREQUEST +DESCRIPTOR.message_types_by_name[ + "BinarySensorStateResponse" +] = _BINARYSENSORSTATERESPONSE +DESCRIPTOR.message_types_by_name["CoverStateResponse"] = _COVERSTATERESPONSE +DESCRIPTOR.message_types_by_name["FanStateResponse"] = _FANSTATERESPONSE +DESCRIPTOR.message_types_by_name["LightStateResponse"] = _LIGHTSTATERESPONSE +DESCRIPTOR.message_types_by_name["SensorStateResponse"] = _SENSORSTATERESPONSE +DESCRIPTOR.message_types_by_name["SwitchStateResponse"] = _SWITCHSTATERESPONSE +DESCRIPTOR.message_types_by_name["TextSensorStateResponse"] = _TEXTSENSORSTATERESPONSE +DESCRIPTOR.message_types_by_name["CoverCommandRequest"] = _COVERCOMMANDREQUEST +DESCRIPTOR.message_types_by_name["FanCommandRequest"] = _FANCOMMANDREQUEST +DESCRIPTOR.message_types_by_name["LightCommandRequest"] = _LIGHTCOMMANDREQUEST +DESCRIPTOR.message_types_by_name["SwitchCommandRequest"] = _SWITCHCOMMANDREQUEST +DESCRIPTOR.message_types_by_name["SubscribeLogsRequest"] = _SUBSCRIBELOGSREQUEST +DESCRIPTOR.message_types_by_name["SubscribeLogsResponse"] = _SUBSCRIBELOGSRESPONSE +DESCRIPTOR.message_types_by_name[ + "SubscribeServiceCallsRequest" +] = _SUBSCRIBESERVICECALLSREQUEST +DESCRIPTOR.message_types_by_name["ServiceCallResponse"] = _SERVICECALLRESPONSE +DESCRIPTOR.message_types_by_name[ + "SubscribeHomeAssistantStatesRequest" +] = _SUBSCRIBEHOMEASSISTANTSTATESREQUEST +DESCRIPTOR.message_types_by_name[ + "SubscribeHomeAssistantStateResponse" +] = _SUBSCRIBEHOMEASSISTANTSTATERESPONSE +DESCRIPTOR.message_types_by_name[ + "HomeAssistantStateResponse" +] = _HOMEASSISTANTSTATERESPONSE +DESCRIPTOR.message_types_by_name["GetTimeRequest"] = _GETTIMEREQUEST +DESCRIPTOR.message_types_by_name["GetTimeResponse"] = _GETTIMERESPONSE +DESCRIPTOR.enum_types_by_name["FanSpeed"] = _FANSPEED +DESCRIPTOR.enum_types_by_name["LogLevel"] = _LOGLEVEL _sym_db.RegisterFileDescriptor(DESCRIPTOR) -HelloRequest = _reflection.GeneratedProtocolMessageType('HelloRequest', (_message.Message,), dict( - DESCRIPTOR = _HELLOREQUEST, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:HelloRequest) - )) +HelloRequest = _reflection.GeneratedProtocolMessageType( + "HelloRequest", + (_message.Message,), + dict( + DESCRIPTOR=_HELLOREQUEST, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:HelloRequest) + ), +) _sym_db.RegisterMessage(HelloRequest) -HelloResponse = _reflection.GeneratedProtocolMessageType('HelloResponse', (_message.Message,), dict( - DESCRIPTOR = _HELLORESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:HelloResponse) - )) +HelloResponse = _reflection.GeneratedProtocolMessageType( + "HelloResponse", + (_message.Message,), + dict( + DESCRIPTOR=_HELLORESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:HelloResponse) + ), +) _sym_db.RegisterMessage(HelloResponse) -ConnectRequest = _reflection.GeneratedProtocolMessageType('ConnectRequest', (_message.Message,), dict( - DESCRIPTOR = _CONNECTREQUEST, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:ConnectRequest) - )) +ConnectRequest = _reflection.GeneratedProtocolMessageType( + "ConnectRequest", + (_message.Message,), + dict( + DESCRIPTOR=_CONNECTREQUEST, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:ConnectRequest) + ), +) _sym_db.RegisterMessage(ConnectRequest) -ConnectResponse = _reflection.GeneratedProtocolMessageType('ConnectResponse', (_message.Message,), dict( - DESCRIPTOR = _CONNECTRESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:ConnectResponse) - )) +ConnectResponse = _reflection.GeneratedProtocolMessageType( + "ConnectResponse", + (_message.Message,), + dict( + DESCRIPTOR=_CONNECTRESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:ConnectResponse) + ), +) _sym_db.RegisterMessage(ConnectResponse) -DisconnectRequest = _reflection.GeneratedProtocolMessageType('DisconnectRequest', (_message.Message,), dict( - DESCRIPTOR = _DISCONNECTREQUEST, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:DisconnectRequest) - )) +DisconnectRequest = _reflection.GeneratedProtocolMessageType( + "DisconnectRequest", + (_message.Message,), + dict( + DESCRIPTOR=_DISCONNECTREQUEST, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:DisconnectRequest) + ), +) _sym_db.RegisterMessage(DisconnectRequest) -DisconnectResponse = _reflection.GeneratedProtocolMessageType('DisconnectResponse', (_message.Message,), dict( - DESCRIPTOR = _DISCONNECTRESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:DisconnectResponse) - )) +DisconnectResponse = _reflection.GeneratedProtocolMessageType( + "DisconnectResponse", + (_message.Message,), + dict( + DESCRIPTOR=_DISCONNECTRESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:DisconnectResponse) + ), +) _sym_db.RegisterMessage(DisconnectResponse) -PingRequest = _reflection.GeneratedProtocolMessageType('PingRequest', (_message.Message,), dict( - DESCRIPTOR = _PINGREQUEST, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:PingRequest) - )) +PingRequest = _reflection.GeneratedProtocolMessageType( + "PingRequest", + (_message.Message,), + dict( + DESCRIPTOR=_PINGREQUEST, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:PingRequest) + ), +) _sym_db.RegisterMessage(PingRequest) -PingResponse = _reflection.GeneratedProtocolMessageType('PingResponse', (_message.Message,), dict( - DESCRIPTOR = _PINGRESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:PingResponse) - )) +PingResponse = _reflection.GeneratedProtocolMessageType( + "PingResponse", + (_message.Message,), + dict( + DESCRIPTOR=_PINGRESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:PingResponse) + ), +) _sym_db.RegisterMessage(PingResponse) -DeviceInfoRequest = _reflection.GeneratedProtocolMessageType('DeviceInfoRequest', (_message.Message,), dict( - DESCRIPTOR = _DEVICEINFOREQUEST, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:DeviceInfoRequest) - )) +DeviceInfoRequest = _reflection.GeneratedProtocolMessageType( + "DeviceInfoRequest", + (_message.Message,), + dict( + DESCRIPTOR=_DEVICEINFOREQUEST, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:DeviceInfoRequest) + ), +) _sym_db.RegisterMessage(DeviceInfoRequest) -DeviceInfoResponse = _reflection.GeneratedProtocolMessageType('DeviceInfoResponse', (_message.Message,), dict( - DESCRIPTOR = _DEVICEINFORESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:DeviceInfoResponse) - )) +DeviceInfoResponse = _reflection.GeneratedProtocolMessageType( + "DeviceInfoResponse", + (_message.Message,), + dict( + DESCRIPTOR=_DEVICEINFORESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:DeviceInfoResponse) + ), +) _sym_db.RegisterMessage(DeviceInfoResponse) -ListEntitiesRequest = _reflection.GeneratedProtocolMessageType('ListEntitiesRequest', (_message.Message,), dict( - DESCRIPTOR = _LISTENTITIESREQUEST, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:ListEntitiesRequest) - )) +ListEntitiesRequest = _reflection.GeneratedProtocolMessageType( + "ListEntitiesRequest", + (_message.Message,), + dict( + DESCRIPTOR=_LISTENTITIESREQUEST, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:ListEntitiesRequest) + ), +) _sym_db.RegisterMessage(ListEntitiesRequest) -ListEntitiesBinarySensorResponse = _reflection.GeneratedProtocolMessageType('ListEntitiesBinarySensorResponse', (_message.Message,), dict( - DESCRIPTOR = _LISTENTITIESBINARYSENSORRESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:ListEntitiesBinarySensorResponse) - )) +ListEntitiesBinarySensorResponse = _reflection.GeneratedProtocolMessageType( + "ListEntitiesBinarySensorResponse", + (_message.Message,), + dict( + DESCRIPTOR=_LISTENTITIESBINARYSENSORRESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:ListEntitiesBinarySensorResponse) + ), +) _sym_db.RegisterMessage(ListEntitiesBinarySensorResponse) -ListEntitiesCoverResponse = _reflection.GeneratedProtocolMessageType('ListEntitiesCoverResponse', (_message.Message,), dict( - DESCRIPTOR = _LISTENTITIESCOVERRESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:ListEntitiesCoverResponse) - )) +ListEntitiesCoverResponse = _reflection.GeneratedProtocolMessageType( + "ListEntitiesCoverResponse", + (_message.Message,), + dict( + DESCRIPTOR=_LISTENTITIESCOVERRESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:ListEntitiesCoverResponse) + ), +) _sym_db.RegisterMessage(ListEntitiesCoverResponse) -ListEntitiesFanResponse = _reflection.GeneratedProtocolMessageType('ListEntitiesFanResponse', (_message.Message,), dict( - DESCRIPTOR = _LISTENTITIESFANRESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:ListEntitiesFanResponse) - )) +ListEntitiesFanResponse = _reflection.GeneratedProtocolMessageType( + "ListEntitiesFanResponse", + (_message.Message,), + dict( + DESCRIPTOR=_LISTENTITIESFANRESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:ListEntitiesFanResponse) + ), +) _sym_db.RegisterMessage(ListEntitiesFanResponse) -ListEntitiesLightResponse = _reflection.GeneratedProtocolMessageType('ListEntitiesLightResponse', (_message.Message,), dict( - DESCRIPTOR = _LISTENTITIESLIGHTRESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:ListEntitiesLightResponse) - )) +ListEntitiesLightResponse = _reflection.GeneratedProtocolMessageType( + "ListEntitiesLightResponse", + (_message.Message,), + dict( + DESCRIPTOR=_LISTENTITIESLIGHTRESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:ListEntitiesLightResponse) + ), +) _sym_db.RegisterMessage(ListEntitiesLightResponse) -ListEntitiesSensorResponse = _reflection.GeneratedProtocolMessageType('ListEntitiesSensorResponse', (_message.Message,), dict( - DESCRIPTOR = _LISTENTITIESSENSORRESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:ListEntitiesSensorResponse) - )) +ListEntitiesSensorResponse = _reflection.GeneratedProtocolMessageType( + "ListEntitiesSensorResponse", + (_message.Message,), + dict( + DESCRIPTOR=_LISTENTITIESSENSORRESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:ListEntitiesSensorResponse) + ), +) _sym_db.RegisterMessage(ListEntitiesSensorResponse) -ListEntitiesSwitchResponse = _reflection.GeneratedProtocolMessageType('ListEntitiesSwitchResponse', (_message.Message,), dict( - DESCRIPTOR = _LISTENTITIESSWITCHRESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:ListEntitiesSwitchResponse) - )) +ListEntitiesSwitchResponse = _reflection.GeneratedProtocolMessageType( + "ListEntitiesSwitchResponse", + (_message.Message,), + dict( + DESCRIPTOR=_LISTENTITIESSWITCHRESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:ListEntitiesSwitchResponse) + ), +) _sym_db.RegisterMessage(ListEntitiesSwitchResponse) -ListEntitiesTextSensorResponse = _reflection.GeneratedProtocolMessageType('ListEntitiesTextSensorResponse', (_message.Message,), dict( - DESCRIPTOR = _LISTENTITIESTEXTSENSORRESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:ListEntitiesTextSensorResponse) - )) +ListEntitiesTextSensorResponse = _reflection.GeneratedProtocolMessageType( + "ListEntitiesTextSensorResponse", + (_message.Message,), + dict( + DESCRIPTOR=_LISTENTITIESTEXTSENSORRESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:ListEntitiesTextSensorResponse) + ), +) _sym_db.RegisterMessage(ListEntitiesTextSensorResponse) -ListEntitiesDoneResponse = _reflection.GeneratedProtocolMessageType('ListEntitiesDoneResponse', (_message.Message,), dict( - DESCRIPTOR = _LISTENTITIESDONERESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:ListEntitiesDoneResponse) - )) +ListEntitiesDoneResponse = _reflection.GeneratedProtocolMessageType( + "ListEntitiesDoneResponse", + (_message.Message,), + dict( + DESCRIPTOR=_LISTENTITIESDONERESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:ListEntitiesDoneResponse) + ), +) _sym_db.RegisterMessage(ListEntitiesDoneResponse) -SubscribeStatesRequest = _reflection.GeneratedProtocolMessageType('SubscribeStatesRequest', (_message.Message,), dict( - DESCRIPTOR = _SUBSCRIBESTATESREQUEST, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:SubscribeStatesRequest) - )) +SubscribeStatesRequest = _reflection.GeneratedProtocolMessageType( + "SubscribeStatesRequest", + (_message.Message,), + dict( + DESCRIPTOR=_SUBSCRIBESTATESREQUEST, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:SubscribeStatesRequest) + ), +) _sym_db.RegisterMessage(SubscribeStatesRequest) -BinarySensorStateResponse = _reflection.GeneratedProtocolMessageType('BinarySensorStateResponse', (_message.Message,), dict( - DESCRIPTOR = _BINARYSENSORSTATERESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:BinarySensorStateResponse) - )) +BinarySensorStateResponse = _reflection.GeneratedProtocolMessageType( + "BinarySensorStateResponse", + (_message.Message,), + dict( + DESCRIPTOR=_BINARYSENSORSTATERESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:BinarySensorStateResponse) + ), +) _sym_db.RegisterMessage(BinarySensorStateResponse) -CoverStateResponse = _reflection.GeneratedProtocolMessageType('CoverStateResponse', (_message.Message,), dict( - DESCRIPTOR = _COVERSTATERESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:CoverStateResponse) - )) +CoverStateResponse = _reflection.GeneratedProtocolMessageType( + "CoverStateResponse", + (_message.Message,), + dict( + DESCRIPTOR=_COVERSTATERESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:CoverStateResponse) + ), +) _sym_db.RegisterMessage(CoverStateResponse) -FanStateResponse = _reflection.GeneratedProtocolMessageType('FanStateResponse', (_message.Message,), dict( - DESCRIPTOR = _FANSTATERESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:FanStateResponse) - )) +FanStateResponse = _reflection.GeneratedProtocolMessageType( + "FanStateResponse", + (_message.Message,), + dict( + DESCRIPTOR=_FANSTATERESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:FanStateResponse) + ), +) _sym_db.RegisterMessage(FanStateResponse) -LightStateResponse = _reflection.GeneratedProtocolMessageType('LightStateResponse', (_message.Message,), dict( - DESCRIPTOR = _LIGHTSTATERESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:LightStateResponse) - )) +LightStateResponse = _reflection.GeneratedProtocolMessageType( + "LightStateResponse", + (_message.Message,), + dict( + DESCRIPTOR=_LIGHTSTATERESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:LightStateResponse) + ), +) _sym_db.RegisterMessage(LightStateResponse) -SensorStateResponse = _reflection.GeneratedProtocolMessageType('SensorStateResponse', (_message.Message,), dict( - DESCRIPTOR = _SENSORSTATERESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:SensorStateResponse) - )) +SensorStateResponse = _reflection.GeneratedProtocolMessageType( + "SensorStateResponse", + (_message.Message,), + dict( + DESCRIPTOR=_SENSORSTATERESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:SensorStateResponse) + ), +) _sym_db.RegisterMessage(SensorStateResponse) -SwitchStateResponse = _reflection.GeneratedProtocolMessageType('SwitchStateResponse', (_message.Message,), dict( - DESCRIPTOR = _SWITCHSTATERESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:SwitchStateResponse) - )) +SwitchStateResponse = _reflection.GeneratedProtocolMessageType( + "SwitchStateResponse", + (_message.Message,), + dict( + DESCRIPTOR=_SWITCHSTATERESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:SwitchStateResponse) + ), +) _sym_db.RegisterMessage(SwitchStateResponse) -TextSensorStateResponse = _reflection.GeneratedProtocolMessageType('TextSensorStateResponse', (_message.Message,), dict( - DESCRIPTOR = _TEXTSENSORSTATERESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:TextSensorStateResponse) - )) +TextSensorStateResponse = _reflection.GeneratedProtocolMessageType( + "TextSensorStateResponse", + (_message.Message,), + dict( + DESCRIPTOR=_TEXTSENSORSTATERESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:TextSensorStateResponse) + ), +) _sym_db.RegisterMessage(TextSensorStateResponse) -CoverCommandRequest = _reflection.GeneratedProtocolMessageType('CoverCommandRequest', (_message.Message,), dict( - DESCRIPTOR = _COVERCOMMANDREQUEST, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:CoverCommandRequest) - )) +CoverCommandRequest = _reflection.GeneratedProtocolMessageType( + "CoverCommandRequest", + (_message.Message,), + dict( + DESCRIPTOR=_COVERCOMMANDREQUEST, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:CoverCommandRequest) + ), +) _sym_db.RegisterMessage(CoverCommandRequest) -FanCommandRequest = _reflection.GeneratedProtocolMessageType('FanCommandRequest', (_message.Message,), dict( - DESCRIPTOR = _FANCOMMANDREQUEST, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:FanCommandRequest) - )) +FanCommandRequest = _reflection.GeneratedProtocolMessageType( + "FanCommandRequest", + (_message.Message,), + dict( + DESCRIPTOR=_FANCOMMANDREQUEST, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:FanCommandRequest) + ), +) _sym_db.RegisterMessage(FanCommandRequest) -LightCommandRequest = _reflection.GeneratedProtocolMessageType('LightCommandRequest', (_message.Message,), dict( - DESCRIPTOR = _LIGHTCOMMANDREQUEST, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:LightCommandRequest) - )) +LightCommandRequest = _reflection.GeneratedProtocolMessageType( + "LightCommandRequest", + (_message.Message,), + dict( + DESCRIPTOR=_LIGHTCOMMANDREQUEST, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:LightCommandRequest) + ), +) _sym_db.RegisterMessage(LightCommandRequest) -SwitchCommandRequest = _reflection.GeneratedProtocolMessageType('SwitchCommandRequest', (_message.Message,), dict( - DESCRIPTOR = _SWITCHCOMMANDREQUEST, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:SwitchCommandRequest) - )) +SwitchCommandRequest = _reflection.GeneratedProtocolMessageType( + "SwitchCommandRequest", + (_message.Message,), + dict( + DESCRIPTOR=_SWITCHCOMMANDREQUEST, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:SwitchCommandRequest) + ), +) _sym_db.RegisterMessage(SwitchCommandRequest) -SubscribeLogsRequest = _reflection.GeneratedProtocolMessageType('SubscribeLogsRequest', (_message.Message,), dict( - DESCRIPTOR = _SUBSCRIBELOGSREQUEST, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:SubscribeLogsRequest) - )) +SubscribeLogsRequest = _reflection.GeneratedProtocolMessageType( + "SubscribeLogsRequest", + (_message.Message,), + dict( + DESCRIPTOR=_SUBSCRIBELOGSREQUEST, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:SubscribeLogsRequest) + ), +) _sym_db.RegisterMessage(SubscribeLogsRequest) -SubscribeLogsResponse = _reflection.GeneratedProtocolMessageType('SubscribeLogsResponse', (_message.Message,), dict( - DESCRIPTOR = _SUBSCRIBELOGSRESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:SubscribeLogsResponse) - )) +SubscribeLogsResponse = _reflection.GeneratedProtocolMessageType( + "SubscribeLogsResponse", + (_message.Message,), + dict( + DESCRIPTOR=_SUBSCRIBELOGSRESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:SubscribeLogsResponse) + ), +) _sym_db.RegisterMessage(SubscribeLogsResponse) -SubscribeServiceCallsRequest = _reflection.GeneratedProtocolMessageType('SubscribeServiceCallsRequest', (_message.Message,), dict( - DESCRIPTOR = _SUBSCRIBESERVICECALLSREQUEST, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:SubscribeServiceCallsRequest) - )) +SubscribeServiceCallsRequest = _reflection.GeneratedProtocolMessageType( + "SubscribeServiceCallsRequest", + (_message.Message,), + dict( + DESCRIPTOR=_SUBSCRIBESERVICECALLSREQUEST, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:SubscribeServiceCallsRequest) + ), +) _sym_db.RegisterMessage(SubscribeServiceCallsRequest) -ServiceCallResponse = _reflection.GeneratedProtocolMessageType('ServiceCallResponse', (_message.Message,), dict( - - DataEntry = _reflection.GeneratedProtocolMessageType('DataEntry', (_message.Message,), dict( - DESCRIPTOR = _SERVICECALLRESPONSE_DATAENTRY, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:ServiceCallResponse.DataEntry) - )) - , - - DataTemplateEntry = _reflection.GeneratedProtocolMessageType('DataTemplateEntry', (_message.Message,), dict( - DESCRIPTOR = _SERVICECALLRESPONSE_DATATEMPLATEENTRY, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:ServiceCallResponse.DataTemplateEntry) - )) - , - - VariablesEntry = _reflection.GeneratedProtocolMessageType('VariablesEntry', (_message.Message,), dict( - DESCRIPTOR = _SERVICECALLRESPONSE_VARIABLESENTRY, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:ServiceCallResponse.VariablesEntry) - )) - , - DESCRIPTOR = _SERVICECALLRESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:ServiceCallResponse) - )) +ServiceCallResponse = _reflection.GeneratedProtocolMessageType( + "ServiceCallResponse", + (_message.Message,), + dict( + DataEntry=_reflection.GeneratedProtocolMessageType( + "DataEntry", + (_message.Message,), + dict( + DESCRIPTOR=_SERVICECALLRESPONSE_DATAENTRY, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:ServiceCallResponse.DataEntry) + ), + ), + DataTemplateEntry=_reflection.GeneratedProtocolMessageType( + "DataTemplateEntry", + (_message.Message,), + dict( + DESCRIPTOR=_SERVICECALLRESPONSE_DATATEMPLATEENTRY, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:ServiceCallResponse.DataTemplateEntry) + ), + ), + VariablesEntry=_reflection.GeneratedProtocolMessageType( + "VariablesEntry", + (_message.Message,), + dict( + DESCRIPTOR=_SERVICECALLRESPONSE_VARIABLESENTRY, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:ServiceCallResponse.VariablesEntry) + ), + ), + DESCRIPTOR=_SERVICECALLRESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:ServiceCallResponse) + ), +) _sym_db.RegisterMessage(ServiceCallResponse) _sym_db.RegisterMessage(ServiceCallResponse.DataEntry) _sym_db.RegisterMessage(ServiceCallResponse.DataTemplateEntry) _sym_db.RegisterMessage(ServiceCallResponse.VariablesEntry) -SubscribeHomeAssistantStatesRequest = _reflection.GeneratedProtocolMessageType('SubscribeHomeAssistantStatesRequest', (_message.Message,), dict( - DESCRIPTOR = _SUBSCRIBEHOMEASSISTANTSTATESREQUEST, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:SubscribeHomeAssistantStatesRequest) - )) +SubscribeHomeAssistantStatesRequest = _reflection.GeneratedProtocolMessageType( + "SubscribeHomeAssistantStatesRequest", + (_message.Message,), + dict( + DESCRIPTOR=_SUBSCRIBEHOMEASSISTANTSTATESREQUEST, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:SubscribeHomeAssistantStatesRequest) + ), +) _sym_db.RegisterMessage(SubscribeHomeAssistantStatesRequest) -SubscribeHomeAssistantStateResponse = _reflection.GeneratedProtocolMessageType('SubscribeHomeAssistantStateResponse', (_message.Message,), dict( - DESCRIPTOR = _SUBSCRIBEHOMEASSISTANTSTATERESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:SubscribeHomeAssistantStateResponse) - )) +SubscribeHomeAssistantStateResponse = _reflection.GeneratedProtocolMessageType( + "SubscribeHomeAssistantStateResponse", + (_message.Message,), + dict( + DESCRIPTOR=_SUBSCRIBEHOMEASSISTANTSTATERESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:SubscribeHomeAssistantStateResponse) + ), +) _sym_db.RegisterMessage(SubscribeHomeAssistantStateResponse) -HomeAssistantStateResponse = _reflection.GeneratedProtocolMessageType('HomeAssistantStateResponse', (_message.Message,), dict( - DESCRIPTOR = _HOMEASSISTANTSTATERESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:HomeAssistantStateResponse) - )) +HomeAssistantStateResponse = _reflection.GeneratedProtocolMessageType( + "HomeAssistantStateResponse", + (_message.Message,), + dict( + DESCRIPTOR=_HOMEASSISTANTSTATERESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:HomeAssistantStateResponse) + ), +) _sym_db.RegisterMessage(HomeAssistantStateResponse) -GetTimeRequest = _reflection.GeneratedProtocolMessageType('GetTimeRequest', (_message.Message,), dict( - DESCRIPTOR = _GETTIMEREQUEST, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:GetTimeRequest) - )) +GetTimeRequest = _reflection.GeneratedProtocolMessageType( + "GetTimeRequest", + (_message.Message,), + dict( + DESCRIPTOR=_GETTIMEREQUEST, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:GetTimeRequest) + ), +) _sym_db.RegisterMessage(GetTimeRequest) -GetTimeResponse = _reflection.GeneratedProtocolMessageType('GetTimeResponse', (_message.Message,), dict( - DESCRIPTOR = _GETTIMERESPONSE, - __module__ = 'api_pb2' - # @@protoc_insertion_point(class_scope:GetTimeResponse) - )) +GetTimeResponse = _reflection.GeneratedProtocolMessageType( + "GetTimeResponse", + (_message.Message,), + dict( + DESCRIPTOR=_GETTIMERESPONSE, + __module__="api_pb2" + # @@protoc_insertion_point(class_scope:GetTimeResponse) + ), +) _sym_db.RegisterMessage(GetTimeResponse) diff --git a/esphome/api/client.py b/esphome/api/client.py index a32c23981..84c9890fe 100644 --- a/esphome/api/client.py +++ b/esphome/api/client.py @@ -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(): diff --git a/esphome/automation.py b/esphome/automation.py index 4b5e39b0f..63e4ce037 100644 --- a/esphome/automation.py +++ b/esphome/automation.py @@ -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) diff --git a/esphome/codegen.py b/esphome/codegen.py index c30b43f95..57316ab4f 100644 --- a/esphome/codegen.py +++ b/esphome/codegen.py @@ -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, +) diff --git a/esphome/components/a4988/stepper.py b/esphome/components/a4988/stepper.py index 29696dbd5..1de3562ff 100644 --- a/esphome/components/a4988/stepper.py +++ b/esphome/components/a4988/stepper.py @@ -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): diff --git a/esphome/components/ac_dimmer/output.py b/esphome/components/ac_dimmer/output.py index 17dcd8ac2..2f06a0b6f 100644 --- a/esphome/components/ac_dimmer/output.py +++ b/esphome/components/ac_dimmer/output.py @@ -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): diff --git a/esphome/components/adalight/__init__.py b/esphome/components/adalight/__init__.py index 66fae17f1..169a13716 100644 --- a/esphome/components/adalight/__init__.py +++ b/esphome/components/adalight/__init__.py @@ -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) diff --git a/esphome/components/adc/__init__.py b/esphome/components/adc/__init__.py index 63db7aee2..f70ffa952 100644 --- a/esphome/components/adc/__init__.py +++ b/esphome/components/adc/__init__.py @@ -1 +1 @@ -CODEOWNERS = ['@esphome/core'] +CODEOWNERS = ["@esphome/core"] diff --git a/esphome/components/adc/sensor.py b/esphome/components/adc/sensor.py index 3c06eb91b..2e36c6179 100644 --- a/esphome/components/adc/sensor.py +++ b/esphome/components/adc/sensor.py @@ -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])) diff --git a/esphome/components/ade7953/sensor.py b/esphome/components/ade7953/sensor.py index 255695c4a..6bc991780 100644 --- a/esphome/components/ade7953/sensor.py +++ b/esphome/components/ade7953/sensor.py @@ -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)) diff --git a/esphome/components/ads1115/__init__.py b/esphome/components/ads1115/__init__.py index a41a521ba..32ab17db3 100644 --- a/esphome/components/ads1115/__init__.py +++ b/esphome/components/ads1115/__init__.py @@ -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): diff --git a/esphome/components/ads1115/sensor.py b/esphome/components/ads1115/sensor.py index 48f01337e..6eb39bdd1 100644 --- a/esphome/components/ads1115/sensor.py +++ b/esphome/components/ads1115/sensor.py @@ -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): diff --git a/esphome/components/aht10/sensor.py b/esphome/components/aht10/sensor.py index 17cbb8892..e335934a8 100644 --- a/esphome/components/aht10/sensor.py +++ b/esphome/components/aht10/sensor.py @@ -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): diff --git a/esphome/components/am2320/sensor.py b/esphome/components/am2320/sensor.py index 098315290..6d1cc4258 100644 --- a/esphome/components/am2320/sensor.py +++ b/esphome/components/am2320/sensor.py @@ -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): diff --git a/esphome/components/animation/__init__.py b/esphome/components/animation/__init__.py index f19dbd694..fbcb2b4c1 100644 --- a/esphome/components/animation/__init__.py +++ b/esphome/components/animation/__init__.py @@ -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]], + ) diff --git a/esphome/components/apds9960/__init__.py b/esphome/components/apds9960/__init__.py index 4725c1603..9346b5ece 100644 --- a/esphome/components/apds9960/__init__.py +++ b/esphome/components/apds9960/__init__.py @@ -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): diff --git a/esphome/components/apds9960/binary_sensor.py b/esphome/components/apds9960/binary_sensor.py index 440451090..043306138 100644 --- a/esphome/components/apds9960/binary_sensor.py +++ b/esphome/components/apds9960/binary_sensor.py @@ -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): diff --git a/esphome/components/apds9960/sensor.py b/esphome/components/apds9960/sensor.py index eb1008e71..a1ebd9b5c 100644 --- a/esphome/components/apds9960/sensor.py +++ b/esphome/components/apds9960/sensor.py @@ -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): diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index 884ae9867..d12c01e61 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -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) diff --git a/esphome/components/as3935/__init__.py b/esphome/components/as3935/__init__.py index 51958048c..337f0a908 100644 --- a/esphome/components/as3935/__init__.py +++ b/esphome/components/as3935/__init__.py @@ -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 diff --git a/esphome/components/as3935/binary_sensor.py b/esphome/components/as3935/binary_sensor.py index 3748c3484..85ba05286 100644 --- a/esphome/components/as3935/binary_sensor.py +++ b/esphome/components/as3935/binary_sensor.py @@ -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): diff --git a/esphome/components/as3935/sensor.py b/esphome/components/as3935/sensor.py index ff6f1d619..64eeea7b0 100644 --- a/esphome/components/as3935/sensor.py +++ b/esphome/components/as3935/sensor.py @@ -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): diff --git a/esphome/components/as3935_i2c/__init__.py b/esphome/components/as3935_i2c/__init__.py index e22937ab8..277ccd84d 100644 --- a/esphome/components/as3935_i2c/__init__.py +++ b/esphome/components/as3935_i2c/__init__.py @@ -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): diff --git a/esphome/components/as3935_spi/__init__.py b/esphome/components/as3935_spi/__init__.py index 30c2240c2..b921444b8 100644 --- a/esphome/components/as3935_spi/__init__.py +++ b/esphome/components/as3935_spi/__init__.py @@ -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): diff --git a/esphome/components/async_tcp/__init__.py b/esphome/components/async_tcp/__init__.py index b2307d5a7..b07db9ed7 100644 --- a/esphome/components/async_tcp/__init__.py +++ b/esphome/components/async_tcp/__init__.py @@ -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") diff --git a/esphome/components/atc_mithermometer/sensor.py b/esphome/components/atc_mithermometer/sensor.py index 73115ff4b..51891b33c 100644 --- a/esphome/components/atc_mithermometer/sensor.py +++ b/esphome/components/atc_mithermometer/sensor.py @@ -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): diff --git a/esphome/components/atm90e32/sensor.py b/esphome/components/atm90e32/sensor.py index f35232b7e..d0813cfa5 100644 --- a/esphome/components/atm90e32/sensor.py +++ b/esphome/components/atm90e32/sensor.py @@ -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): diff --git a/esphome/components/bang_bang/__init__.py b/esphome/components/bang_bang/__init__.py index 6f14e1003..71a87b6ae 100644 --- a/esphome/components/bang_bang/__init__.py +++ b/esphome/components/bang_bang/__init__.py @@ -1 +1 @@ -CODEOWNERS = ['@OttoWinter'] +CODEOWNERS = ["@OttoWinter"] diff --git a/esphome/components/bang_bang/climate.py b/esphome/components/bang_bang/climate.py index 4ef811c55..e0d75a6a1 100644 --- a/esphome/components/bang_bang/climate.py +++ b/esphome/components/bang_bang/climate.py @@ -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)) diff --git a/esphome/components/bh1750/sensor.py b/esphome/components/bh1750/sensor.py index 98777ab9c..9ad1b7ead 100644 --- a/esphome/components/bh1750/sensor.py +++ b/esphome/components/bh1750/sensor.py @@ -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): diff --git a/esphome/components/binary/__init__.py b/esphome/components/binary/__init__.py index 7a8031df5..3f6a45d28 100644 --- a/esphome/components/binary/__init__.py +++ b/esphome/components/binary/__init__.py @@ -1,3 +1,3 @@ import esphome.codegen as cg -binary_ns = cg.esphome_ns.namespace('binary') +binary_ns = cg.esphome_ns.namespace("binary") diff --git a/esphome/components/binary/fan/__init__.py b/esphome/components/binary/fan/__init__.py index 6969c1dbb..88dc50623 100644 --- a/esphome/components/binary/fan/__init__.py +++ b/esphome/components/binary/fan/__init__.py @@ -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): diff --git a/esphome/components/binary/light/__init__.py b/esphome/components/binary/light/__init__.py index 6167ae239..7e62f4705 100644 --- a/esphome/components/binary/light/__init__.py +++ b/esphome/components/binary/light/__init__.py @@ -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): diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index da1dc697a..56e6b7dc9 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -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) diff --git a/esphome/components/binary_sensor_map/sensor.py b/esphome/components/binary_sensor_map/sensor.py index ffd945bb5..81bc85e57 100644 --- a/esphome/components/binary_sensor_map/sensor.py +++ b/esphome/components/binary_sensor_map/sensor.py @@ -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): diff --git a/esphome/components/ble_presence/binary_sensor.py b/esphome/components/ble_presence/binary_sensor.py index 1cf800938..4c6e7ee56 100644 --- a/esphome/components/ble_presence/binary_sensor.py +++ b/esphome/components/ble_presence/binary_sensor.py @@ -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)) diff --git a/esphome/components/ble_rssi/sensor.py b/esphome/components/ble_rssi/sensor.py index 16903dd9d..f6ee209ae 100644 --- a/esphome/components/ble_rssi/sensor.py +++ b/esphome/components/ble_rssi/sensor.py @@ -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)) diff --git a/esphome/components/ble_scanner/text_sensor.py b/esphome/components/ble_scanner/text_sensor.py index 1a43ffb68..96c7b4d88 100644 --- a/esphome/components/ble_scanner/text_sensor.py +++ b/esphome/components/ble_scanner/text_sensor.py @@ -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): diff --git a/esphome/components/bme280/sensor.py b/esphome/components/bme280/sensor.py index 26e1df40e..5b0e418a6 100644 --- a/esphome/components/bme280/sensor.py +++ b/esphome/components/bme280/sensor.py @@ -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): diff --git a/esphome/components/bme680/sensor.py b/esphome/components/bme680/sensor.py index 705ddc41f..a82ecefe9 100644 --- a/esphome/components/bme680/sensor.py +++ b/esphome/components/bme680/sensor.py @@ -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): diff --git a/esphome/components/bmp085/sensor.py b/esphome/components/bmp085/sensor.py index e15fe1335..a070e4aa6 100644 --- a/esphome/components/bmp085/sensor.py +++ b/esphome/components/bmp085/sensor.py @@ -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): diff --git a/esphome/components/bmp280/sensor.py b/esphome/components/bmp280/sensor.py index c485cdb71..b12d7bff7 100644 --- a/esphome/components/bmp280/sensor.py +++ b/esphome/components/bmp280/sensor.py @@ -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): diff --git a/esphome/components/canbus/__init__.py b/esphome/components/canbus/__init__.py index 24decc14b..28501c7a8 100644 --- a/esphome/components/canbus/__init__.py +++ b/esphome/components/canbus/__init__.py @@ -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] diff --git a/esphome/components/captive_portal/__init__.py b/esphome/components/captive_portal/__init__.py index bb8b2198a..e158db674 100644 --- a/esphome/components/captive_portal/__init__.py +++ b/esphome/components/captive_portal/__init__.py @@ -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") diff --git a/esphome/components/ccs811/sensor.py b/esphome/components/ccs811/sensor.py index 869a49dcd..95b108a22 100644 --- a/esphome/components/ccs811/sensor.py +++ b/esphome/components/ccs811/sensor.py @@ -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): diff --git a/esphome/components/climate/__init__.py b/esphome/components/climate/__init__.py index 38e254bb9..7f74b62c6 100644 --- a/esphome/components/climate/__init__.py +++ b/esphome/components/climate/__init__.py @@ -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) diff --git a/esphome/components/climate_ir/__init__.py b/esphome/components/climate_ir/__init__.py index 40ab3f22e..8dcd75c31 100644 --- a/esphome/components/climate_ir/__init__.py +++ b/esphome/components/climate_ir/__init__.py @@ -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 diff --git a/esphome/components/climate_ir_lg/climate.py b/esphome/components/climate_ir_lg/climate.py index a3f573068..06e538d9c 100644 --- a/esphome/components/climate_ir_lg/climate.py +++ b/esphome/components/climate_ir_lg/climate.py @@ -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): diff --git a/esphome/components/color/__init__.py b/esphome/components/color/__init__.py index db2fc6c09..7c044040e 100644 --- a/esphome/components/color/__init__.py +++ b/esphome/components/color/__init__.py @@ -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)), + ) diff --git a/esphome/components/coolix/climate.py b/esphome/components/coolix/climate.py index 075fad5a4..b7a584643 100644 --- a/esphome/components/coolix/climate.py +++ b/esphome/components/coolix/climate.py @@ -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): diff --git a/esphome/components/cover/__init__.py b/esphome/components/cover/__init__.py index f39e7ba54..e731c1833 100644 --- a/esphome/components/cover/__init__.py +++ b/esphome/components/cover/__init__.py @@ -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) diff --git a/esphome/components/cse7766/sensor.py b/esphome/components/cse7766/sensor.py index 1c5fcd836..71e945861 100644 --- a/esphome/components/cse7766/sensor.py +++ b/esphome/components/cse7766/sensor.py @@ -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): diff --git a/esphome/components/ct_clamp/sensor.py b/esphome/components/ct_clamp/sensor.py index 276fd8f1a..e4dbd9238 100644 --- a/esphome/components/ct_clamp/sensor.py +++ b/esphome/components/ct_clamp/sensor.py @@ -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): diff --git a/esphome/components/custom/__init__.py b/esphome/components/custom/__init__.py index 0ef87cc6e..74450300f 100644 --- a/esphome/components/custom/__init__.py +++ b/esphome/components/custom/__init__.py @@ -1,3 +1,3 @@ import esphome.codegen as cg -custom_ns = cg.esphome_ns.namespace('custom') +custom_ns = cg.esphome_ns.namespace("custom") diff --git a/esphome/components/custom/binary_sensor/__init__.py b/esphome/components/custom/binary_sensor/__init__.py index 83b4a3dad..402540c25 100644 --- a/esphome/components/custom/binary_sensor/__init__.py +++ b/esphome/components/custom/binary_sensor/__init__.py @@ -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) diff --git a/esphome/components/custom/climate/__init__.py b/esphome/components/custom/climate/__init__.py index ed19452de..75f9c3247 100644 --- a/esphome/components/custom/climate/__init__.py +++ b/esphome/components/custom/climate/__init__.py @@ -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) diff --git a/esphome/components/custom/cover/__init__.py b/esphome/components/custom/cover/__init__.py index 3ab3ec1d0..35f25b827 100644 --- a/esphome/components/custom/cover/__init__.py +++ b/esphome/components/custom/cover/__init__.py @@ -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) diff --git a/esphome/components/custom/light/__init__.py b/esphome/components/custom/light/__init__.py index 61dd74e66..f4bd8331f 100644 --- a/esphome/components/custom/light/__init__.py +++ b/esphome/components/custom/light/__init__.py @@ -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) diff --git a/esphome/components/custom/output/__init__.py b/esphome/components/custom/output/__init__.py index efe6f19da..c803d89c3 100644 --- a/esphome/components/custom/output/__init__.py +++ b/esphome/components/custom/output/__init__.py @@ -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) diff --git a/esphome/components/custom/sensor/__init__.py b/esphome/components/custom/sensor/__init__.py index e6da4a733..2be14afc0 100644 --- a/esphome/components/custom/sensor/__init__.py +++ b/esphome/components/custom/sensor/__init__.py @@ -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) diff --git a/esphome/components/custom/switch/__init__.py b/esphome/components/custom/switch/__init__.py index fd619e676..a470c3e44 100644 --- a/esphome/components/custom/switch/__init__.py +++ b/esphome/components/custom/switch/__init__.py @@ -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) diff --git a/esphome/components/custom/text_sensor/__init__.py b/esphome/components/custom/text_sensor/__init__.py index 58db2a3f9..f09d72d22 100644 --- a/esphome/components/custom/text_sensor/__init__.py +++ b/esphome/components/custom/text_sensor/__init__.py @@ -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) diff --git a/esphome/components/custom_component/__init__.py b/esphome/components/custom_component/__init__.py index 198aa6a9e..fc154a82c 100644 --- a/esphome/components/custom_component/__init__.py +++ b/esphome/components/custom_component/__init__.py @@ -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) diff --git a/esphome/components/cwww/light.py b/esphome/components/cwww/light.py index 5cc426210..b099de435 100644 --- a/esphome/components/cwww/light.py +++ b/esphome/components/cwww/light.py @@ -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): diff --git a/esphome/components/daikin/climate.py b/esphome/components/daikin/climate.py index ff3f506fb..07bc079a9 100644 --- a/esphome/components/daikin/climate.py +++ b/esphome/components/daikin/climate.py @@ -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): diff --git a/esphome/components/dallas/__init__.py b/esphome/components/dallas/__init__.py index 85ab4300e..87049b8c6 100644 --- a/esphome/components/dallas/__init__.py +++ b/esphome/components/dallas/__init__.py @@ -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): diff --git a/esphome/components/dallas/sensor.py b/esphome/components/dallas/sensor.py index 457a21100..bb0a463a6 100644 --- a/esphome/components/dallas/sensor.py +++ b/esphome/components/dallas/sensor.py @@ -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): diff --git a/esphome/components/debug/__init__.py b/esphome/components/debug/__init__.py index d43b0de06..e43eb8bfc 100644 --- a/esphome/components/debug/__init__.py +++ b/esphome/components/debug/__init__.py @@ -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): diff --git a/esphome/components/deep_sleep/__init__.py b/esphome/components/deep_sleep/__init__.py index 9eafcc860..793d6b2eb 100644 --- a/esphome/components/deep_sleep/__init__.py +++ b/esphome/components/deep_sleep/__init__.py @@ -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) diff --git a/esphome/components/dfplayer/__init__.py b/esphome/components/dfplayer/__init__.py index 680a6b89e..33e74a220 100644 --- a/esphome/components/dfplayer/__init__.py +++ b/esphome/components/dfplayer/__init__.py @@ -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]) diff --git a/esphome/components/dht/__init__.py b/esphome/components/dht/__init__.py index 6f14e1003..71a87b6ae 100644 --- a/esphome/components/dht/__init__.py +++ b/esphome/components/dht/__init__.py @@ -1 +1 @@ -CODEOWNERS = ['@OttoWinter'] +CODEOWNERS = ["@OttoWinter"] diff --git a/esphome/components/dht/sensor.py b/esphome/components/dht/sensor.py index a8a101ddf..4b2f6ee8d 100644 --- a/esphome/components/dht/sensor.py +++ b/esphome/components/dht/sensor.py @@ -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): diff --git a/esphome/components/dht12/sensor.py b/esphome/components/dht12/sensor.py index 4e418dbc9..f63768142 100644 --- a/esphome/components/dht12/sensor.py +++ b/esphome/components/dht12/sensor.py @@ -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): diff --git a/esphome/components/display/__init__.py b/esphome/components/display/__init__.py index 951d561ca..f72ec88fa 100644 --- a/esphome/components/display/__init__.py +++ b/esphome/components/display/__init__.py @@ -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) diff --git a/esphome/components/ds1307/time.py b/esphome/components/ds1307/time.py index 371dc85be..9c1d75c02 100644 --- a/esphome/components/ds1307/time.py +++ b/esphome/components/ds1307/time.py @@ -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]) diff --git a/esphome/components/duty_cycle/sensor.py b/esphome/components/duty_cycle/sensor.py index 930745cfc..0dd91bade 100644 --- a/esphome/components/duty_cycle/sensor.py +++ b/esphome/components/duty_cycle/sensor.py @@ -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): diff --git a/esphome/components/e131/__init__.py b/esphome/components/e131/__init__.py index 0ba16bc92..b33aef8cf 100644 --- a/esphome/components/e131/__init__.py +++ b/esphome/components/e131/__init__.py @@ -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]) diff --git a/esphome/components/endstop/cover.py b/esphome/components/endstop/cover.py index 0d65cc107..b463d5d96 100644 --- a/esphome/components/endstop/cover.py +++ b/esphome/components/endstop/cover.py @@ -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])) diff --git a/esphome/components/esp32_ble_beacon/__init__.py b/esphome/components/esp32_ble_beacon/__init__.py index 2f02e71fe..46f567885 100644 --- a/esphome/components/esp32_ble_beacon/__init__.py +++ b/esphome/components/esp32_ble_beacon/__init__.py @@ -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])) diff --git a/esphome/components/esp32_ble_tracker/__init__.py b/esphome/components/esp32_ble_tracker/__init__.py index c4cc7260f..2e567b49b 100644 --- a/esphome/components/esp32_ble_tracker/__init__.py +++ b/esphome/components/esp32_ble_tracker/__init__.py @@ -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 diff --git a/esphome/components/esp32_camera/__init__.py b/esphome/components/esp32_camera/__init__.py index 57a6394c8..f7169257a 100644 --- a/esphome/components/esp32_camera/__init__.py +++ b/esphome/components/esp32_camera/__init__.py @@ -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") diff --git a/esphome/components/esp32_dac/output.py b/esphome/components/esp32_dac/output.py index bb0a8b60e..8cfc7570e 100644 --- a/esphome/components/esp32_dac/output.py +++ b/esphome/components/esp32_dac/output.py @@ -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): diff --git a/esphome/components/esp32_hall/sensor.py b/esphome/components/esp32_hall/sensor.py index 02a4b4900..363b3f754 100644 --- a/esphome/components/esp32_hall/sensor.py +++ b/esphome/components/esp32_hall/sensor.py @@ -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): diff --git a/esphome/components/esp32_touch/__init__.py b/esphome/components/esp32_touch/__init__.py index 3bdc988fc..5c3b47af7 100644 --- a/esphome/components/esp32_touch/__init__.py +++ b/esphome/components/esp32_touch/__init__.py @@ -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]] + ) + ) diff --git a/esphome/components/esp32_touch/binary_sensor.py b/esphome/components/esp32_touch/binary_sensor.py index 5142879a0..f8bc34813 100644 --- a/esphome/components/esp32_touch/binary_sensor.py +++ b/esphome/components/esp32_touch/binary_sensor.py @@ -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)) diff --git a/esphome/components/esp8266_pwm/output.py b/esphome/components/esp8266_pwm/output.py index e97349052..ad7da4e00 100644 --- a/esphome/components/esp8266_pwm/output.py +++ b/esphome/components/esp8266_pwm/output.py @@ -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) diff --git a/esphome/components/ethernet/__init__.py b/esphome/components/ethernet/__init__.py index ce7422d05..ca00f3335 100644 --- a/esphome/components/ethernet/__init__.py +++ b/esphome/components/ethernet/__init__.py @@ -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") diff --git a/esphome/components/exposure_notifications/__init__.py b/esphome/components/exposure_notifications/__init__.py index 8175a2d3a..1bd800778 100644 --- a/esphome/components/exposure_notifications/__init__.py +++ b/esphome/components/exposure_notifications/__init__.py @@ -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) diff --git a/esphome/components/ezo/sensor.py b/esphome/components/ezo/sensor.py index ee896eea1..12640f403 100644 --- a/esphome/components/ezo/sensor.py +++ b/esphome/components/ezo/sensor.py @@ -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): diff --git a/esphome/components/fan/__init__.py b/esphome/components/fan/__init__.py index 7b0a79a0d..79ed72f49 100644 --- a/esphome/components/fan/__init__.py +++ b/esphome/components/fan/__init__.py @@ -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) diff --git a/esphome/components/fastled_base/__init__.py b/esphome/components/fastled_base/__init__.py index ab78f7537..4c720191b 100644 --- a/esphome/components/fastled_base/__init__.py +++ b/esphome/components/fastled_base/__init__.py @@ -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 diff --git a/esphome/components/fastled_clockless/light.py b/esphome/components/fastled_clockless/light.py index 30fa910e5..b8a36ff39 100644 --- a/esphome/components/fastled_clockless/light.py +++ b/esphome/components/fastled_clockless/light.py @@ -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])) diff --git a/esphome/components/fastled_spi/light.py b/esphome/components/fastled_spi/light.py index ef14c0573..11e0a8159 100644 --- a/esphome/components/fastled_spi/light.py +++ b/esphome/components/fastled_spi/light.py @@ -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])) diff --git a/esphome/components/font/__init__.py b/esphome/components/font/__init__.py index ee50b1083..e79d311da 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -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 diff --git a/esphome/components/fujitsu_general/climate.py b/esphome/components/fujitsu_general/climate.py index a6774c397..64319eff2 100644 --- a/esphome/components/fujitsu_general/climate.py +++ b/esphome/components/fujitsu_general/climate.py @@ -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): diff --git a/esphome/components/globals/__init__.py b/esphome/components/globals/__init__.py index f1c4f4faf..9ec3bc17c 100644 --- a/esphome/components/globals/__init__.py +++ b/esphome/components/globals/__init__.py @@ -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 diff --git a/esphome/components/gpio/__init__.py b/esphome/components/gpio/__init__.py index c36ba8f43..07ebb64cd 100644 --- a/esphome/components/gpio/__init__.py +++ b/esphome/components/gpio/__init__.py @@ -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") diff --git a/esphome/components/gpio/binary_sensor/__init__.py b/esphome/components/gpio/binary_sensor/__init__.py index e269de5a7..4a24efcdb 100644 --- a/esphome/components/gpio/binary_sensor/__init__.py +++ b/esphome/components/gpio/binary_sensor/__init__.py @@ -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): diff --git a/esphome/components/gpio/output/__init__.py b/esphome/components/gpio/output/__init__.py index bab23c824..d98a49056 100644 --- a/esphome/components/gpio/output/__init__.py +++ b/esphome/components/gpio/output/__init__.py @@ -5,13 +5,14 @@ from esphome.components import output from esphome.const import CONF_ID, CONF_PIN from .. import gpio_ns -GPIOBinaryOutput = gpio_ns.class_('GPIOBinaryOutput', output.BinaryOutput, - cg.Component) +GPIOBinaryOutput = gpio_ns.class_("GPIOBinaryOutput", output.BinaryOutput, cg.Component) -CONFIG_SCHEMA = output.BINARY_OUTPUT_SCHEMA.extend({ - cv.Required(CONF_ID): cv.declare_id(GPIOBinaryOutput), - cv.Required(CONF_PIN): pins.gpio_output_pin_schema, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = output.BINARY_OUTPUT_SCHEMA.extend( + { + cv.Required(CONF_ID): cv.declare_id(GPIOBinaryOutput), + cv.Required(CONF_PIN): pins.gpio_output_pin_schema, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/gpio/switch/__init__.py b/esphome/components/gpio/switch/__init__.py index f75bc7100..ebd12d10c 100644 --- a/esphome/components/gpio/switch/__init__.py +++ b/esphome/components/gpio/switch/__init__.py @@ -5,25 +5,30 @@ from esphome.components import switch from esphome.const import CONF_ID, CONF_INTERLOCK, CONF_PIN, CONF_RESTORE_MODE from .. import gpio_ns -GPIOSwitch = gpio_ns.class_('GPIOSwitch', switch.Switch, cg.Component) -GPIOSwitchRestoreMode = gpio_ns.enum('GPIOSwitchRestoreMode') +GPIOSwitch = gpio_ns.class_("GPIOSwitch", switch.Switch, cg.Component) +GPIOSwitchRestoreMode = gpio_ns.enum("GPIOSwitchRestoreMode") RESTORE_MODES = { - 'RESTORE_DEFAULT_OFF': GPIOSwitchRestoreMode.GPIO_SWITCH_RESTORE_DEFAULT_OFF, - 'RESTORE_DEFAULT_ON': GPIOSwitchRestoreMode.GPIO_SWITCH_RESTORE_DEFAULT_ON, - 'ALWAYS_OFF': GPIOSwitchRestoreMode.GPIO_SWITCH_ALWAYS_OFF, - 'ALWAYS_ON': GPIOSwitchRestoreMode.GPIO_SWITCH_ALWAYS_ON, + "RESTORE_DEFAULT_OFF": GPIOSwitchRestoreMode.GPIO_SWITCH_RESTORE_DEFAULT_OFF, + "RESTORE_DEFAULT_ON": GPIOSwitchRestoreMode.GPIO_SWITCH_RESTORE_DEFAULT_ON, + "ALWAYS_OFF": GPIOSwitchRestoreMode.GPIO_SWITCH_ALWAYS_OFF, + "ALWAYS_ON": GPIOSwitchRestoreMode.GPIO_SWITCH_ALWAYS_ON, } -CONF_INTERLOCK_WAIT_TIME = 'interlock_wait_time' -CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(GPIOSwitch), - cv.Required(CONF_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_RESTORE_MODE, default='RESTORE_DEFAULT_OFF'): - cv.enum(RESTORE_MODES, upper=True, space='_'), - cv.Optional(CONF_INTERLOCK): cv.ensure_list(cv.use_id(switch.Switch)), - cv.Optional(CONF_INTERLOCK_WAIT_TIME, default='0ms'): cv.positive_time_period_milliseconds, -}).extend(cv.COMPONENT_SCHEMA) +CONF_INTERLOCK_WAIT_TIME = "interlock_wait_time" +CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(GPIOSwitch), + cv.Required(CONF_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_RESTORE_MODE, default="RESTORE_DEFAULT_OFF"): cv.enum( + RESTORE_MODES, upper=True, space="_" + ), + cv.Optional(CONF_INTERLOCK): cv.ensure_list(cv.use_id(switch.Switch)), + cv.Optional( + CONF_INTERLOCK_WAIT_TIME, default="0ms" + ): cv.positive_time_period_milliseconds, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/gps/__init__.py b/esphome/components/gps/__init__.py index ddbd29d5f..60dcc2002 100644 --- a/esphome/components/gps/__init__.py +++ b/esphome/components/gps/__init__.py @@ -3,17 +3,23 @@ import esphome.config_validation as cv from esphome.components import uart from esphome.const import CONF_ID -DEPENDENCIES = ['uart'] +DEPENDENCIES = ["uart"] -gps_ns = cg.esphome_ns.namespace('gps') -GPS = gps_ns.class_('GPS', cg.Component, uart.UARTDevice) -GPSListener = gps_ns.class_('GPSListener') +gps_ns = cg.esphome_ns.namespace("gps") +GPS = gps_ns.class_("GPS", cg.Component, uart.UARTDevice) +GPSListener = gps_ns.class_("GPSListener") -CONF_GPS_ID = 'gps_id' +CONF_GPS_ID = "gps_id" MULTI_CONF = True -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(GPS), -}).extend(cv.COMPONENT_SCHEMA).extend(uart.UART_DEVICE_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(GPS), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(uart.UART_DEVICE_SCHEMA) +) def to_code(config): @@ -22,4 +28,4 @@ def to_code(config): yield uart.register_uart_device(var, config) # https://platformio.org/lib/show/1655/TinyGPSPlus - cg.add_library('1655', '1.0.2') # TinyGPSPlus, has name conflict + cg.add_library("1655", "1.0.2") # TinyGPSPlus, has name conflict diff --git a/esphome/components/gps/time/__init__.py b/esphome/components/gps/time/__init__.py index 421d2e671..24ea263f6 100644 --- a/esphome/components/gps/time/__init__.py +++ b/esphome/components/gps/time/__init__.py @@ -4,14 +4,18 @@ import esphome.codegen as cg from esphome.const import CONF_ID from .. import gps_ns, GPSListener, CONF_GPS_ID, GPS -DEPENDENCIES = ['gps'] +DEPENDENCIES = ["gps"] -GPSTime = gps_ns.class_('GPSTime', cg.PollingComponent, time_.RealTimeClock, GPSListener) +GPSTime = gps_ns.class_( + "GPSTime", cg.PollingComponent, time_.RealTimeClock, GPSListener +) -CONFIG_SCHEMA = time_.TIME_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(GPSTime), - cv.GenerateID(CONF_GPS_ID): cv.use_id(GPS), -}).extend(cv.polling_component_schema('5min')) +CONFIG_SCHEMA = time_.TIME_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(GPSTime), + cv.GenerateID(CONF_GPS_ID): cv.use_id(GPS), + } +).extend(cv.polling_component_schema("5min")) def to_code(config): diff --git a/esphome/components/hbridge/light.py b/esphome/components/hbridge/light.py index abaf7152d..6c695fbd4 100644 --- a/esphome/components/hbridge/light.py +++ b/esphome/components/hbridge/light.py @@ -3,14 +3,18 @@ import esphome.config_validation as cv from esphome.components import light, output from esphome.const import CONF_OUTPUT_ID, CONF_PIN_A, CONF_PIN_B -hbridge_ns = cg.esphome_ns.namespace('hbridge') -HBridgeLightOutput = hbridge_ns.class_('HBridgeLightOutput', cg.PollingComponent, light.LightOutput) +hbridge_ns = cg.esphome_ns.namespace("hbridge") +HBridgeLightOutput = hbridge_ns.class_( + "HBridgeLightOutput", cg.PollingComponent, light.LightOutput +) -CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend({ - cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(HBridgeLightOutput), - cv.Required(CONF_PIN_A): cv.use_id(output.FloatOutput), - cv.Required(CONF_PIN_B): cv.use_id(output.FloatOutput), -}) +CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend( + { + cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(HBridgeLightOutput), + cv.Required(CONF_PIN_A): cv.use_id(output.FloatOutput), + cv.Required(CONF_PIN_B): cv.use_id(output.FloatOutput), + } +) def to_code(config): diff --git a/esphome/components/hdc1080/sensor.py b/esphome/components/hdc1080/sensor.py index fe80374be..15a92cccf 100644 --- a/esphome/components/hdc1080/sensor.py +++ b/esphome/components/hdc1080/sensor.py @@ -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, 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"] -hdc1080_ns = cg.esphome_ns.namespace('hdc1080') -HDC1080Component = hdc1080_ns.class_('HDC1080Component', cg.PollingComponent, i2c.I2CDevice) +hdc1080_ns = cg.esphome_ns.namespace("hdc1080") +HDC1080Component = hdc1080_ns.class_( + "HDC1080Component", cg.PollingComponent, i2c.I2CDevice +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(HDC1080Component), - 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), -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x40)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(HDC1080Component), + 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 + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x40)) +) def to_code(config): diff --git a/esphome/components/hitachi_ac344/climate.py b/esphome/components/hitachi_ac344/climate.py index fb1c21b20..9ae0cd39d 100644 --- a/esphome/components/hitachi_ac344/climate.py +++ b/esphome/components/hitachi_ac344/climate.py @@ -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"] -hitachi_ac344_ns = cg.esphome_ns.namespace('hitachi_ac344') -HitachiClimate = hitachi_ac344_ns.class_('HitachiClimate', climate_ir.ClimateIR) +hitachi_ac344_ns = cg.esphome_ns.namespace("hitachi_ac344") +HitachiClimate = hitachi_ac344_ns.class_("HitachiClimate", climate_ir.ClimateIR) -CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(HitachiClimate), -}) +CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(HitachiClimate), + } +) def to_code(config): diff --git a/esphome/components/hlw8012/sensor.py b/esphome/components/hlw8012/sensor.py index 74230c53c..28aa24d7c 100644 --- a/esphome/components/hlw8012/sensor.py +++ b/esphome/components/hlw8012/sensor.py @@ -2,43 +2,72 @@ 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_CHANGE_MODE_EVERY, CONF_INITIAL_MODE, CONF_CURRENT, \ - CONF_CURRENT_RESISTOR, CONF_ID, CONF_POWER, CONF_ENERGY, CONF_SEL_PIN, CONF_VOLTAGE, \ - CONF_VOLTAGE_DIVIDER, DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, DEVICE_CLASS_POWER, \ - DEVICE_CLASS_VOLTAGE, ICON_EMPTY, UNIT_VOLT, UNIT_AMPERE, UNIT_WATT, UNIT_WATT_HOURS +from esphome.const import ( + CONF_CHANGE_MODE_EVERY, + CONF_INITIAL_MODE, + CONF_CURRENT, + CONF_CURRENT_RESISTOR, + CONF_ID, + CONF_POWER, + CONF_ENERGY, + CONF_SEL_PIN, + CONF_VOLTAGE, + CONF_VOLTAGE_DIVIDER, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_ENERGY, + DEVICE_CLASS_POWER, + DEVICE_CLASS_VOLTAGE, + ICON_EMPTY, + UNIT_VOLT, + UNIT_AMPERE, + UNIT_WATT, + UNIT_WATT_HOURS, +) -AUTO_LOAD = ['pulse_counter'] +AUTO_LOAD = ["pulse_counter"] -hlw8012_ns = cg.esphome_ns.namespace('hlw8012') -HLW8012Component = hlw8012_ns.class_('HLW8012Component', cg.PollingComponent) -HLW8012InitialMode = hlw8012_ns.enum('HLW8012InitialMode') +hlw8012_ns = cg.esphome_ns.namespace("hlw8012") +HLW8012Component = hlw8012_ns.class_("HLW8012Component", cg.PollingComponent) +HLW8012InitialMode = hlw8012_ns.enum("HLW8012InitialMode") INITIAL_MODES = { CONF_CURRENT: HLW8012InitialMode.HLW8012_INITIAL_MODE_CURRENT, CONF_VOLTAGE: HLW8012InitialMode.HLW8012_INITIAL_MODE_VOLTAGE, } -CONF_CF1_PIN = 'cf1_pin' -CONF_CF_PIN = 'cf_pin' -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(HLW8012Component), - cv.Required(CONF_SEL_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_CF_PIN): cv.All(pins.internal_gpio_input_pullup_pin_schema, - pins.validate_has_interrupt), - cv.Required(CONF_CF1_PIN): cv.All(pins.internal_gpio_input_pullup_pin_schema, - pins.validate_has_interrupt), - - 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), - cv.Optional(CONF_ENERGY): sensor.sensor_schema(UNIT_WATT_HOURS, ICON_EMPTY, 1, - DEVICE_CLASS_ENERGY), - - cv.Optional(CONF_CURRENT_RESISTOR, default=0.001): cv.resistance, - cv.Optional(CONF_VOLTAGE_DIVIDER, default=2351): cv.positive_float, - cv.Optional(CONF_CHANGE_MODE_EVERY, default=8): cv.All(cv.uint32_t, cv.Range(min=1)), - cv.Optional(CONF_INITIAL_MODE, default=CONF_VOLTAGE): cv.one_of(*INITIAL_MODES, lower=True), -}).extend(cv.polling_component_schema('60s')) +CONF_CF1_PIN = "cf1_pin" +CONF_CF_PIN = "cf_pin" +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(HLW8012Component), + cv.Required(CONF_SEL_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_CF_PIN): cv.All( + pins.internal_gpio_input_pullup_pin_schema, pins.validate_has_interrupt + ), + cv.Required(CONF_CF1_PIN): cv.All( + pins.internal_gpio_input_pullup_pin_schema, pins.validate_has_interrupt + ), + 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 + ), + cv.Optional(CONF_ENERGY): sensor.sensor_schema( + UNIT_WATT_HOURS, ICON_EMPTY, 1, DEVICE_CLASS_ENERGY + ), + cv.Optional(CONF_CURRENT_RESISTOR, default=0.001): cv.resistance, + cv.Optional(CONF_VOLTAGE_DIVIDER, default=2351): cv.positive_float, + cv.Optional(CONF_CHANGE_MODE_EVERY, default=8): cv.All( + cv.uint32_t, cv.Range(min=1) + ), + cv.Optional(CONF_INITIAL_MODE, default=CONF_VOLTAGE): cv.one_of( + *INITIAL_MODES, lower=True + ), + } +).extend(cv.polling_component_schema("60s")) def to_code(config): diff --git a/esphome/components/hm3301/sensor.py b/esphome/components/hm3301/sensor.py index 67bfd3541..14ca2e77b 100644 --- a/esphome/components/hm3301/sensor.py +++ b/esphome/components/hm3301/sensor.py @@ -1,22 +1,31 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, sensor -from esphome.const import CONF_ID, CONF_PM_2_5, CONF_PM_10_0, CONF_PM_1_0, DEVICE_CLASS_EMPTY, \ - UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_CHEMICAL_WEAPON +from esphome.const import ( + CONF_ID, + CONF_PM_2_5, + CONF_PM_10_0, + CONF_PM_1_0, + DEVICE_CLASS_EMPTY, + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -hm3301_ns = cg.esphome_ns.namespace('hm3301') -HM3301Component = hm3301_ns.class_('HM3301Component', cg.PollingComponent, i2c.I2CDevice) -AQICalculatorType = hm3301_ns.enum('AQICalculatorType') +hm3301_ns = cg.esphome_ns.namespace("hm3301") +HM3301Component = hm3301_ns.class_( + "HM3301Component", cg.PollingComponent, i2c.I2CDevice +) +AQICalculatorType = hm3301_ns.enum("AQICalculatorType") -CONF_AQI = 'aqi' -CONF_CALCULATION_TYPE = 'calculation_type' -UNIT_INDEX = 'index' +CONF_AQI = "aqi" +CONF_CALCULATION_TYPE = "calculation_type" +UNIT_INDEX = "index" AQI_CALCULATION_TYPE = { - 'CAQI': AQICalculatorType.CAQI_TYPE, - 'AQI': AQICalculatorType.AQI_TYPE + "CAQI": AQICalculatorType.CAQI_TYPE, + "AQI": AQICalculatorType.AQI_TYPE, } @@ -28,23 +37,43 @@ def validate(config): return config -CONFIG_SCHEMA = cv.All(cv.Schema({ - cv.GenerateID(): cv.declare_id(HM3301Component), - - cv.Optional(CONF_PM_1_0): - sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_CHEMICAL_WEAPON, 0, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_PM_2_5): - sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_CHEMICAL_WEAPON, 0, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_PM_10_0): - sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_CHEMICAL_WEAPON, 0, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_AQI): - sensor.sensor_schema(UNIT_INDEX, ICON_CHEMICAL_WEAPON, 0, DEVICE_CLASS_EMPTY).extend({ - cv.Required(CONF_CALCULATION_TYPE): cv.enum(AQI_CALCULATION_TYPE, upper=True), - }) -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x40)), validate) +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(HM3301Component), + cv.Optional(CONF_PM_1_0): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, + 0, + DEVICE_CLASS_EMPTY, + ), + cv.Optional(CONF_PM_2_5): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, + 0, + DEVICE_CLASS_EMPTY, + ), + cv.Optional(CONF_PM_10_0): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, + 0, + DEVICE_CLASS_EMPTY, + ), + cv.Optional(CONF_AQI): sensor.sensor_schema( + UNIT_INDEX, ICON_CHEMICAL_WEAPON, 0, DEVICE_CLASS_EMPTY + ).extend( + { + cv.Required(CONF_CALCULATION_TYPE): cv.enum( + AQI_CALCULATION_TYPE, upper=True + ), + } + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x40)), + validate, +) def to_code(config): @@ -70,4 +99,4 @@ def to_code(config): cg.add(var.set_aqi_calculation_type(config[CONF_AQI][CONF_CALCULATION_TYPE])) # https://platformio.org/lib/show/6306/Grove%20-%20Laser%20PM2.5%20Sensor%20HM3301 - cg.add_library('6306', '1.0.3') + cg.add_library("6306", "1.0.3") diff --git a/esphome/components/hmc5883l/sensor.py b/esphome/components/hmc5883l/sensor.py index d98569493..d057caf03 100644 --- a/esphome/components/hmc5883l/sensor.py +++ b/esphome/components/hmc5883l/sensor.py @@ -1,22 +1,33 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, sensor -from esphome.const import CONF_ADDRESS, CONF_ID, CONF_OVERSAMPLING, CONF_RANGE, \ - DEVICE_CLASS_EMPTY, ICON_MAGNET, UNIT_MICROTESLA, UNIT_DEGREES, ICON_SCREEN_ROTATION, \ - CONF_UPDATE_INTERVAL +from esphome.const import ( + CONF_ADDRESS, + CONF_ID, + CONF_OVERSAMPLING, + CONF_RANGE, + DEVICE_CLASS_EMPTY, + ICON_MAGNET, + UNIT_MICROTESLA, + UNIT_DEGREES, + ICON_SCREEN_ROTATION, + CONF_UPDATE_INTERVAL, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -hmc5883l_ns = cg.esphome_ns.namespace('hmc5883l') +hmc5883l_ns = cg.esphome_ns.namespace("hmc5883l") -CONF_FIELD_STRENGTH_X = 'field_strength_x' -CONF_FIELD_STRENGTH_Y = 'field_strength_y' -CONF_FIELD_STRENGTH_Z = 'field_strength_z' -CONF_HEADING = 'heading' +CONF_FIELD_STRENGTH_X = "field_strength_x" +CONF_FIELD_STRENGTH_Y = "field_strength_y" +CONF_FIELD_STRENGTH_Z = "field_strength_z" +CONF_HEADING = "heading" -HMC5883LComponent = hmc5883l_ns.class_('HMC5883LComponent', cg.PollingComponent, i2c.I2CDevice) +HMC5883LComponent = hmc5883l_ns.class_( + "HMC5883LComponent", cg.PollingComponent, i2c.I2CDevice +) -HMC5883LOversampling = hmc5883l_ns.enum('HMC5883LOversampling') +HMC5883LOversampling = hmc5883l_ns.enum("HMC5883LOversampling") HMC5883LOversamplings = { 1: HMC5883LOversampling.HMC5883L_OVERSAMPLING_1, 2: HMC5883LOversampling.HMC5883L_OVERSAMPLING_2, @@ -24,7 +35,7 @@ HMC5883LOversamplings = { 8: HMC5883LOversampling.HMC5883L_OVERSAMPLING_8, } -HMC5883LDatarate = hmc5883l_ns.enum('HMC5883LDatarate') +HMC5883LDatarate = hmc5883l_ns.enum("HMC5883LDatarate") HMC5883LDatarates = { 0.75: HMC5883LDatarate.HMC5883L_DATARATE_0_75_HZ, 1.5: HMC5883LDatarate.HMC5883L_DATARATE_1_5_HZ, @@ -35,7 +46,7 @@ HMC5883LDatarates = { 75: HMC5883LDatarate.HMC5883L_DATARATE_75_0_HZ, } -HMC5883LRange = hmc5883l_ns.enum('HMC5883LRange') +HMC5883LRange = hmc5883l_ns.enum("HMC5883LRange") HMC5883L_RANGES = { 88: HMC5883LRange.HMC5883L_RANGE_88_UT, 130: HMC5883LRange.HMC5883L_RANGE_130_UT, @@ -59,30 +70,45 @@ def validate_enum(enum_values, units=None, int=True): value = cv.string(value) for unit in _units: if value.endswith(unit): - value = value[:-len(unit)] + value = value[: -len(unit)] break return enum_bound(value) + return validate_enum_bound -field_strength_schema = sensor.sensor_schema(UNIT_MICROTESLA, ICON_MAGNET, 1, DEVICE_CLASS_EMPTY) -heading_schema = sensor.sensor_schema(UNIT_DEGREES, ICON_SCREEN_ROTATION, 1, DEVICE_CLASS_EMPTY) +field_strength_schema = sensor.sensor_schema( + UNIT_MICROTESLA, ICON_MAGNET, 1, DEVICE_CLASS_EMPTY +) +heading_schema = sensor.sensor_schema( + UNIT_DEGREES, ICON_SCREEN_ROTATION, 1, DEVICE_CLASS_EMPTY +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(HMC5883LComponent), - cv.Optional(CONF_ADDRESS): cv.i2c_address, - cv.Optional(CONF_OVERSAMPLING, default='1x'): validate_enum(HMC5883LOversamplings, units="x"), - cv.Optional(CONF_RANGE, default='130µT'): validate_enum(HMC5883L_RANGES, units=["uT", "µT"]), - cv.Optional(CONF_FIELD_STRENGTH_X): field_strength_schema, - cv.Optional(CONF_FIELD_STRENGTH_Y): field_strength_schema, - cv.Optional(CONF_FIELD_STRENGTH_Z): field_strength_schema, - cv.Optional(CONF_HEADING): heading_schema, -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x1E)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(HMC5883LComponent), + cv.Optional(CONF_ADDRESS): cv.i2c_address, + cv.Optional(CONF_OVERSAMPLING, default="1x"): validate_enum( + HMC5883LOversamplings, units="x" + ), + cv.Optional(CONF_RANGE, default="130µT"): validate_enum( + HMC5883L_RANGES, units=["uT", "µT"] + ), + cv.Optional(CONF_FIELD_STRENGTH_X): field_strength_schema, + cv.Optional(CONF_FIELD_STRENGTH_Y): field_strength_schema, + cv.Optional(CONF_FIELD_STRENGTH_Z): field_strength_schema, + cv.Optional(CONF_HEADING): heading_schema, + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x1E)) +) def auto_data_rate(config): interval_sec = config[CONF_UPDATE_INTERVAL].seconds - interval_hz = 1.0/interval_sec + interval_hz = 1.0 / interval_sec for datarate in sorted(HMC5883LDatarates.keys()): if float(datarate) >= interval_hz: return HMC5883LDatarates[datarate] diff --git a/esphome/components/homeassistant/__init__.py b/esphome/components/homeassistant/__init__.py index 69d759b97..c151abc25 100644 --- a/esphome/components/homeassistant/__init__.py +++ b/esphome/components/homeassistant/__init__.py @@ -1,4 +1,4 @@ import esphome.codegen as cg -CODEOWNERS = ['@OttoWinter'] -homeassistant_ns = cg.esphome_ns.namespace('homeassistant') +CODEOWNERS = ["@OttoWinter"] +homeassistant_ns = cg.esphome_ns.namespace("homeassistant") diff --git a/esphome/components/homeassistant/binary_sensor/__init__.py b/esphome/components/homeassistant/binary_sensor/__init__.py index 88e2f2fcb..850f239d6 100644 --- a/esphome/components/homeassistant/binary_sensor/__init__.py +++ b/esphome/components/homeassistant/binary_sensor/__init__.py @@ -4,15 +4,17 @@ from esphome.components import binary_sensor from esphome.const import CONF_ENTITY_ID, CONF_ID from .. import homeassistant_ns -DEPENDENCIES = ['api'] -HomeassistantBinarySensor = homeassistant_ns.class_('HomeassistantBinarySensor', - binary_sensor.BinarySensor, - cg.Component) +DEPENDENCIES = ["api"] +HomeassistantBinarySensor = homeassistant_ns.class_( + "HomeassistantBinarySensor", binary_sensor.BinarySensor, cg.Component +) -CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(HomeassistantBinarySensor), - cv.Required(CONF_ENTITY_ID): cv.entity_id, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(HomeassistantBinarySensor), + cv.Required(CONF_ENTITY_ID): cv.entity_id, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/homeassistant/sensor/__init__.py b/esphome/components/homeassistant/sensor/__init__.py index a413518e0..9c19c7867 100644 --- a/esphome/components/homeassistant/sensor/__init__.py +++ b/esphome/components/homeassistant/sensor/__init__.py @@ -1,18 +1,29 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor -from esphome.const import CONF_ENTITY_ID, CONF_ID, ICON_EMPTY, UNIT_EMPTY, DEVICE_CLASS_EMPTY +from esphome.const import ( + CONF_ENTITY_ID, + CONF_ID, + ICON_EMPTY, + UNIT_EMPTY, + DEVICE_CLASS_EMPTY, +) from .. import homeassistant_ns -DEPENDENCIES = ['api'] +DEPENDENCIES = ["api"] -HomeassistantSensor = homeassistant_ns.class_('HomeassistantSensor', sensor.Sensor, - cg.Component) +HomeassistantSensor = homeassistant_ns.class_( + "HomeassistantSensor", sensor.Sensor, cg.Component +) -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_EMPTY, ICON_EMPTY, 1, DEVICE_CLASS_EMPTY).extend({ - cv.GenerateID(): cv.declare_id(HomeassistantSensor), - cv.Required(CONF_ENTITY_ID): cv.entity_id, -}) +CONFIG_SCHEMA = sensor.sensor_schema( + UNIT_EMPTY, ICON_EMPTY, 1, DEVICE_CLASS_EMPTY +).extend( + { + cv.GenerateID(): cv.declare_id(HomeassistantSensor), + cv.Required(CONF_ENTITY_ID): cv.entity_id, + } +) def to_code(config): diff --git a/esphome/components/homeassistant/text_sensor/__init__.py b/esphome/components/homeassistant/text_sensor/__init__.py index 2d06473f3..478bd1c3d 100644 --- a/esphome/components/homeassistant/text_sensor/__init__.py +++ b/esphome/components/homeassistant/text_sensor/__init__.py @@ -4,15 +4,18 @@ from esphome.components import text_sensor from esphome.const import CONF_ENTITY_ID, CONF_ID from .. import homeassistant_ns -DEPENDENCIES = ['api'] +DEPENDENCIES = ["api"] -HomeassistantTextSensor = homeassistant_ns.class_('HomeassistantTextSensor', - text_sensor.TextSensor, cg.Component) +HomeassistantTextSensor = homeassistant_ns.class_( + "HomeassistantTextSensor", text_sensor.TextSensor, cg.Component +) -CONFIG_SCHEMA = text_sensor.TEXT_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(HomeassistantTextSensor), - cv.Required(CONF_ENTITY_ID): cv.entity_id, -}) +CONFIG_SCHEMA = text_sensor.TEXT_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(HomeassistantTextSensor), + cv.Required(CONF_ENTITY_ID): cv.entity_id, + } +) def to_code(config): diff --git a/esphome/components/homeassistant/time/__init__.py b/esphome/components/homeassistant/time/__init__.py index fd40de68d..e99542130 100644 --- a/esphome/components/homeassistant/time/__init__.py +++ b/esphome/components/homeassistant/time/__init__.py @@ -4,17 +4,19 @@ import esphome.codegen as cg from esphome.const import CONF_ID from .. import homeassistant_ns -DEPENDENCIES = ['api'] +DEPENDENCIES = ["api"] -HomeassistantTime = homeassistant_ns.class_('HomeassistantTime', time_.RealTimeClock) +HomeassistantTime = homeassistant_ns.class_("HomeassistantTime", time_.RealTimeClock) -CONFIG_SCHEMA = time_.TIME_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(HomeassistantTime), -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = time_.TIME_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(HomeassistantTime), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) yield time_.register_time(var, config) yield cg.register_component(var, config) - cg.add_define('USE_HOMEASSISTANT_TIME') + cg.add_define("USE_HOMEASSISTANT_TIME") diff --git a/esphome/components/http_request/__init__.py b/esphome/components/http_request/__init__.py index f7ec3cdbb..0cac088f3 100644 --- a/esphome/components/http_request/__init__.py +++ b/esphome/components/http_request/__init__.py @@ -3,39 +3,54 @@ import urllib.parse as urlparse import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation -from esphome.const import CONF_ID, CONF_TIMEOUT, CONF_ESPHOME, CONF_METHOD, \ - CONF_ARDUINO_VERSION, ARDUINO_VERSION_ESP8266, CONF_URL +from esphome.const import ( + CONF_ID, + CONF_TIMEOUT, + CONF_ESPHOME, + CONF_METHOD, + CONF_ARDUINO_VERSION, + ARDUINO_VERSION_ESP8266, + CONF_URL, +) from esphome.core import CORE, Lambda from esphome.core_config import PLATFORMIO_ESP8266_LUT -DEPENDENCIES = ['network'] -AUTO_LOAD = ['json'] +DEPENDENCIES = ["network"] +AUTO_LOAD = ["json"] -http_request_ns = cg.esphome_ns.namespace('http_request') -HttpRequestComponent = http_request_ns.class_('HttpRequestComponent', cg.Component) -HttpRequestSendAction = http_request_ns.class_('HttpRequestSendAction', automation.Action) +http_request_ns = cg.esphome_ns.namespace("http_request") +HttpRequestComponent = http_request_ns.class_("HttpRequestComponent", cg.Component) +HttpRequestSendAction = http_request_ns.class_( + "HttpRequestSendAction", automation.Action +) -CONF_HEADERS = 'headers' -CONF_USERAGENT = 'useragent' -CONF_BODY = 'body' -CONF_JSON = 'json' -CONF_VERIFY_SSL = 'verify_ssl' +CONF_HEADERS = "headers" +CONF_USERAGENT = "useragent" +CONF_BODY = "body" +CONF_JSON = "json" +CONF_VERIFY_SSL = "verify_ssl" def validate_framework(config): if CORE.is_esp32: return config - version = 'RECOMMENDED' + version = "RECOMMENDED" if CONF_ARDUINO_VERSION in CORE.raw_config[CONF_ESPHOME]: version = CORE.raw_config[CONF_ESPHOME][CONF_ARDUINO_VERSION] - if version in ['LATEST', 'DEV']: + if version in ["LATEST", "DEV"]: return config - framework = PLATFORMIO_ESP8266_LUT[version] if version in PLATFORMIO_ESP8266_LUT else version - if framework < ARDUINO_VERSION_ESP8266['2.5.1']: - raise cv.Invalid('This component is not supported on arduino framework version below 2.5.1') + framework = ( + PLATFORMIO_ESP8266_LUT[version] + if version in PLATFORMIO_ESP8266_LUT + else version + ) + if framework < ARDUINO_VERSION_ESP8266["2.5.1"]: + raise cv.Invalid( + "This component is not supported on arduino framework version below 2.5.1" + ) return config @@ -44,34 +59,47 @@ def validate_url(value): try: parsed = list(urlparse.urlparse(value)) except Exception as err: - raise cv.Invalid('Invalid URL') from err + raise cv.Invalid("Invalid URL") from err if not parsed[0] or not parsed[1]: - raise cv.Invalid('URL must have a URL scheme and host') + raise cv.Invalid("URL must have a URL scheme and host") - if parsed[0] not in ['http', 'https']: - raise cv.Invalid('Scheme must be http or https') + if parsed[0] not in ["http", "https"]: + raise cv.Invalid("Scheme must be http or https") if not parsed[2]: - parsed[2] = '/' + parsed[2] = "/" return urlparse.urlunparse(parsed) def validate_secure_url(config): url_ = config[CONF_URL] - if config.get(CONF_VERIFY_SSL) and not isinstance(url_, Lambda) \ - and url_.lower().startswith('https:'): - raise cv.Invalid('Currently ESPHome doesn\'t support SSL verification. ' - 'Set \'verify_ssl: false\' to make insecure HTTPS requests.') + if ( + config.get(CONF_VERIFY_SSL) + and not isinstance(url_, Lambda) + and url_.lower().startswith("https:") + ): + raise cv.Invalid( + "Currently ESPHome doesn't support SSL verification. " + "Set 'verify_ssl: false' to make insecure HTTPS requests." + ) return config -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(HttpRequestComponent), - cv.Optional(CONF_USERAGENT, 'ESPHome'): cv.string, - cv.Optional(CONF_TIMEOUT, default='5s'): cv.positive_time_period_milliseconds, -}).add_extra(validate_framework).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(HttpRequestComponent), + cv.Optional(CONF_USERAGENT, "ESPHome"): cv.string, + cv.Optional( + CONF_TIMEOUT, default="5s" + ): cv.positive_time_period_milliseconds, + } + ) + .add_extra(validate_framework) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): @@ -81,41 +109,60 @@ def to_code(config): yield cg.register_component(var, config) -HTTP_REQUEST_ACTION_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.use_id(HttpRequestComponent), - cv.Required(CONF_URL): cv.templatable(validate_url), - cv.Optional(CONF_HEADERS): cv.All(cv.Schema({cv.string: cv.templatable(cv.string)})), - cv.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, -}).add_extra(validate_secure_url) +HTTP_REQUEST_ACTION_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.use_id(HttpRequestComponent), + cv.Required(CONF_URL): cv.templatable(validate_url), + cv.Optional(CONF_HEADERS): cv.All( + cv.Schema({cv.string: cv.templatable(cv.string)}) + ), + cv.Optional(CONF_VERIFY_SSL, default=True): cv.boolean, + } +).add_extra(validate_secure_url) HTTP_REQUEST_GET_ACTION_SCHEMA = automation.maybe_conf( - CONF_URL, HTTP_REQUEST_ACTION_SCHEMA.extend({ - cv.Optional(CONF_METHOD, default='GET'): cv.one_of('GET', upper=True), - }) + CONF_URL, + HTTP_REQUEST_ACTION_SCHEMA.extend( + { + cv.Optional(CONF_METHOD, default="GET"): cv.one_of("GET", upper=True), + } + ), ) HTTP_REQUEST_POST_ACTION_SCHEMA = automation.maybe_conf( - CONF_URL, HTTP_REQUEST_ACTION_SCHEMA.extend({ - cv.Optional(CONF_METHOD, default='POST'): cv.one_of('POST', upper=True), - cv.Exclusive(CONF_BODY, 'body'): cv.templatable(cv.string), - cv.Exclusive(CONF_JSON, 'body'): cv.Any( - cv.lambda_, cv.All(cv.Schema({cv.string: cv.templatable(cv.string_strict)})), - ), - }) -) -HTTP_REQUEST_SEND_ACTION_SCHEMA = HTTP_REQUEST_ACTION_SCHEMA.extend({ - cv.Required(CONF_METHOD): cv.one_of('GET', 'POST', 'PUT', 'DELETE', 'PATCH', upper=True), - cv.Exclusive(CONF_BODY, 'body'): cv.templatable(cv.string), - cv.Exclusive(CONF_JSON, 'body'): cv.Any( - cv.lambda_, cv.All(cv.Schema({cv.string: cv.templatable(cv.string_strict)})), + CONF_URL, + HTTP_REQUEST_ACTION_SCHEMA.extend( + { + cv.Optional(CONF_METHOD, default="POST"): cv.one_of("POST", upper=True), + cv.Exclusive(CONF_BODY, "body"): cv.templatable(cv.string), + cv.Exclusive(CONF_JSON, "body"): cv.Any( + cv.lambda_, + cv.All(cv.Schema({cv.string: cv.templatable(cv.string_strict)})), + ), + } ), -}) +) +HTTP_REQUEST_SEND_ACTION_SCHEMA = HTTP_REQUEST_ACTION_SCHEMA.extend( + { + cv.Required(CONF_METHOD): cv.one_of( + "GET", "POST", "PUT", "DELETE", "PATCH", upper=True + ), + cv.Exclusive(CONF_BODY, "body"): cv.templatable(cv.string), + cv.Exclusive(CONF_JSON, "body"): cv.Any( + cv.lambda_, + cv.All(cv.Schema({cv.string: cv.templatable(cv.string_strict)})), + ), + } +) -@automation.register_action('http_request.get', HttpRequestSendAction, - HTTP_REQUEST_GET_ACTION_SCHEMA) -@automation.register_action('http_request.post', HttpRequestSendAction, - HTTP_REQUEST_POST_ACTION_SCHEMA) -@automation.register_action('http_request.send', HttpRequestSendAction, - HTTP_REQUEST_SEND_ACTION_SCHEMA) +@automation.register_action( + "http_request.get", HttpRequestSendAction, HTTP_REQUEST_GET_ACTION_SCHEMA +) +@automation.register_action( + "http_request.post", HttpRequestSendAction, HTTP_REQUEST_POST_ACTION_SCHEMA +) +@automation.register_action( + "http_request.send", HttpRequestSendAction, HTTP_REQUEST_SEND_ACTION_SCHEMA +) def http_request_action_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) @@ -129,7 +176,7 @@ def http_request_action_to_code(config, action_id, template_arg, args): if CONF_JSON in config: json_ = config[CONF_JSON] if isinstance(json_, Lambda): - args_ = args + [(cg.JsonObjectRef, 'root')] + args_ = args + [(cg.JsonObjectRef, "root")] lambda_ = yield cg.process_lambda(json_, args_, return_type=cg.void) cg.add(var.set_json(lambda_)) else: @@ -137,7 +184,9 @@ def http_request_action_to_code(config, action_id, template_arg, args): template_ = yield cg.templatable(json_[key], args, cg.std_string) cg.add(var.add_json(key, template_)) for key in config.get(CONF_HEADERS, []): - template_ = yield cg.templatable(config[CONF_HEADERS][key], args, cg.const_char_ptr) + template_ = yield cg.templatable( + config[CONF_HEADERS][key], args, cg.const_char_ptr + ) cg.add(var.add_header(key, template_)) yield var diff --git a/esphome/components/htu21d/sensor.py b/esphome/components/htu21d/sensor.py index 358eb33d6..258681a5a 100644 --- a/esphome/components/htu21d/sensor.py +++ b/esphome/components/htu21d/sensor.py @@ -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, 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"] -htu21d_ns = cg.esphome_ns.namespace('htu21d') -HTU21DComponent = htu21d_ns.class_('HTU21DComponent', cg.PollingComponent, i2c.I2CDevice) +htu21d_ns = cg.esphome_ns.namespace("htu21d") +HTU21DComponent = htu21d_ns.class_( + "HTU21DComponent", cg.PollingComponent, i2c.I2CDevice +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(HTU21DComponent), - cv.Required(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, - DEVICE_CLASS_TEMPERATURE), - cv.Required(CONF_HUMIDITY): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 1, - DEVICE_CLASS_HUMIDITY), -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x40)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(HTU21DComponent), + cv.Required(CONF_TEMPERATURE): sensor.sensor_schema( + UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE + ), + cv.Required(CONF_HUMIDITY): sensor.sensor_schema( + UNIT_PERCENT, ICON_EMPTY, 1, DEVICE_CLASS_HUMIDITY + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x40)) +) def to_code(config): diff --git a/esphome/components/hx711/sensor.py b/esphome/components/hx711/sensor.py index ad060646d..191a7386e 100644 --- a/esphome/components/hx711/sensor.py +++ b/esphome/components/hx711/sensor.py @@ -2,27 +2,39 @@ 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_CLK_PIN, CONF_GAIN, CONF_ID, DEVICE_CLASS_EMPTY, ICON_SCALE, \ - UNIT_EMPTY +from esphome.const import ( + CONF_CLK_PIN, + CONF_GAIN, + CONF_ID, + DEVICE_CLASS_EMPTY, + ICON_SCALE, + UNIT_EMPTY, +) -hx711_ns = cg.esphome_ns.namespace('hx711') -HX711Sensor = hx711_ns.class_('HX711Sensor', sensor.Sensor, cg.PollingComponent) +hx711_ns = cg.esphome_ns.namespace("hx711") +HX711Sensor = hx711_ns.class_("HX711Sensor", sensor.Sensor, cg.PollingComponent) -CONF_DOUT_PIN = 'dout_pin' +CONF_DOUT_PIN = "dout_pin" -HX711Gain = hx711_ns.enum('HX711Gain') +HX711Gain = hx711_ns.enum("HX711Gain") GAINS = { 128: HX711Gain.HX711_GAIN_128, 32: HX711Gain.HX711_GAIN_32, 64: HX711Gain.HX711_GAIN_64, } -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_EMPTY, ICON_SCALE, 0, DEVICE_CLASS_EMPTY).extend({ - cv.GenerateID(): cv.declare_id(HX711Sensor), - cv.Required(CONF_DOUT_PIN): pins.gpio_input_pin_schema, - cv.Required(CONF_CLK_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_GAIN, default=128): cv.enum(GAINS, int=True), -}).extend(cv.polling_component_schema('60s')) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_EMPTY, ICON_SCALE, 0, DEVICE_CLASS_EMPTY) + .extend( + { + cv.GenerateID(): cv.declare_id(HX711Sensor), + cv.Required(CONF_DOUT_PIN): pins.gpio_input_pin_schema, + cv.Required(CONF_CLK_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_GAIN, default=128): cv.enum(GAINS, int=True), + } + ) + .extend(cv.polling_component_schema("60s")) +) def to_code(config): diff --git a/esphome/components/i2c/__init__.py b/esphome/components/i2c/__init__.py index 91c6a9719..144683590 100644 --- a/esphome/components/i2c/__init__.py +++ b/esphome/components/i2c/__init__.py @@ -1,24 +1,34 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins -from esphome.const import CONF_FREQUENCY, CONF_ID, CONF_SCAN, CONF_SCL, CONF_SDA, CONF_ADDRESS, \ - CONF_I2C_ID +from esphome.const import ( + CONF_FREQUENCY, + CONF_ID, + CONF_SCAN, + CONF_SCL, + CONF_SDA, + CONF_ADDRESS, + CONF_I2C_ID, +) from esphome.core import coroutine, coroutine_with_priority -CODEOWNERS = ['@esphome/core'] -i2c_ns = cg.esphome_ns.namespace('i2c') -I2CComponent = i2c_ns.class_('I2CComponent', cg.Component) -I2CDevice = i2c_ns.class_('I2CDevice') +CODEOWNERS = ["@esphome/core"] +i2c_ns = cg.esphome_ns.namespace("i2c") +I2CComponent = i2c_ns.class_("I2CComponent", cg.Component) +I2CDevice = i2c_ns.class_("I2CDevice") MULTI_CONF = True -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(I2CComponent), - cv.Optional(CONF_SDA, default='SDA'): pins.input_pin, - cv.Optional(CONF_SCL, default='SCL'): pins.input_pin, - cv.Optional(CONF_FREQUENCY, default='50kHz'): - cv.All(cv.frequency, cv.Range(min=0, min_included=False)), - cv.Optional(CONF_SCAN, default=True): cv.boolean, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(I2CComponent), + cv.Optional(CONF_SDA, default="SDA"): pins.input_pin, + cv.Optional(CONF_SCL, default="SCL"): pins.input_pin, + cv.Optional(CONF_FREQUENCY, default="50kHz"): cv.All( + cv.frequency, cv.Range(min=0, min_included=False) + ), + cv.Optional(CONF_SCAN, default=True): cv.boolean, + } +).extend(cv.COMPONENT_SCHEMA) @coroutine_with_priority(1.0) @@ -31,7 +41,7 @@ def to_code(config): cg.add(var.set_scl_pin(config[CONF_SCL])) cg.add(var.set_frequency(int(config[CONF_FREQUENCY]))) cg.add(var.set_scan(config[CONF_SCAN])) - cg.add_library('Wire', None) + cg.add_library("Wire", None) def i2c_device_schema(default_address): diff --git a/esphome/components/ili9341/display.py b/esphome/components/ili9341/display.py index 0a3e9e16c..8c1a28ea5 100644 --- a/esphome/components/ili9341/display.py +++ b/esphome/components/ili9341/display.py @@ -2,42 +2,55 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.components import display, spi -from esphome.const import CONF_DC_PIN, \ - CONF_ID, CONF_LAMBDA, CONF_MODEL, CONF_PAGES, CONF_RESET_PIN +from esphome.const import ( + CONF_DC_PIN, + CONF_ID, + CONF_LAMBDA, + CONF_MODEL, + CONF_PAGES, + CONF_RESET_PIN, +) -DEPENDENCIES = ['spi'] +DEPENDENCIES = ["spi"] -CONF_LED_PIN = 'led_pin' +CONF_LED_PIN = "led_pin" -ili9341_ns = cg.esphome_ns.namespace('ili9341') -ili9341 = ili9341_ns.class_('ILI9341Display', cg.PollingComponent, spi.SPIDevice, - display.DisplayBuffer) -ILI9341M5Stack = ili9341_ns.class_('ILI9341M5Stack', ili9341) -ILI9341TFT24 = ili9341_ns.class_('ILI9341TFT24', ili9341) +ili9341_ns = cg.esphome_ns.namespace("ili9341") +ili9341 = ili9341_ns.class_( + "ILI9341Display", cg.PollingComponent, spi.SPIDevice, display.DisplayBuffer +) +ILI9341M5Stack = ili9341_ns.class_("ILI9341M5Stack", ili9341) +ILI9341TFT24 = ili9341_ns.class_("ILI9341TFT24", ili9341) -ILI9341Model = ili9341_ns.enum('ILI9341Model') +ILI9341Model = ili9341_ns.enum("ILI9341Model") MODELS = { - 'M5STACK': ILI9341Model.M5STACK, - 'TFT_2.4': ILI9341Model.TFT_24, + "M5STACK": ILI9341Model.M5STACK, + "TFT_2.4": ILI9341Model.TFT_24, } ILI9341_MODEL = cv.enum(MODELS, upper=True, space="_") -CONFIG_SCHEMA = cv.All(display.FULL_DISPLAY_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(ili9341), - cv.Required(CONF_MODEL): ILI9341_MODEL, - cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_LED_PIN): pins.gpio_output_pin_schema, -}).extend(cv.polling_component_schema('1s')).extend(spi.spi_device_schema()), - cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) +CONFIG_SCHEMA = cv.All( + display.FULL_DISPLAY_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(ili9341), + cv.Required(CONF_MODEL): ILI9341_MODEL, + cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_LED_PIN): pins.gpio_output_pin_schema, + } + ) + .extend(cv.polling_component_schema("1s")) + .extend(spi.spi_device_schema()), + cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), +) def to_code(config): - if config[CONF_MODEL] == 'M5STACK': + if config[CONF_MODEL] == "M5STACK": lcd_type = ILI9341M5Stack - if config[CONF_MODEL] == 'TFT_2.4': + if config[CONF_MODEL] == "TFT_2.4": lcd_type = ILI9341TFT24 rhs = lcd_type.new() var = cg.Pvariable(config[CONF_ID], rhs) @@ -50,8 +63,9 @@ def to_code(config): cg.add(var.set_dc_pin(dc)) if CONF_LAMBDA in config: - lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], [(display.DisplayBufferRef, 'it')], - return_type=cg.void) + lambda_ = yield cg.process_lambda( + config[CONF_LAMBDA], [(display.DisplayBufferRef, "it")], return_type=cg.void + ) cg.add(var.set_writer(lambda_)) if CONF_RESET_PIN in config: reset = yield cg.gpio_pin_expression(config[CONF_RESET_PIN]) diff --git a/esphome/components/image/__init__.py b/esphome/components/image/__init__.py index 3558d9660..b62977969 100644 --- a/esphome/components/image/__init__.py +++ b/esphome/components/image/__init__.py @@ -9,28 +9,32 @@ from esphome.core import CORE, HexInt _LOGGER = logging.getLogger(__name__) -DEPENDENCIES = ['display'] +DEPENDENCIES = ["display"] MULTI_CONF = True -ImageType = display.display_ns.enum('ImageType') +ImageType = display.display_ns.enum("ImageType") IMAGE_TYPE = { - 'BINARY': ImageType.IMAGE_TYPE_BINARY, - 'GRAYSCALE': ImageType.IMAGE_TYPE_GRAYSCALE, - 'RGB24': ImageType.IMAGE_TYPE_RGB24, + "BINARY": ImageType.IMAGE_TYPE_BINARY, + "GRAYSCALE": ImageType.IMAGE_TYPE_GRAYSCALE, + "RGB24": ImageType.IMAGE_TYPE_RGB24, } -Image_ = display.display_ns.class_('Image') +Image_ = display.display_ns.class_("Image") -CONF_RAW_DATA_ID = 'raw_data_id' +CONF_RAW_DATA_ID = "raw_data_id" -IMAGE_SCHEMA = cv.Schema({ - cv.Required(CONF_ID): cv.declare_id(Image_), - cv.Required(CONF_FILE): cv.file_, - cv.Optional(CONF_RESIZE): cv.dimensions, - cv.Optional(CONF_TYPE, default='BINARY'): cv.enum(IMAGE_TYPE, upper=True), - cv.Optional(CONF_DITHER, default='NONE'): cv.one_of("NONE", "FLOYDSTEINBERG", upper=True), - cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8), -}) +IMAGE_SCHEMA = cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(Image_), + cv.Required(CONF_FILE): cv.file_, + cv.Optional(CONF_RESIZE): cv.dimensions, + cv.Optional(CONF_TYPE, default="BINARY"): cv.enum(IMAGE_TYPE, upper=True), + cv.Optional(CONF_DITHER, default="NONE"): cv.one_of( + "NONE", "FLOYDSTEINBERG", upper=True + ), + cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8), + } +) CONFIG_SCHEMA = cv.All(font.validate_pillow_installed, IMAGE_SCHEMA) @@ -51,12 +55,14 @@ 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." + ) - dither = Image.NONE if config[CONF_DITHER] == 'NONE' else Image.FLOYDSTEINBERG - if config[CONF_TYPE] == 'GRAYSCALE': - image = image.convert('L', dither=dither) + dither = Image.NONE if config[CONF_DITHER] == "NONE" else Image.FLOYDSTEINBERG + if config[CONF_TYPE] == "GRAYSCALE": + image = image.convert("L", dither=dither) pixels = list(image.getdata()) data = [0 for _ in range(height * width)] pos = 0 @@ -64,8 +70,8 @@ def to_code(config): data[pos] = pix pos += 1 - elif config[CONF_TYPE] == 'RGB24': - image = image.convert('RGB') + elif config[CONF_TYPE] == "RGB24": + image = image.convert("RGB") pixels = list(image.getdata()) data = [0 for _ in range(height * width * 3)] pos = 0 @@ -77,8 +83,8 @@ def to_code(config): data[pos] = pix[2] pos += 1 - elif config[CONF_TYPE] == 'BINARY': - image = image.convert('1', dither=dither) + elif config[CONF_TYPE] == "BINARY": + image = image.convert("1", dither=dither) width8 = ((width + 7) // 8) * 8 data = [0 for _ in range(height * width8 // 8)] for y in range(height): @@ -90,5 +96,6 @@ 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, - IMAGE_TYPE[config[CONF_TYPE]]) + cg.new_Pvariable( + config[CONF_ID], prog_arr, width, height, IMAGE_TYPE[config[CONF_TYPE]] + ) diff --git a/esphome/components/ina219/sensor.py b/esphome/components/ina219/sensor.py index 6229dad0d..d122754b8 100644 --- a/esphome/components/ina219/sensor.py +++ b/esphome/components/ina219/sensor.py @@ -1,29 +1,61 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, sensor -from esphome.const import CONF_BUS_VOLTAGE, CONF_CURRENT, CONF_ID, CONF_MAX_CURRENT, \ - CONF_MAX_VOLTAGE, CONF_POWER, CONF_SHUNT_RESISTANCE, CONF_SHUNT_VOLTAGE, DEVICE_CLASS_CURRENT, \ - DEVICE_CLASS_POWER, DEVICE_CLASS_VOLTAGE, ICON_EMPTY, UNIT_VOLT, UNIT_AMPERE, UNIT_WATT +from esphome.const import ( + CONF_BUS_VOLTAGE, + CONF_CURRENT, + CONF_ID, + CONF_MAX_CURRENT, + CONF_MAX_VOLTAGE, + CONF_POWER, + CONF_SHUNT_RESISTANCE, + CONF_SHUNT_VOLTAGE, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_POWER, + DEVICE_CLASS_VOLTAGE, + ICON_EMPTY, + UNIT_VOLT, + UNIT_AMPERE, + UNIT_WATT, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -ina219_ns = cg.esphome_ns.namespace('ina219') -INA219Component = ina219_ns.class_('INA219Component', cg.PollingComponent, i2c.I2CDevice) +ina219_ns = cg.esphome_ns.namespace("ina219") +INA219Component = ina219_ns.class_( + "INA219Component", cg.PollingComponent, i2c.I2CDevice +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(INA219Component), - cv.Optional(CONF_BUS_VOLTAGE): sensor.sensor_schema(UNIT_VOLT, ICON_EMPTY, 2, - DEVICE_CLASS_VOLTAGE), - cv.Optional(CONF_SHUNT_VOLTAGE): sensor.sensor_schema(UNIT_VOLT, ICON_EMPTY, 2, - DEVICE_CLASS_VOLTAGE), - cv.Optional(CONF_CURRENT): sensor.sensor_schema(UNIT_AMPERE, ICON_EMPTY, 3, - DEVICE_CLASS_CURRENT), - cv.Optional(CONF_POWER): sensor.sensor_schema(UNIT_WATT, ICON_EMPTY, 2, DEVICE_CLASS_POWER), - cv.Optional(CONF_SHUNT_RESISTANCE, default=0.1): cv.All(cv.resistance, - cv.Range(min=0.0, max=32.0)), - cv.Optional(CONF_MAX_VOLTAGE, default=32.0): cv.All(cv.voltage, cv.Range(min=0.0, max=32.0)), - cv.Optional(CONF_MAX_CURRENT, default=3.2): cv.All(cv.current, cv.Range(min=0.0)), -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x40)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(INA219Component), + cv.Optional(CONF_BUS_VOLTAGE): sensor.sensor_schema( + UNIT_VOLT, ICON_EMPTY, 2, DEVICE_CLASS_VOLTAGE + ), + cv.Optional(CONF_SHUNT_VOLTAGE): sensor.sensor_schema( + UNIT_VOLT, ICON_EMPTY, 2, DEVICE_CLASS_VOLTAGE + ), + cv.Optional(CONF_CURRENT): sensor.sensor_schema( + UNIT_AMPERE, ICON_EMPTY, 3, DEVICE_CLASS_CURRENT + ), + cv.Optional(CONF_POWER): sensor.sensor_schema( + UNIT_WATT, ICON_EMPTY, 2, DEVICE_CLASS_POWER + ), + cv.Optional(CONF_SHUNT_RESISTANCE, default=0.1): cv.All( + cv.resistance, cv.Range(min=0.0, max=32.0) + ), + cv.Optional(CONF_MAX_VOLTAGE, default=32.0): cv.All( + cv.voltage, cv.Range(min=0.0, max=32.0) + ), + cv.Optional(CONF_MAX_CURRENT, default=3.2): cv.All( + cv.current, cv.Range(min=0.0) + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x40)) +) def to_code(config): diff --git a/esphome/components/ina226/sensor.py b/esphome/components/ina226/sensor.py index b36a74755..2b7346fbe 100644 --- a/esphome/components/ina226/sensor.py +++ b/esphome/components/ina226/sensor.py @@ -1,27 +1,57 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, sensor -from esphome.const import CONF_BUS_VOLTAGE, CONF_CURRENT, CONF_ID, CONF_MAX_CURRENT, CONF_POWER, \ - CONF_SHUNT_RESISTANCE, CONF_SHUNT_VOLTAGE, DEVICE_CLASS_VOLTAGE, DEVICE_CLASS_CURRENT, \ - DEVICE_CLASS_POWER, ICON_EMPTY, UNIT_VOLT, UNIT_AMPERE, UNIT_WATT +from esphome.const import ( + CONF_BUS_VOLTAGE, + CONF_CURRENT, + CONF_ID, + CONF_MAX_CURRENT, + CONF_POWER, + CONF_SHUNT_RESISTANCE, + CONF_SHUNT_VOLTAGE, + DEVICE_CLASS_VOLTAGE, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_POWER, + ICON_EMPTY, + UNIT_VOLT, + UNIT_AMPERE, + UNIT_WATT, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -ina226_ns = cg.esphome_ns.namespace('ina226') -INA226Component = ina226_ns.class_('INA226Component', cg.PollingComponent, i2c.I2CDevice) +ina226_ns = cg.esphome_ns.namespace("ina226") +INA226Component = ina226_ns.class_( + "INA226Component", cg.PollingComponent, i2c.I2CDevice +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(INA226Component), - cv.Optional(CONF_BUS_VOLTAGE): sensor.sensor_schema(UNIT_VOLT, ICON_EMPTY, 2, - DEVICE_CLASS_VOLTAGE), - cv.Optional(CONF_SHUNT_VOLTAGE): sensor.sensor_schema(UNIT_VOLT, ICON_EMPTY, 2, - DEVICE_CLASS_VOLTAGE), - cv.Optional(CONF_CURRENT): sensor.sensor_schema(UNIT_AMPERE, ICON_EMPTY, 3, - DEVICE_CLASS_CURRENT), - cv.Optional(CONF_POWER): sensor.sensor_schema(UNIT_WATT, ICON_EMPTY, 2, DEVICE_CLASS_POWER), - cv.Optional(CONF_SHUNT_RESISTANCE, default=0.1): cv.All(cv.resistance, cv.Range(min=0.0)), - cv.Optional(CONF_MAX_CURRENT, default=3.2): cv.All(cv.current, cv.Range(min=0.0)), -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x40)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(INA226Component), + cv.Optional(CONF_BUS_VOLTAGE): sensor.sensor_schema( + UNIT_VOLT, ICON_EMPTY, 2, DEVICE_CLASS_VOLTAGE + ), + cv.Optional(CONF_SHUNT_VOLTAGE): sensor.sensor_schema( + UNIT_VOLT, ICON_EMPTY, 2, DEVICE_CLASS_VOLTAGE + ), + cv.Optional(CONF_CURRENT): sensor.sensor_schema( + UNIT_AMPERE, ICON_EMPTY, 3, DEVICE_CLASS_CURRENT + ), + cv.Optional(CONF_POWER): sensor.sensor_schema( + UNIT_WATT, ICON_EMPTY, 2, DEVICE_CLASS_POWER + ), + cv.Optional(CONF_SHUNT_RESISTANCE, default=0.1): cv.All( + cv.resistance, cv.Range(min=0.0) + ), + cv.Optional(CONF_MAX_CURRENT, default=3.2): cv.All( + cv.current, cv.Range(min=0.0) + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x40)) +) def to_code(config): diff --git a/esphome/components/ina3221/sensor.py b/esphome/components/ina3221/sensor.py index e71f9f5d9..c055e149b 100644 --- a/esphome/components/ina3221/sensor.py +++ b/esphome/components/ina3221/sensor.py @@ -1,37 +1,65 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, sensor -from esphome.const import CONF_BUS_VOLTAGE, CONF_CURRENT, CONF_ID, CONF_POWER, \ - CONF_SHUNT_RESISTANCE, CONF_SHUNT_VOLTAGE, DEVICE_CLASS_VOLTAGE, DEVICE_CLASS_CURRENT, \ - DEVICE_CLASS_POWER, ICON_EMPTY, UNIT_VOLT, UNIT_AMPERE, UNIT_WATT +from esphome.const import ( + CONF_BUS_VOLTAGE, + CONF_CURRENT, + CONF_ID, + CONF_POWER, + CONF_SHUNT_RESISTANCE, + CONF_SHUNT_VOLTAGE, + DEVICE_CLASS_VOLTAGE, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_POWER, + ICON_EMPTY, + UNIT_VOLT, + UNIT_AMPERE, + UNIT_WATT, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -CONF_CHANNEL_1 = 'channel_1' -CONF_CHANNEL_2 = 'channel_2' -CONF_CHANNEL_3 = 'channel_3' +CONF_CHANNEL_1 = "channel_1" +CONF_CHANNEL_2 = "channel_2" +CONF_CHANNEL_3 = "channel_3" -ina3221_ns = cg.esphome_ns.namespace('ina3221') -INA3221Component = ina3221_ns.class_('INA3221Component', cg.PollingComponent, i2c.I2CDevice) +ina3221_ns = cg.esphome_ns.namespace("ina3221") +INA3221Component = ina3221_ns.class_( + "INA3221Component", cg.PollingComponent, i2c.I2CDevice +) -INA3221_CHANNEL_SCHEMA = cv.Schema({ - cv.Optional(CONF_BUS_VOLTAGE): sensor.sensor_schema(UNIT_VOLT, ICON_EMPTY, 2, - DEVICE_CLASS_VOLTAGE), - cv.Optional(CONF_SHUNT_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_SHUNT_RESISTANCE, default=0.1): cv.All(cv.resistance, - cv.Range(min=0.0, max=32.0)), -}) +INA3221_CHANNEL_SCHEMA = cv.Schema( + { + cv.Optional(CONF_BUS_VOLTAGE): sensor.sensor_schema( + UNIT_VOLT, ICON_EMPTY, 2, DEVICE_CLASS_VOLTAGE + ), + cv.Optional(CONF_SHUNT_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_SHUNT_RESISTANCE, default=0.1): cv.All( + cv.resistance, cv.Range(min=0.0, max=32.0) + ), + } +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(INA3221Component), - cv.Optional(CONF_CHANNEL_1): INA3221_CHANNEL_SCHEMA, - cv.Optional(CONF_CHANNEL_2): INA3221_CHANNEL_SCHEMA, - cv.Optional(CONF_CHANNEL_3): INA3221_CHANNEL_SCHEMA, -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x40)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(INA3221Component), + cv.Optional(CONF_CHANNEL_1): INA3221_CHANNEL_SCHEMA, + cv.Optional(CONF_CHANNEL_2): INA3221_CHANNEL_SCHEMA, + cv.Optional(CONF_CHANNEL_3): INA3221_CHANNEL_SCHEMA, + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x40)) +) def to_code(config): diff --git a/esphome/components/inkbird_ibsth1_mini/sensor.py b/esphome/components/inkbird_ibsth1_mini/sensor.py index 57a16f288..c67acb859 100644 --- a/esphome/components/inkbird_ibsth1_mini/sensor.py +++ b/esphome/components/inkbird_ibsth1_mini/sensor.py @@ -1,27 +1,47 @@ 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_HUMIDITY, CONF_MAC_ADDRESS, CONF_TEMPERATURE, \ - DEVICE_CLASS_BATTERY, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, \ - UNIT_CELSIUS, UNIT_PERCENT, CONF_ID +from esphome.const import ( + CONF_BATTERY_LEVEL, + CONF_HUMIDITY, + CONF_MAC_ADDRESS, + CONF_TEMPERATURE, + DEVICE_CLASS_BATTERY, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_TEMPERATURE, + ICON_EMPTY, + UNIT_CELSIUS, + UNIT_PERCENT, + CONF_ID, +) -CODEOWNERS = ['@fkirill'] -DEPENDENCIES = ['esp32_ble_tracker'] +CODEOWNERS = ["@fkirill"] +DEPENDENCIES = ["esp32_ble_tracker"] -inkbird_ibsth1_mini_ns = cg.esphome_ns.namespace('inkbird_ibsth1_mini') +inkbird_ibsth1_mini_ns = cg.esphome_ns.namespace("inkbird_ibsth1_mini") InkbirdUBSTH1_MINI = inkbird_ibsth1_mini_ns.class_( - 'InkbirdIBSTH1_MINI', esp32_ble_tracker.ESPBTDeviceListener, cg.Component) + "InkbirdIBSTH1_MINI", esp32_ble_tracker.ESPBTDeviceListener, cg.Component +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(InkbirdUBSTH1_MINI), - 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, 1, - DEVICE_CLASS_HUMIDITY), - cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 0, - DEVICE_CLASS_BATTERY), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(InkbirdUBSTH1_MINI), + 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, 1, DEVICE_CLASS_HUMIDITY + ), + cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema( + UNIT_PERCENT, ICON_EMPTY, 0, DEVICE_CLASS_BATTERY + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/inkplate6/__init__.py b/esphome/components/inkplate6/__init__.py index ba7653988..b1de57df8 100644 --- a/esphome/components/inkplate6/__init__.py +++ b/esphome/components/inkplate6/__init__.py @@ -1 +1 @@ -CODEOWNERS = ['@jesserockz'] +CODEOWNERS = ["@jesserockz"] diff --git a/esphome/components/inkplate6/display.py b/esphome/components/inkplate6/display.py index 4f35901bd..cd2b5ac51 100644 --- a/esphome/components/inkplate6/display.py +++ b/esphome/components/inkplate6/display.py @@ -2,67 +2,94 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.components import display, i2c -from esphome.const import CONF_FULL_UPDATE_EVERY, CONF_ID, CONF_LAMBDA, CONF_PAGES, \ - CONF_WAKEUP_PIN, ESP_PLATFORM_ESP32 +from esphome.const import ( + CONF_FULL_UPDATE_EVERY, + CONF_ID, + CONF_LAMBDA, + CONF_PAGES, + CONF_WAKEUP_PIN, + ESP_PLATFORM_ESP32, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] ESP_PLATFORMS = [ESP_PLATFORM_ESP32] -CONF_DISPLAY_DATA_0_PIN = 'display_data_0_pin' -CONF_DISPLAY_DATA_1_PIN = 'display_data_1_pin' -CONF_DISPLAY_DATA_2_PIN = 'display_data_2_pin' -CONF_DISPLAY_DATA_3_PIN = 'display_data_3_pin' -CONF_DISPLAY_DATA_4_PIN = 'display_data_4_pin' -CONF_DISPLAY_DATA_5_PIN = 'display_data_5_pin' -CONF_DISPLAY_DATA_6_PIN = 'display_data_6_pin' -CONF_DISPLAY_DATA_7_PIN = 'display_data_7_pin' +CONF_DISPLAY_DATA_0_PIN = "display_data_0_pin" +CONF_DISPLAY_DATA_1_PIN = "display_data_1_pin" +CONF_DISPLAY_DATA_2_PIN = "display_data_2_pin" +CONF_DISPLAY_DATA_3_PIN = "display_data_3_pin" +CONF_DISPLAY_DATA_4_PIN = "display_data_4_pin" +CONF_DISPLAY_DATA_5_PIN = "display_data_5_pin" +CONF_DISPLAY_DATA_6_PIN = "display_data_6_pin" +CONF_DISPLAY_DATA_7_PIN = "display_data_7_pin" -CONF_CL_PIN = 'cl_pin' -CONF_CKV_PIN = 'ckv_pin' -CONF_GREYSCALE = 'greyscale' -CONF_GMOD_PIN = 'gmod_pin' -CONF_GPIO0_ENABLE_PIN = 'gpio0_enable_pin' -CONF_LE_PIN = 'le_pin' -CONF_OE_PIN = 'oe_pin' -CONF_PARTIAL_UPDATING = 'partial_updating' -CONF_POWERUP_PIN = 'powerup_pin' -CONF_SPH_PIN = 'sph_pin' -CONF_SPV_PIN = 'spv_pin' -CONF_VCOM_PIN = 'vcom_pin' +CONF_CL_PIN = "cl_pin" +CONF_CKV_PIN = "ckv_pin" +CONF_GREYSCALE = "greyscale" +CONF_GMOD_PIN = "gmod_pin" +CONF_GPIO0_ENABLE_PIN = "gpio0_enable_pin" +CONF_LE_PIN = "le_pin" +CONF_OE_PIN = "oe_pin" +CONF_PARTIAL_UPDATING = "partial_updating" +CONF_POWERUP_PIN = "powerup_pin" +CONF_SPH_PIN = "sph_pin" +CONF_SPV_PIN = "spv_pin" +CONF_VCOM_PIN = "vcom_pin" -inkplate6_ns = cg.esphome_ns.namespace('inkplate6') -Inkplate6 = inkplate6_ns.class_('Inkplate6', cg.PollingComponent, i2c.I2CDevice, - display.DisplayBuffer) +inkplate6_ns = cg.esphome_ns.namespace("inkplate6") +Inkplate6 = inkplate6_ns.class_( + "Inkplate6", cg.PollingComponent, i2c.I2CDevice, display.DisplayBuffer +) -CONFIG_SCHEMA = cv.All(display.FULL_DISPLAY_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(Inkplate6), - cv.Optional(CONF_GREYSCALE, default=False): cv.boolean, - cv.Optional(CONF_PARTIAL_UPDATING, default=True): cv.boolean, - cv.Optional(CONF_FULL_UPDATE_EVERY, default=10): cv.uint32_t, - # Control pins - cv.Required(CONF_CKV_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_GMOD_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_GPIO0_ENABLE_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_OE_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_POWERUP_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_SPH_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_SPV_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_VCOM_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_WAKEUP_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_CL_PIN, default=0): pins.internal_gpio_output_pin_schema, - cv.Optional(CONF_LE_PIN, default=2): pins.internal_gpio_output_pin_schema, - # Data pins - cv.Optional(CONF_DISPLAY_DATA_0_PIN, default=4): pins.internal_gpio_output_pin_schema, - cv.Optional(CONF_DISPLAY_DATA_1_PIN, default=5): pins.internal_gpio_output_pin_schema, - cv.Optional(CONF_DISPLAY_DATA_2_PIN, default=18): pins.internal_gpio_output_pin_schema, - cv.Optional(CONF_DISPLAY_DATA_3_PIN, default=19): pins.internal_gpio_output_pin_schema, - cv.Optional(CONF_DISPLAY_DATA_4_PIN, default=23): pins.internal_gpio_output_pin_schema, - cv.Optional(CONF_DISPLAY_DATA_5_PIN, default=25): pins.internal_gpio_output_pin_schema, - cv.Optional(CONF_DISPLAY_DATA_6_PIN, default=26): pins.internal_gpio_output_pin_schema, - cv.Optional(CONF_DISPLAY_DATA_7_PIN, default=27): pins.internal_gpio_output_pin_schema, -}).extend(cv.polling_component_schema('5s').extend(i2c.i2c_device_schema(0x48))), - cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) +CONFIG_SCHEMA = cv.All( + display.FULL_DISPLAY_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(Inkplate6), + cv.Optional(CONF_GREYSCALE, default=False): cv.boolean, + cv.Optional(CONF_PARTIAL_UPDATING, default=True): cv.boolean, + cv.Optional(CONF_FULL_UPDATE_EVERY, default=10): cv.uint32_t, + # Control pins + cv.Required(CONF_CKV_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_GMOD_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_GPIO0_ENABLE_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_OE_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_POWERUP_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_SPH_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_SPV_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_VCOM_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_WAKEUP_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_CL_PIN, default=0): pins.internal_gpio_output_pin_schema, + cv.Optional(CONF_LE_PIN, default=2): pins.internal_gpio_output_pin_schema, + # Data pins + cv.Optional( + CONF_DISPLAY_DATA_0_PIN, default=4 + ): pins.internal_gpio_output_pin_schema, + cv.Optional( + CONF_DISPLAY_DATA_1_PIN, default=5 + ): pins.internal_gpio_output_pin_schema, + cv.Optional( + CONF_DISPLAY_DATA_2_PIN, default=18 + ): pins.internal_gpio_output_pin_schema, + cv.Optional( + CONF_DISPLAY_DATA_3_PIN, default=19 + ): pins.internal_gpio_output_pin_schema, + cv.Optional( + CONF_DISPLAY_DATA_4_PIN, default=23 + ): pins.internal_gpio_output_pin_schema, + cv.Optional( + CONF_DISPLAY_DATA_5_PIN, default=25 + ): pins.internal_gpio_output_pin_schema, + cv.Optional( + CONF_DISPLAY_DATA_6_PIN, default=26 + ): pins.internal_gpio_output_pin_schema, + cv.Optional( + CONF_DISPLAY_DATA_7_PIN, default=27 + ): pins.internal_gpio_output_pin_schema, + } + ).extend(cv.polling_component_schema("5s").extend(i2c.i2c_device_schema(0x48))), + cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), +) def to_code(config): @@ -73,8 +100,9 @@ def to_code(config): yield i2c.register_i2c_device(var, config) if CONF_LAMBDA in config: - lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], [(display.DisplayBufferRef, 'it')], - return_type=cg.void) + lambda_ = yield cg.process_lambda( + config[CONF_LAMBDA], [(display.DisplayBufferRef, "it")], return_type=cg.void + ) cg.add(var.set_writer(lambda_)) cg.add(var.set_greyscale(config[CONF_GREYSCALE])) @@ -138,4 +166,4 @@ def to_code(config): display_data_7 = yield cg.gpio_pin_expression(config[CONF_DISPLAY_DATA_7_PIN]) cg.add(var.set_display_data_7_pin(display_data_7)) - cg.add_build_flag('-DBOARD_HAS_PSRAM') + cg.add_build_flag("-DBOARD_HAS_PSRAM") diff --git a/esphome/components/integration/__init__.py b/esphome/components/integration/__init__.py index 6f14e1003..71a87b6ae 100644 --- a/esphome/components/integration/__init__.py +++ b/esphome/components/integration/__init__.py @@ -1 +1 @@ -CODEOWNERS = ['@OttoWinter'] +CODEOWNERS = ["@OttoWinter"] diff --git a/esphome/components/integration/sensor.py b/esphome/components/integration/sensor.py index a354ab743..81b588610 100644 --- a/esphome/components/integration/sensor.py +++ b/esphome/components/integration/sensor.py @@ -4,36 +4,41 @@ from esphome import automation from esphome.components import sensor from esphome.const import CONF_ID, CONF_SENSOR, CONF_RESTORE -integration_ns = cg.esphome_ns.namespace('integration') -IntegrationSensor = integration_ns.class_('IntegrationSensor', sensor.Sensor, cg.Component) -ResetAction = integration_ns.class_('ResetAction', automation.Action) +integration_ns = cg.esphome_ns.namespace("integration") +IntegrationSensor = integration_ns.class_( + "IntegrationSensor", sensor.Sensor, cg.Component +) +ResetAction = integration_ns.class_("ResetAction", automation.Action) -IntegrationSensorTime = integration_ns.enum('IntegrationSensorTime') +IntegrationSensorTime = integration_ns.enum("IntegrationSensorTime") INTEGRATION_TIMES = { - 'ms': IntegrationSensorTime.INTEGRATION_SENSOR_TIME_MILLISECOND, - 's': IntegrationSensorTime.INTEGRATION_SENSOR_TIME_SECOND, - 'min': IntegrationSensorTime.INTEGRATION_SENSOR_TIME_MINUTE, - 'h': IntegrationSensorTime.INTEGRATION_SENSOR_TIME_HOUR, - 'd': IntegrationSensorTime.INTEGRATION_SENSOR_TIME_DAY, + "ms": IntegrationSensorTime.INTEGRATION_SENSOR_TIME_MILLISECOND, + "s": IntegrationSensorTime.INTEGRATION_SENSOR_TIME_SECOND, + "min": IntegrationSensorTime.INTEGRATION_SENSOR_TIME_MINUTE, + "h": IntegrationSensorTime.INTEGRATION_SENSOR_TIME_HOUR, + "d": IntegrationSensorTime.INTEGRATION_SENSOR_TIME_DAY, } -IntegrationMethod = integration_ns.enum('IntegrationMethod') +IntegrationMethod = integration_ns.enum("IntegrationMethod") INTEGRATION_METHODS = { - 'trapezoid': IntegrationMethod.INTEGRATION_METHOD_TRAPEZOID, - 'left': IntegrationMethod.INTEGRATION_METHOD_LEFT, - 'right': IntegrationMethod.INTEGRATION_METHOD_RIGHT, + "trapezoid": IntegrationMethod.INTEGRATION_METHOD_TRAPEZOID, + "left": IntegrationMethod.INTEGRATION_METHOD_LEFT, + "right": IntegrationMethod.INTEGRATION_METHOD_RIGHT, } -CONF_TIME_UNIT = 'time_unit' -CONF_INTEGRATION_METHOD = 'integration_method' +CONF_TIME_UNIT = "time_unit" +CONF_INTEGRATION_METHOD = "integration_method" -CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(IntegrationSensor), - cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor), - cv.Required(CONF_TIME_UNIT): cv.enum(INTEGRATION_TIMES, lower=True), - cv.Optional(CONF_INTEGRATION_METHOD, default='trapezoid'): - cv.enum(INTEGRATION_METHODS, lower=True), - cv.Optional(CONF_RESTORE, default=False): cv.boolean, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(IntegrationSensor), + cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor), + cv.Required(CONF_TIME_UNIT): cv.enum(INTEGRATION_TIMES, lower=True), + cv.Optional(CONF_INTEGRATION_METHOD, default="trapezoid"): cv.enum( + INTEGRATION_METHODS, lower=True + ), + cv.Optional(CONF_RESTORE, default=False): cv.boolean, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): @@ -49,9 +54,15 @@ def to_code(config): cg.add(var.set_restore(config[CONF_RESTORE])) -@automation.register_action('sensor.integration.reset', ResetAction, automation.maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(IntegrationSensor), -})) +@automation.register_action( + "sensor.integration.reset", + ResetAction, + automation.maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(IntegrationSensor), + } + ), +) def sensor_integration_reset_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) diff --git a/esphome/components/interval/__init__.py b/esphome/components/interval/__init__.py index be37526ad..7d04a9e9a 100644 --- a/esphome/components/interval/__init__.py +++ b/esphome/components/interval/__init__.py @@ -3,15 +3,20 @@ import esphome.config_validation as cv from esphome import automation from esphome.const import CONF_ID, CONF_INTERVAL -CODEOWNERS = ['@esphome/core'] -interval_ns = cg.esphome_ns.namespace('interval') -IntervalTrigger = interval_ns.class_('IntervalTrigger', automation.Trigger.template(), - cg.PollingComponent) +CODEOWNERS = ["@esphome/core"] +interval_ns = cg.esphome_ns.namespace("interval") +IntervalTrigger = interval_ns.class_( + "IntervalTrigger", automation.Trigger.template(), cg.PollingComponent +) -CONFIG_SCHEMA = automation.validate_automation(cv.Schema({ - cv.GenerateID(): cv.declare_id(IntervalTrigger), - cv.Required(CONF_INTERVAL): cv.positive_time_period_milliseconds, -}).extend(cv.COMPONENT_SCHEMA)) +CONFIG_SCHEMA = automation.validate_automation( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(IntervalTrigger), + cv.Required(CONF_INTERVAL): cv.positive_time_period_milliseconds, + } + ).extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/json/__init__.py b/esphome/components/json/__init__.py index 63bc16dfa..f73fcb53f 100644 --- a/esphome/components/json/__init__.py +++ b/esphome/components/json/__init__.py @@ -1,12 +1,12 @@ import esphome.codegen as cg from esphome.core import coroutine_with_priority -CODEOWNERS = ['@OttoWinter'] -json_ns = cg.esphome_ns.namespace('json') +CODEOWNERS = ["@OttoWinter"] +json_ns = cg.esphome_ns.namespace("json") @coroutine_with_priority(1.0) def to_code(config): - cg.add_library('ArduinoJson-esphomelib', '5.13.3') - cg.add_define('USE_JSON') + cg.add_library("ArduinoJson-esphomelib", "5.13.3") + cg.add_define("USE_JSON") cg.add_global(json_ns.using) diff --git a/esphome/components/lcd_base/__init__.py b/esphome/components/lcd_base/__init__.py index bff194578..c577d7f8b 100644 --- a/esphome/components/lcd_base/__init__.py +++ b/esphome/components/lcd_base/__init__.py @@ -4,8 +4,8 @@ from esphome.components import display from esphome.const import CONF_DIMENSIONS from esphome.core import coroutine -lcd_base_ns = cg.esphome_ns.namespace('lcd_base') -LCDDisplay = lcd_base_ns.class_('LCDDisplay', cg.PollingComponent) +lcd_base_ns = cg.esphome_ns.namespace("lcd_base") +LCDDisplay = lcd_base_ns.class_("LCDDisplay", cg.PollingComponent) def validate_lcd_dimensions(value): @@ -17,9 +17,11 @@ def validate_lcd_dimensions(value): return value -LCD_SCHEMA = display.BASIC_DISPLAY_SCHEMA.extend({ - cv.Required(CONF_DIMENSIONS): validate_lcd_dimensions, -}).extend(cv.polling_component_schema('1s')) +LCD_SCHEMA = display.BASIC_DISPLAY_SCHEMA.extend( + { + cv.Required(CONF_DIMENSIONS): validate_lcd_dimensions, + } +).extend(cv.polling_component_schema("1s")) @coroutine diff --git a/esphome/components/lcd_gpio/display.py b/esphome/components/lcd_gpio/display.py index 91498d59c..28c6df2ef 100644 --- a/esphome/components/lcd_gpio/display.py +++ b/esphome/components/lcd_gpio/display.py @@ -2,29 +2,41 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.components import lcd_base -from esphome.const import CONF_DATA_PINS, CONF_ENABLE_PIN, CONF_RS_PIN, CONF_RW_PIN, CONF_ID, \ - CONF_LAMBDA +from esphome.const import ( + CONF_DATA_PINS, + CONF_ENABLE_PIN, + CONF_RS_PIN, + CONF_RW_PIN, + CONF_ID, + CONF_LAMBDA, +) -AUTO_LOAD = ['lcd_base'] +AUTO_LOAD = ["lcd_base"] -lcd_gpio_ns = cg.esphome_ns.namespace('lcd_gpio') -GPIOLCDDisplay = lcd_gpio_ns.class_('GPIOLCDDisplay', lcd_base.LCDDisplay) +lcd_gpio_ns = cg.esphome_ns.namespace("lcd_gpio") +GPIOLCDDisplay = lcd_gpio_ns.class_("GPIOLCDDisplay", lcd_base.LCDDisplay) def validate_pin_length(value): if len(value) != 4 and len(value) != 8: - raise cv.Invalid("LCD Displays can either operate in 4-pin or 8-pin mode," - "not {}-pin mode".format(len(value))) + raise cv.Invalid( + "LCD Displays can either operate in 4-pin or 8-pin mode," + "not {}-pin mode".format(len(value)) + ) return value -CONFIG_SCHEMA = lcd_base.LCD_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(GPIOLCDDisplay), - cv.Required(CONF_DATA_PINS): cv.All([pins.gpio_output_pin_schema], validate_pin_length), - cv.Required(CONF_ENABLE_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_RS_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_RW_PIN): pins.gpio_output_pin_schema, -}) +CONFIG_SCHEMA = lcd_base.LCD_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(GPIOLCDDisplay), + cv.Required(CONF_DATA_PINS): cv.All( + [pins.gpio_output_pin_schema], validate_pin_length + ), + cv.Required(CONF_ENABLE_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_RS_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_RW_PIN): pins.gpio_output_pin_schema, + } +) def to_code(config): @@ -45,7 +57,9 @@ def to_code(config): cg.add(var.set_rw_pin(rw)) if CONF_LAMBDA in config: - lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], - [(GPIOLCDDisplay.operator('ref'), 'it')], - return_type=cg.void) + lambda_ = yield cg.process_lambda( + config[CONF_LAMBDA], + [(GPIOLCDDisplay.operator("ref"), "it")], + return_type=cg.void, + ) cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/lcd_pcf8574/display.py b/esphome/components/lcd_pcf8574/display.py index 2bbb3a2f7..6499a8369 100644 --- a/esphome/components/lcd_pcf8574/display.py +++ b/esphome/components/lcd_pcf8574/display.py @@ -3,15 +3,19 @@ import esphome.config_validation as cv from esphome.components import lcd_base, i2c from esphome.const import CONF_ID, CONF_LAMBDA -DEPENDENCIES = ['i2c'] -AUTO_LOAD = ['lcd_base'] +DEPENDENCIES = ["i2c"] +AUTO_LOAD = ["lcd_base"] -lcd_pcf8574_ns = cg.esphome_ns.namespace('lcd_pcf8574') -PCF8574LCDDisplay = lcd_pcf8574_ns.class_('PCF8574LCDDisplay', lcd_base.LCDDisplay, i2c.I2CDevice) +lcd_pcf8574_ns = cg.esphome_ns.namespace("lcd_pcf8574") +PCF8574LCDDisplay = lcd_pcf8574_ns.class_( + "PCF8574LCDDisplay", lcd_base.LCDDisplay, i2c.I2CDevice +) -CONFIG_SCHEMA = lcd_base.LCD_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(PCF8574LCDDisplay), -}).extend(i2c.i2c_device_schema(0x3F)) +CONFIG_SCHEMA = lcd_base.LCD_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(PCF8574LCDDisplay), + } +).extend(i2c.i2c_device_schema(0x3F)) def to_code(config): @@ -20,7 +24,9 @@ def to_code(config): yield i2c.register_i2c_device(var, config) if CONF_LAMBDA in config: - lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], - [(PCF8574LCDDisplay.operator('ref'), 'it')], - return_type=cg.void) + lambda_ = yield cg.process_lambda( + config[CONF_LAMBDA], + [(PCF8574LCDDisplay.operator("ref"), "it")], + return_type=cg.void, + ) cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/ledc/__init__.py b/esphome/components/ledc/__init__.py index 6f14e1003..71a87b6ae 100644 --- a/esphome/components/ledc/__init__.py +++ b/esphome/components/ledc/__init__.py @@ -1 +1 @@ -CODEOWNERS = ['@OttoWinter'] +CODEOWNERS = ["@OttoWinter"] diff --git a/esphome/components/ledc/output.py b/esphome/components/ledc/output.py index b608e9bbf..df746fff4 100644 --- a/esphome/components/ledc/output.py +++ b/esphome/components/ledc/output.py @@ -2,19 +2,25 @@ 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_BIT_DEPTH, CONF_CHANNEL, CONF_FREQUENCY, \ - CONF_ID, CONF_PIN, ESP_PLATFORM_ESP32 +from esphome.const import ( + CONF_BIT_DEPTH, + CONF_CHANNEL, + CONF_FREQUENCY, + CONF_ID, + CONF_PIN, + ESP_PLATFORM_ESP32, +) ESP_PLATFORMS = [ESP_PLATFORM_ESP32] def calc_max_frequency(bit_depth): - return 80e6 / (2**bit_depth) + return 80e6 / (2 ** bit_depth) def calc_min_frequency(bit_depth): - max_div_num = ((2**20) - 1) / 256.0 - return 80e6 / (max_div_num * (2**bit_depth)) + max_div_num = ((2 ** 20) - 1) / 256.0 + return 80e6 / (max_div_num * (2 ** bit_depth)) def validate_frequency(value): @@ -22,27 +28,34 @@ def validate_frequency(value): min_freq = calc_min_frequency(20) max_freq = calc_max_frequency(1) if value < min_freq: - raise cv.Invalid("This frequency setting is not possible, please choose a higher " - "frequency (at least {}Hz)".format(int(min_freq))) + raise cv.Invalid( + "This frequency setting is not possible, please choose a higher " + "frequency (at least {}Hz)".format(int(min_freq)) + ) if value > max_freq: - raise cv.Invalid("This frequency setting is not possible, please choose a lower " - "frequency (at most {}Hz)".format(int(max_freq))) + raise cv.Invalid( + "This frequency setting is not possible, please choose a lower " + "frequency (at most {}Hz)".format(int(max_freq)) + ) return value -ledc_ns = cg.esphome_ns.namespace('ledc') -LEDCOutput = ledc_ns.class_('LEDCOutput', output.FloatOutput, cg.Component) -SetFrequencyAction = ledc_ns.class_('SetFrequencyAction', automation.Action) +ledc_ns = cg.esphome_ns.namespace("ledc") +LEDCOutput = ledc_ns.class_("LEDCOutput", output.FloatOutput, cg.Component) +SetFrequencyAction = ledc_ns.class_("SetFrequencyAction", automation.Action) -CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend({ - cv.Required(CONF_ID): cv.declare_id(LEDCOutput), - cv.Required(CONF_PIN): pins.internal_gpio_output_pin_schema, - cv.Optional(CONF_FREQUENCY, default='1kHz'): cv.frequency, - cv.Optional(CONF_CHANNEL): cv.int_range(min=0, max=15), - - cv.Optional(CONF_BIT_DEPTH): cv.invalid("The bit_depth option has been removed in v1.14, the " - "best bit depth is now automatically calculated."), -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( + { + cv.Required(CONF_ID): cv.declare_id(LEDCOutput), + cv.Required(CONF_PIN): pins.internal_gpio_output_pin_schema, + cv.Optional(CONF_FREQUENCY, default="1kHz"): cv.frequency, + cv.Optional(CONF_CHANNEL): cv.int_range(min=0, max=15), + cv.Optional(CONF_BIT_DEPTH): cv.invalid( + "The bit_depth option has been removed in v1.14, the " + "best bit depth is now automatically calculated." + ), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): @@ -55,10 +68,16 @@ def to_code(config): cg.add(var.set_frequency(config[CONF_FREQUENCY])) -@automation.register_action('output.ledc.set_frequency', SetFrequencyAction, cv.Schema({ - cv.Required(CONF_ID): cv.use_id(LEDCOutput), - cv.Required(CONF_FREQUENCY): cv.templatable(validate_frequency), -})) +@automation.register_action( + "output.ledc.set_frequency", + SetFrequencyAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(LEDCOutput), + cv.Required(CONF_FREQUENCY): cv.templatable(validate_frequency), + } + ), +) def ledc_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) diff --git a/esphome/components/light/__init__.py b/esphome/components/light/__init__.py index 9d58fa47b..034dbdaf3 100644 --- a/esphome/components/light/__init__.py +++ b/esphome/components/light/__init__.py @@ -2,62 +2,104 @@ import esphome.codegen as cg import esphome.config_validation as cv import esphome.automation as auto from esphome.components import mqtt, power_supply -from esphome.const import CONF_COLOR_CORRECT, \ - CONF_DEFAULT_TRANSITION_LENGTH, CONF_EFFECTS, CONF_GAMMA_CORRECT, CONF_ID, \ - CONF_INTERNAL, CONF_NAME, CONF_MQTT_ID, CONF_POWER_SUPPLY, CONF_RESTORE_MODE, \ - CONF_ON_TURN_OFF, CONF_ON_TURN_ON, CONF_TRIGGER_ID +from esphome.const import ( + CONF_COLOR_CORRECT, + CONF_DEFAULT_TRANSITION_LENGTH, + CONF_EFFECTS, + CONF_GAMMA_CORRECT, + CONF_ID, + CONF_INTERNAL, + CONF_NAME, + CONF_MQTT_ID, + CONF_POWER_SUPPLY, + CONF_RESTORE_MODE, + CONF_ON_TURN_OFF, + CONF_ON_TURN_ON, + CONF_TRIGGER_ID, +) from esphome.core import coroutine, coroutine_with_priority from .automation import light_control_to_code # noqa -from .effects import validate_effects, BINARY_EFFECTS, \ - MONOCHROMATIC_EFFECTS, RGB_EFFECTS, ADDRESSABLE_EFFECTS, EFFECTS_REGISTRY +from .effects import ( + validate_effects, + BINARY_EFFECTS, + MONOCHROMATIC_EFFECTS, + RGB_EFFECTS, + ADDRESSABLE_EFFECTS, + EFFECTS_REGISTRY, +) from .types import ( # noqa - LightState, AddressableLightState, light_ns, LightOutput, AddressableLight, \ - LightTurnOnTrigger, LightTurnOffTrigger) + LightState, + AddressableLightState, + light_ns, + LightOutput, + AddressableLight, + LightTurnOnTrigger, + LightTurnOffTrigger, +) -CODEOWNERS = ['@esphome/core'] +CODEOWNERS = ["@esphome/core"] IS_PLATFORM_COMPONENT = True -LightRestoreMode = light_ns.enum('LightRestoreMode') +LightRestoreMode = light_ns.enum("LightRestoreMode") RESTORE_MODES = { - 'RESTORE_DEFAULT_OFF': LightRestoreMode.LIGHT_RESTORE_DEFAULT_OFF, - 'RESTORE_DEFAULT_ON': LightRestoreMode.LIGHT_RESTORE_DEFAULT_ON, - 'ALWAYS_OFF': LightRestoreMode.LIGHT_ALWAYS_OFF, - 'ALWAYS_ON': LightRestoreMode.LIGHT_ALWAYS_ON, + "RESTORE_DEFAULT_OFF": LightRestoreMode.LIGHT_RESTORE_DEFAULT_OFF, + "RESTORE_DEFAULT_ON": LightRestoreMode.LIGHT_RESTORE_DEFAULT_ON, + "ALWAYS_OFF": LightRestoreMode.LIGHT_ALWAYS_OFF, + "ALWAYS_ON": LightRestoreMode.LIGHT_ALWAYS_ON, } -LIGHT_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(LightState), - cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTJSONLightComponent), - cv.Optional(CONF_RESTORE_MODE, default='restore_default_off'): - cv.enum(RESTORE_MODES, upper=True, space='_'), - cv.Optional(CONF_ON_TURN_ON): auto.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LightTurnOnTrigger), - }), - cv.Optional(CONF_ON_TURN_OFF): auto.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LightTurnOffTrigger), - }), -}) +LIGHT_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(LightState), + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTJSONLightComponent), + cv.Optional(CONF_RESTORE_MODE, default="restore_default_off"): cv.enum( + RESTORE_MODES, upper=True, space="_" + ), + cv.Optional(CONF_ON_TURN_ON): auto.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LightTurnOnTrigger), + } + ), + cv.Optional(CONF_ON_TURN_OFF): auto.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LightTurnOffTrigger), + } + ), + } +) -BINARY_LIGHT_SCHEMA = LIGHT_SCHEMA.extend({ - cv.Optional(CONF_EFFECTS): validate_effects(BINARY_EFFECTS), -}) +BINARY_LIGHT_SCHEMA = LIGHT_SCHEMA.extend( + { + cv.Optional(CONF_EFFECTS): validate_effects(BINARY_EFFECTS), + } +) -BRIGHTNESS_ONLY_LIGHT_SCHEMA = LIGHT_SCHEMA.extend({ - cv.Optional(CONF_GAMMA_CORRECT, default=2.8): cv.positive_float, - cv.Optional(CONF_DEFAULT_TRANSITION_LENGTH, default='1s'): cv.positive_time_period_milliseconds, - cv.Optional(CONF_EFFECTS): validate_effects(MONOCHROMATIC_EFFECTS), -}) +BRIGHTNESS_ONLY_LIGHT_SCHEMA = LIGHT_SCHEMA.extend( + { + cv.Optional(CONF_GAMMA_CORRECT, default=2.8): cv.positive_float, + cv.Optional( + CONF_DEFAULT_TRANSITION_LENGTH, default="1s" + ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_EFFECTS): validate_effects(MONOCHROMATIC_EFFECTS), + } +) -RGB_LIGHT_SCHEMA = BRIGHTNESS_ONLY_LIGHT_SCHEMA.extend({ - cv.Optional(CONF_EFFECTS): validate_effects(RGB_EFFECTS), -}) +RGB_LIGHT_SCHEMA = BRIGHTNESS_ONLY_LIGHT_SCHEMA.extend( + { + cv.Optional(CONF_EFFECTS): validate_effects(RGB_EFFECTS), + } +) -ADDRESSABLE_LIGHT_SCHEMA = RGB_LIGHT_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(AddressableLightState), - cv.Optional(CONF_EFFECTS): validate_effects(ADDRESSABLE_EFFECTS), - cv.Optional(CONF_COLOR_CORRECT): cv.All([cv.percentage], cv.Length(min=3, max=4)), - cv.Optional(CONF_POWER_SUPPLY): cv.use_id(power_supply.PowerSupply), -}) +ADDRESSABLE_LIGHT_SCHEMA = RGB_LIGHT_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(AddressableLightState), + cv.Optional(CONF_EFFECTS): validate_effects(ADDRESSABLE_EFFECTS), + cv.Optional(CONF_COLOR_CORRECT): cv.All( + [cv.percentage], cv.Length(min=3, max=4) + ), + cv.Optional(CONF_POWER_SUPPLY): cv.use_id(power_supply.PowerSupply), + } +) @coroutine @@ -66,10 +108,16 @@ def setup_light_core_(light_var, output_var, config): if CONF_INTERNAL in config: cg.add(light_var.set_internal(config[CONF_INTERNAL])) if CONF_DEFAULT_TRANSITION_LENGTH in config: - cg.add(light_var.set_default_transition_length(config[CONF_DEFAULT_TRANSITION_LENGTH])) + cg.add( + light_var.set_default_transition_length( + config[CONF_DEFAULT_TRANSITION_LENGTH] + ) + ) if CONF_GAMMA_CORRECT in config: cg.add(light_var.set_gamma_correct(config[CONF_GAMMA_CORRECT])) - effects = yield cg.build_registry_list(EFFECTS_REGISTRY, config.get(CONF_EFFECTS, [])) + effects = yield cg.build_registry_list( + EFFECTS_REGISTRY, config.get(CONF_EFFECTS, []) + ) cg.add(light_var.add_effects(effects)) for conf in config.get(CONF_ON_TURN_ON, []): @@ -101,5 +149,5 @@ def register_light(output_var, config): @coroutine_with_priority(100.0) def to_code(config): - cg.add_define('USE_LIGHT') + cg.add_define("USE_LIGHT") cg.add_global(light_ns.using) diff --git a/esphome/components/light/automation.py b/esphome/components/light/automation.py index 9e14246c0..7f1c6d9cb 100644 --- a/esphome/components/light/automation.py +++ b/esphome/components/light/automation.py @@ -1,54 +1,102 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation -from esphome.const import CONF_ID, CONF_TRANSITION_LENGTH, CONF_STATE, CONF_FLASH_LENGTH, \ - CONF_EFFECT, CONF_BRIGHTNESS, CONF_RED, CONF_GREEN, CONF_BLUE, CONF_WHITE, \ - CONF_COLOR_TEMPERATURE, CONF_RANGE_FROM, CONF_RANGE_TO -from .types import DimRelativeAction, ToggleAction, LightState, LightControlAction, \ - AddressableLightState, AddressableSet, LightIsOnCondition, LightIsOffCondition +from esphome.const import ( + CONF_ID, + CONF_TRANSITION_LENGTH, + CONF_STATE, + CONF_FLASH_LENGTH, + CONF_EFFECT, + CONF_BRIGHTNESS, + CONF_RED, + CONF_GREEN, + CONF_BLUE, + CONF_WHITE, + CONF_COLOR_TEMPERATURE, + CONF_RANGE_FROM, + CONF_RANGE_TO, +) +from .types import ( + DimRelativeAction, + ToggleAction, + LightState, + LightControlAction, + AddressableLightState, + AddressableSet, + LightIsOnCondition, + LightIsOffCondition, +) -@automation.register_action('light.toggle', ToggleAction, automation.maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(LightState), - cv.Optional(CONF_TRANSITION_LENGTH): cv.templatable(cv.positive_time_period_milliseconds), -})) +@automation.register_action( + "light.toggle", + ToggleAction, + automation.maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(LightState), + cv.Optional(CONF_TRANSITION_LENGTH): cv.templatable( + cv.positive_time_period_milliseconds + ), + } + ), +) def light_toggle_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) if CONF_TRANSITION_LENGTH in config: - template_ = yield cg.templatable(config[CONF_TRANSITION_LENGTH], args, cg.uint32) + template_ = yield cg.templatable( + config[CONF_TRANSITION_LENGTH], args, cg.uint32 + ) cg.add(var.set_transition_length(template_)) yield var -LIGHT_CONTROL_ACTION_SCHEMA = cv.Schema({ - cv.Required(CONF_ID): cv.use_id(LightState), - cv.Optional(CONF_STATE): cv.templatable(cv.boolean), - cv.Exclusive(CONF_TRANSITION_LENGTH, 'transformer'): - cv.templatable(cv.positive_time_period_milliseconds), - cv.Exclusive(CONF_FLASH_LENGTH, 'transformer'): - cv.templatable(cv.positive_time_period_milliseconds), - cv.Exclusive(CONF_EFFECT, 'transformer'): cv.templatable(cv.string), - cv.Optional(CONF_BRIGHTNESS): cv.templatable(cv.percentage), - cv.Optional(CONF_RED): cv.templatable(cv.percentage), - cv.Optional(CONF_GREEN): cv.templatable(cv.percentage), - cv.Optional(CONF_BLUE): cv.templatable(cv.percentage), - cv.Optional(CONF_WHITE): cv.templatable(cv.percentage), - cv.Optional(CONF_COLOR_TEMPERATURE): cv.templatable(cv.color_temperature), -}) -LIGHT_TURN_OFF_ACTION_SCHEMA = automation.maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(LightState), - cv.Optional(CONF_TRANSITION_LENGTH): cv.templatable(cv.positive_time_period_milliseconds), - cv.Optional(CONF_STATE, default=False): False, -}) -LIGHT_TURN_ON_ACTION_SCHEMA = automation.maybe_simple_id(LIGHT_CONTROL_ACTION_SCHEMA.extend({ - cv.Optional(CONF_STATE, default=True): True, -})) +LIGHT_CONTROL_ACTION_SCHEMA = cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(LightState), + cv.Optional(CONF_STATE): cv.templatable(cv.boolean), + cv.Exclusive(CONF_TRANSITION_LENGTH, "transformer"): cv.templatable( + cv.positive_time_period_milliseconds + ), + cv.Exclusive(CONF_FLASH_LENGTH, "transformer"): cv.templatable( + cv.positive_time_period_milliseconds + ), + cv.Exclusive(CONF_EFFECT, "transformer"): cv.templatable(cv.string), + cv.Optional(CONF_BRIGHTNESS): cv.templatable(cv.percentage), + cv.Optional(CONF_RED): cv.templatable(cv.percentage), + cv.Optional(CONF_GREEN): cv.templatable(cv.percentage), + cv.Optional(CONF_BLUE): cv.templatable(cv.percentage), + cv.Optional(CONF_WHITE): cv.templatable(cv.percentage), + cv.Optional(CONF_COLOR_TEMPERATURE): cv.templatable(cv.color_temperature), + } +) +LIGHT_TURN_OFF_ACTION_SCHEMA = automation.maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(LightState), + cv.Optional(CONF_TRANSITION_LENGTH): cv.templatable( + cv.positive_time_period_milliseconds + ), + cv.Optional(CONF_STATE, default=False): False, + } +) +LIGHT_TURN_ON_ACTION_SCHEMA = automation.maybe_simple_id( + LIGHT_CONTROL_ACTION_SCHEMA.extend( + { + cv.Optional(CONF_STATE, default=True): True, + } + ) +) -@automation.register_action('light.turn_off', LightControlAction, LIGHT_TURN_OFF_ACTION_SCHEMA) -@automation.register_action('light.turn_on', LightControlAction, LIGHT_TURN_ON_ACTION_SCHEMA) -@automation.register_action('light.control', LightControlAction, LIGHT_CONTROL_ACTION_SCHEMA) +@automation.register_action( + "light.turn_off", LightControlAction, LIGHT_TURN_OFF_ACTION_SCHEMA +) +@automation.register_action( + "light.turn_on", LightControlAction, LIGHT_TURN_ON_ACTION_SCHEMA +) +@automation.register_action( + "light.control", LightControlAction, LIGHT_CONTROL_ACTION_SCHEMA +) def light_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) @@ -56,7 +104,9 @@ def light_control_to_code(config, action_id, template_arg, args): template_ = yield cg.templatable(config[CONF_STATE], args, bool) cg.add(var.set_state(template_)) if CONF_TRANSITION_LENGTH in config: - template_ = yield cg.templatable(config[CONF_TRANSITION_LENGTH], args, cg.uint32) + template_ = yield cg.templatable( + config[CONF_TRANSITION_LENGTH], args, cg.uint32 + ) cg.add(var.set_transition_length(template_)) if CONF_FLASH_LENGTH in config: template_ = yield cg.templatable(config[CONF_FLASH_LENGTH], args, cg.uint32) @@ -85,16 +135,23 @@ def light_control_to_code(config, action_id, template_arg, args): yield var -CONF_RELATIVE_BRIGHTNESS = 'relative_brightness' -LIGHT_DIM_RELATIVE_ACTION_SCHEMA = cv.Schema({ - cv.Required(CONF_ID): cv.use_id(LightState), - cv.Required(CONF_RELATIVE_BRIGHTNESS): cv.templatable(cv.possibly_negative_percentage), - cv.Optional(CONF_TRANSITION_LENGTH): cv.templatable(cv.positive_time_period_milliseconds), -}) +CONF_RELATIVE_BRIGHTNESS = "relative_brightness" +LIGHT_DIM_RELATIVE_ACTION_SCHEMA = cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(LightState), + cv.Required(CONF_RELATIVE_BRIGHTNESS): cv.templatable( + cv.possibly_negative_percentage + ), + cv.Optional(CONF_TRANSITION_LENGTH): cv.templatable( + cv.positive_time_period_milliseconds + ), + } +) -@automation.register_action('light.dim_relative', DimRelativeAction, - LIGHT_DIM_RELATIVE_ACTION_SCHEMA) +@automation.register_action( + "light.dim_relative", DimRelativeAction, LIGHT_DIM_RELATIVE_ACTION_SCHEMA +) def light_dim_relative_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) @@ -106,19 +163,22 @@ def light_dim_relative_to_code(config, action_id, template_arg, args): yield var -LIGHT_ADDRESSABLE_SET_ACTION_SCHEMA = cv.Schema({ - cv.Required(CONF_ID): cv.use_id(AddressableLightState), - cv.Optional(CONF_RANGE_FROM): cv.templatable(cv.positive_int), - cv.Optional(CONF_RANGE_TO): cv.templatable(cv.positive_int), - cv.Optional(CONF_RED): cv.templatable(cv.percentage), - cv.Optional(CONF_GREEN): cv.templatable(cv.percentage), - cv.Optional(CONF_BLUE): cv.templatable(cv.percentage), - cv.Optional(CONF_WHITE): cv.templatable(cv.percentage), -}) +LIGHT_ADDRESSABLE_SET_ACTION_SCHEMA = cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(AddressableLightState), + cv.Optional(CONF_RANGE_FROM): cv.templatable(cv.positive_int), + cv.Optional(CONF_RANGE_TO): cv.templatable(cv.positive_int), + cv.Optional(CONF_RED): cv.templatable(cv.percentage), + cv.Optional(CONF_GREEN): cv.templatable(cv.percentage), + cv.Optional(CONF_BLUE): cv.templatable(cv.percentage), + cv.Optional(CONF_WHITE): cv.templatable(cv.percentage), + } +) -@automation.register_action('light.addressable_set', AddressableSet, - LIGHT_ADDRESSABLE_SET_ACTION_SCHEMA) +@automation.register_action( + "light.addressable_set", AddressableSet, LIGHT_ADDRESSABLE_SET_ACTION_SCHEMA +) def light_addressable_set_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) @@ -133,28 +193,46 @@ def light_addressable_set_to_code(config, action_id, template_arg, args): return int(round(x * 255)) if CONF_RED in config: - templ = yield cg.templatable(config[CONF_RED], args, cg.uint8, to_exp=rgbw_to_exp) + templ = yield cg.templatable( + config[CONF_RED], args, cg.uint8, to_exp=rgbw_to_exp + ) cg.add(var.set_red(templ)) if CONF_GREEN in config: - templ = yield cg.templatable(config[CONF_GREEN], args, cg.uint8, to_exp=rgbw_to_exp) + templ = yield cg.templatable( + config[CONF_GREEN], args, cg.uint8, to_exp=rgbw_to_exp + ) cg.add(var.set_green(templ)) if CONF_BLUE in config: - templ = yield cg.templatable(config[CONF_BLUE], args, cg.uint8, to_exp=rgbw_to_exp) + templ = yield cg.templatable( + config[CONF_BLUE], args, cg.uint8, to_exp=rgbw_to_exp + ) cg.add(var.set_blue(templ)) if CONF_WHITE in config: - templ = yield cg.templatable(config[CONF_WHITE], args, cg.uint8, to_exp=rgbw_to_exp) + templ = yield cg.templatable( + config[CONF_WHITE], args, cg.uint8, to_exp=rgbw_to_exp + ) cg.add(var.set_white(templ)) yield var -@automation.register_condition('light.is_on', LightIsOnCondition, - automation.maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(LightState), - })) -@automation.register_condition('light.is_off', LightIsOffCondition, - automation.maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(LightState), - })) +@automation.register_condition( + "light.is_on", + LightIsOnCondition, + automation.maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(LightState), + } + ), +) +@automation.register_condition( + "light.is_off", + LightIsOffCondition, + automation.maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(LightState), + } + ), +) def light_is_on_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) diff --git a/esphome/components/light/effects.py b/esphome/components/light/effects.py index edb7a39ed..9f017de98 100644 --- a/esphome/components/light/effects.py +++ b/esphome/components/light/effects.py @@ -2,38 +2,69 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation -from esphome.const import CONF_NAME, CONF_LAMBDA, CONF_UPDATE_INTERVAL, CONF_TRANSITION_LENGTH, \ - CONF_COLORS, CONF_STATE, CONF_DURATION, CONF_BRIGHTNESS, CONF_RED, CONF_GREEN, CONF_BLUE, \ - CONF_WHITE, CONF_ALPHA, CONF_INTENSITY, CONF_SPEED, CONF_WIDTH, CONF_NUM_LEDS, CONF_RANDOM, \ - CONF_SEQUENCE +from esphome.const import ( + CONF_NAME, + CONF_LAMBDA, + CONF_UPDATE_INTERVAL, + CONF_TRANSITION_LENGTH, + CONF_COLORS, + CONF_STATE, + CONF_DURATION, + CONF_BRIGHTNESS, + CONF_RED, + CONF_GREEN, + CONF_BLUE, + CONF_WHITE, + CONF_ALPHA, + CONF_INTENSITY, + CONF_SPEED, + CONF_WIDTH, + CONF_NUM_LEDS, + CONF_RANDOM, + CONF_SEQUENCE, +) from esphome.util import Registry -from .types import LambdaLightEffect, RandomLightEffect, StrobeLightEffect, \ - StrobeLightEffectColor, LightColorValues, AddressableLightRef, AddressableLambdaLightEffect, \ - FlickerLightEffect, AddressableRainbowLightEffect, AddressableColorWipeEffect, \ - AddressableColorWipeEffectColor, AddressableScanEffect, AddressableTwinkleEffect, \ - AddressableRandomTwinkleEffect, AddressableFireworksEffect, AddressableFlickerEffect, \ - AutomationLightEffect, Color +from .types import ( + LambdaLightEffect, + RandomLightEffect, + StrobeLightEffect, + StrobeLightEffectColor, + LightColorValues, + AddressableLightRef, + AddressableLambdaLightEffect, + FlickerLightEffect, + AddressableRainbowLightEffect, + AddressableColorWipeEffect, + AddressableColorWipeEffectColor, + AddressableScanEffect, + AddressableTwinkleEffect, + AddressableRandomTwinkleEffect, + AddressableFireworksEffect, + AddressableFlickerEffect, + AutomationLightEffect, + Color, +) -CONF_ADD_LED_INTERVAL = 'add_led_interval' -CONF_REVERSE = 'reverse' -CONF_MOVE_INTERVAL = 'move_interval' -CONF_SCAN_WIDTH = 'scan_width' -CONF_TWINKLE_PROBABILITY = 'twinkle_probability' -CONF_PROGRESS_INTERVAL = 'progress_interval' -CONF_SPARK_PROBABILITY = 'spark_probability' -CONF_USE_RANDOM_COLOR = 'use_random_color' -CONF_FADE_OUT_RATE = 'fade_out_rate' -CONF_STROBE = 'strobe' -CONF_FLICKER = 'flicker' -CONF_ADDRESSABLE_LAMBDA = 'addressable_lambda' -CONF_ADDRESSABLE_RAINBOW = 'addressable_rainbow' -CONF_ADDRESSABLE_COLOR_WIPE = 'addressable_color_wipe' -CONF_ADDRESSABLE_SCAN = 'addressable_scan' -CONF_ADDRESSABLE_TWINKLE = 'addressable_twinkle' -CONF_ADDRESSABLE_RANDOM_TWINKLE = 'addressable_random_twinkle' -CONF_ADDRESSABLE_FIREWORKS = 'addressable_fireworks' -CONF_ADDRESSABLE_FLICKER = 'addressable_flicker' -CONF_AUTOMATION = 'automation' +CONF_ADD_LED_INTERVAL = "add_led_interval" +CONF_REVERSE = "reverse" +CONF_MOVE_INTERVAL = "move_interval" +CONF_SCAN_WIDTH = "scan_width" +CONF_TWINKLE_PROBABILITY = "twinkle_probability" +CONF_PROGRESS_INTERVAL = "progress_interval" +CONF_SPARK_PROBABILITY = "spark_probability" +CONF_USE_RANDOM_COLOR = "use_random_color" +CONF_FADE_OUT_RATE = "fade_out_rate" +CONF_STROBE = "strobe" +CONF_FLICKER = "flicker" +CONF_ADDRESSABLE_LAMBDA = "addressable_lambda" +CONF_ADDRESSABLE_RAINBOW = "addressable_rainbow" +CONF_ADDRESSABLE_COLOR_WIPE = "addressable_color_wipe" +CONF_ADDRESSABLE_SCAN = "addressable_scan" +CONF_ADDRESSABLE_TWINKLE = "addressable_twinkle" +CONF_ADDRESSABLE_RANDOM_TWINKLE = "addressable_random_twinkle" +CONF_ADDRESSABLE_FIREWORKS = "addressable_fireworks" +CONF_ADDRESSABLE_FLICKER = "addressable_flicker" +CONF_AUTOMATION = "automation" BINARY_EFFECTS = [] MONOCHROMATIC_EFFECTS = [] @@ -44,9 +75,11 @@ EFFECTS_REGISTRY = Registry() def register_effect(name, effect_type, default_name, schema, *extra_validators): - schema = cv.Schema(schema).extend({ - cv.Optional(CONF_NAME, default=default_name): cv.string_strict, - }) + schema = cv.Schema(schema).extend( + { + cv.Optional(CONF_NAME, default=default_name): cv.string_strict, + } + ) validator = cv.All(schema, *extra_validators) return EFFECTS_REGISTRY.register(name, effect_type, validator) @@ -61,7 +94,9 @@ def register_binary_effect(name, effect_type, default_name, schema, *extra_valid return register_effect(name, effect_type, default_name, schema, *extra_validators) -def register_monochromatic_effect(name, effect_type, default_name, schema, *extra_validators): +def register_monochromatic_effect( + name, effect_type, default_name, schema, *extra_validators +): # monochromatic effect can be used for all lights expect binary MONOCHROMATIC_EFFECTS.append(name) RGB_EFFECTS.append(name) @@ -78,36 +113,58 @@ def register_rgb_effect(name, effect_type, default_name, schema, *extra_validato return register_effect(name, effect_type, default_name, schema, *extra_validators) -def register_addressable_effect(name, effect_type, default_name, schema, *extra_validators): +def register_addressable_effect( + name, effect_type, default_name, schema, *extra_validators +): # addressable effect can be used only in addressable ADDRESSABLE_EFFECTS.append(name) return register_effect(name, effect_type, default_name, schema, *extra_validators) -@register_binary_effect('lambda', LambdaLightEffect, "Lambda", { - cv.Required(CONF_LAMBDA): cv.lambda_, - cv.Optional(CONF_UPDATE_INTERVAL, default='0ms'): cv.update_interval, -}) +@register_binary_effect( + "lambda", + LambdaLightEffect, + "Lambda", + { + cv.Required(CONF_LAMBDA): cv.lambda_, + cv.Optional(CONF_UPDATE_INTERVAL, default="0ms"): cv.update_interval, + }, +) def lambda_effect_to_code(config, effect_id): lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], [], return_type=cg.void) - yield cg.new_Pvariable(effect_id, config[CONF_NAME], lambda_, - config[CONF_UPDATE_INTERVAL]) + yield cg.new_Pvariable( + effect_id, config[CONF_NAME], lambda_, config[CONF_UPDATE_INTERVAL] + ) -@register_binary_effect('automation', AutomationLightEffect, "Automation", { - cv.Required(CONF_SEQUENCE): automation.validate_automation(single=True), -}) +@register_binary_effect( + "automation", + AutomationLightEffect, + "Automation", + { + cv.Required(CONF_SEQUENCE): automation.validate_automation(single=True), + }, +) def automation_effect_to_code(config, effect_id): var = yield cg.new_Pvariable(effect_id, config[CONF_NAME]) yield automation.build_automation(var.get_trig(), [], config[CONF_SEQUENCE]) yield var -@register_rgb_effect('random', RandomLightEffect, "Random", { - cv.Optional(CONF_TRANSITION_LENGTH, default='7.5s'): cv.positive_time_period_milliseconds, - cv.Optional(CONF_UPDATE_INTERVAL, default='10s'): cv.positive_time_period_milliseconds, -}) +@register_rgb_effect( + "random", + RandomLightEffect, + "Random", + { + cv.Optional( + CONF_TRANSITION_LENGTH, default="7.5s" + ): cv.positive_time_period_milliseconds, + cv.Optional( + CONF_UPDATE_INTERVAL, default="10s" + ): cv.positive_time_period_milliseconds, + }, +) def random_effect_to_code(config, effect_id): effect = cg.new_Pvariable(effect_id, config[CONF_NAME]) cg.add(effect.set_transition_length(config[CONF_TRANSITION_LENGTH])) @@ -115,40 +172,79 @@ def random_effect_to_code(config, effect_id): yield effect -@register_binary_effect('strobe', StrobeLightEffect, "Strobe", { - cv.Optional(CONF_COLORS, default=[ - {CONF_STATE: True, CONF_DURATION: '0.5s'}, - {CONF_STATE: False, CONF_DURATION: '0.5s'}, - ]): cv.All(cv.ensure_list(cv.Schema({ - cv.Optional(CONF_STATE, default=True): cv.boolean, - cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, - cv.Optional(CONF_RED, default=1.0): cv.percentage, - cv.Optional(CONF_GREEN, default=1.0): cv.percentage, - cv.Optional(CONF_BLUE, default=1.0): cv.percentage, - cv.Optional(CONF_WHITE, default=1.0): cv.percentage, - cv.Required(CONF_DURATION): cv.positive_time_period_milliseconds, - }), cv.has_at_least_one_key(CONF_STATE, CONF_BRIGHTNESS, CONF_RED, CONF_GREEN, CONF_BLUE, - CONF_WHITE)), cv.Length(min=2)), -}) +@register_binary_effect( + "strobe", + StrobeLightEffect, + "Strobe", + { + cv.Optional( + CONF_COLORS, + default=[ + {CONF_STATE: True, CONF_DURATION: "0.5s"}, + {CONF_STATE: False, CONF_DURATION: "0.5s"}, + ], + ): cv.All( + cv.ensure_list( + cv.Schema( + { + cv.Optional(CONF_STATE, default=True): cv.boolean, + cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, + cv.Optional(CONF_RED, default=1.0): cv.percentage, + cv.Optional(CONF_GREEN, default=1.0): cv.percentage, + cv.Optional(CONF_BLUE, default=1.0): cv.percentage, + cv.Optional(CONF_WHITE, default=1.0): cv.percentage, + cv.Required( + CONF_DURATION + ): cv.positive_time_period_milliseconds, + } + ), + cv.has_at_least_one_key( + CONF_STATE, + CONF_BRIGHTNESS, + CONF_RED, + CONF_GREEN, + CONF_BLUE, + CONF_WHITE, + ), + ), + cv.Length(min=2), + ), + }, +) def strobe_effect_to_code(config, effect_id): var = cg.new_Pvariable(effect_id, config[CONF_NAME]) colors = [] for color in config.get(CONF_COLORS, []): - colors.append(cg.StructInitializer( - StrobeLightEffectColor, - ('color', LightColorValues(color[CONF_STATE], color[CONF_BRIGHTNESS], - color[CONF_RED], color[CONF_GREEN], color[CONF_BLUE], - color[CONF_WHITE])), - ('duration', color[CONF_DURATION]), - )) + colors.append( + cg.StructInitializer( + StrobeLightEffectColor, + ( + "color", + LightColorValues( + color[CONF_STATE], + color[CONF_BRIGHTNESS], + color[CONF_RED], + color[CONF_GREEN], + color[CONF_BLUE], + color[CONF_WHITE], + ), + ), + ("duration", color[CONF_DURATION]), + ) + ) cg.add(var.set_colors(colors)) yield var -@register_monochromatic_effect('flicker', FlickerLightEffect, "Flicker", { - cv.Optional(CONF_ALPHA, default=0.95): cv.percentage, - cv.Optional(CONF_INTENSITY, default=0.015): cv.percentage, -}) +@register_monochromatic_effect( + "flicker", + FlickerLightEffect, + "Flicker", + { + cv.Optional(CONF_ALPHA, default=0.95): cv.percentage, + cv.Optional(CONF_INTENSITY, default=0.015): cv.percentage, + }, +) def flicker_effect_to_code(config, effect_id): var = cg.new_Pvariable(effect_id, config[CONF_NAME]) cg.add(var.set_alpha(config[CONF_ALPHA])) @@ -157,23 +253,38 @@ def flicker_effect_to_code(config, effect_id): @register_addressable_effect( - 'addressable_lambda', AddressableLambdaLightEffect, "Addressable Lambda", { + "addressable_lambda", + AddressableLambdaLightEffect, + "Addressable Lambda", + { cv.Required(CONF_LAMBDA): cv.lambda_, - cv.Optional(CONF_UPDATE_INTERVAL, default='0ms'): cv.positive_time_period_milliseconds, - } + cv.Optional( + CONF_UPDATE_INTERVAL, default="0ms" + ): cv.positive_time_period_milliseconds, + }, ) def addressable_lambda_effect_to_code(config, effect_id): - args = [(AddressableLightRef, 'it'), (Color, 'current_color'), (bool, 'initial_run')] + args = [ + (AddressableLightRef, "it"), + (Color, "current_color"), + (bool, "initial_run"), + ] lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], args, return_type=cg.void) - var = cg.new_Pvariable(effect_id, config[CONF_NAME], lambda_, - config[CONF_UPDATE_INTERVAL]) + var = cg.new_Pvariable( + effect_id, config[CONF_NAME], lambda_, config[CONF_UPDATE_INTERVAL] + ) yield var -@register_addressable_effect('addressable_rainbow', AddressableRainbowLightEffect, "Rainbow", { - cv.Optional(CONF_SPEED, default=10): cv.uint32_t, - cv.Optional(CONF_WIDTH, default=50): cv.uint32_t, -}) +@register_addressable_effect( + "addressable_rainbow", + AddressableRainbowLightEffect, + "Rainbow", + { + cv.Optional(CONF_SPEED, default=10): cv.uint32_t, + cv.Optional(CONF_WIDTH, default=50): cv.uint32_t, + }, +) def addressable_rainbow_effect_to_code(config, effect_id): var = cg.new_Pvariable(effect_id, config[CONF_NAME]) cg.add(var.set_speed(config[CONF_SPEED])) @@ -181,41 +292,61 @@ def addressable_rainbow_effect_to_code(config, effect_id): yield var -@register_addressable_effect('addressable_color_wipe', AddressableColorWipeEffect, "Color Wipe", { - cv.Optional(CONF_COLORS, default=[{CONF_NUM_LEDS: 1, CONF_RANDOM: True}]): cv.ensure_list({ - cv.Optional(CONF_RED, default=1.0): cv.percentage, - cv.Optional(CONF_GREEN, default=1.0): cv.percentage, - cv.Optional(CONF_BLUE, default=1.0): cv.percentage, - cv.Optional(CONF_WHITE, default=1.0): cv.percentage, - cv.Optional(CONF_RANDOM, default=False): cv.boolean, - cv.Required(CONF_NUM_LEDS): cv.All(cv.uint32_t, cv.Range(min=1)), - }), - cv.Optional(CONF_ADD_LED_INTERVAL, default='0.1s'): cv.positive_time_period_milliseconds, - cv.Optional(CONF_REVERSE, default=False): cv.boolean, -}) +@register_addressable_effect( + "addressable_color_wipe", + AddressableColorWipeEffect, + "Color Wipe", + { + cv.Optional( + CONF_COLORS, default=[{CONF_NUM_LEDS: 1, CONF_RANDOM: True}] + ): cv.ensure_list( + { + cv.Optional(CONF_RED, default=1.0): cv.percentage, + cv.Optional(CONF_GREEN, default=1.0): cv.percentage, + cv.Optional(CONF_BLUE, default=1.0): cv.percentage, + cv.Optional(CONF_WHITE, default=1.0): cv.percentage, + cv.Optional(CONF_RANDOM, default=False): cv.boolean, + cv.Required(CONF_NUM_LEDS): cv.All(cv.uint32_t, cv.Range(min=1)), + } + ), + cv.Optional( + CONF_ADD_LED_INTERVAL, default="0.1s" + ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_REVERSE, default=False): cv.boolean, + }, +) def addressable_color_wipe_effect_to_code(config, effect_id): var = cg.new_Pvariable(effect_id, config[CONF_NAME]) cg.add(var.set_add_led_interval(config[CONF_ADD_LED_INTERVAL])) cg.add(var.set_reverse(config[CONF_REVERSE])) colors = [] for color in config.get(CONF_COLORS, []): - colors.append(cg.StructInitializer( - AddressableColorWipeEffectColor, - ('r', int(round(color[CONF_RED] * 255))), - ('g', int(round(color[CONF_GREEN] * 255))), - ('b', int(round(color[CONF_BLUE] * 255))), - ('w', int(round(color[CONF_WHITE] * 255))), - ('random', color[CONF_RANDOM]), - ('num_leds', color[CONF_NUM_LEDS]), - )) + colors.append( + cg.StructInitializer( + AddressableColorWipeEffectColor, + ("r", int(round(color[CONF_RED] * 255))), + ("g", int(round(color[CONF_GREEN] * 255))), + ("b", int(round(color[CONF_BLUE] * 255))), + ("w", int(round(color[CONF_WHITE] * 255))), + ("random", color[CONF_RANDOM]), + ("num_leds", color[CONF_NUM_LEDS]), + ) + ) cg.add(var.set_colors(colors)) yield var -@register_addressable_effect('addressable_scan', AddressableScanEffect, "Scan", { - cv.Optional(CONF_MOVE_INTERVAL, default='0.1s'): cv.positive_time_period_milliseconds, - cv.Optional(CONF_SCAN_WIDTH, default=1): cv.int_range(min=1), -}) +@register_addressable_effect( + "addressable_scan", + AddressableScanEffect, + "Scan", + { + cv.Optional( + CONF_MOVE_INTERVAL, default="0.1s" + ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_SCAN_WIDTH, default=1): cv.int_range(min=1), + }, +) def addressable_scan_effect_to_code(config, effect_id): var = cg.new_Pvariable(effect_id, config[CONF_NAME]) cg.add(var.set_move_interval(config[CONF_MOVE_INTERVAL])) @@ -223,10 +354,17 @@ def addressable_scan_effect_to_code(config, effect_id): yield var -@register_addressable_effect('addressable_twinkle', AddressableTwinkleEffect, "Twinkle", { - cv.Optional(CONF_TWINKLE_PROBABILITY, default='5%'): cv.percentage, - cv.Optional(CONF_PROGRESS_INTERVAL, default='4ms'): cv.positive_time_period_milliseconds, -}) +@register_addressable_effect( + "addressable_twinkle", + AddressableTwinkleEffect, + "Twinkle", + { + cv.Optional(CONF_TWINKLE_PROBABILITY, default="5%"): cv.percentage, + cv.Optional( + CONF_PROGRESS_INTERVAL, default="4ms" + ): cv.positive_time_period_milliseconds, + }, +) def addressable_twinkle_effect_to_code(config, effect_id): var = cg.new_Pvariable(effect_id, config[CONF_NAME]) cg.add(var.set_twinkle_probability(config[CONF_TWINKLE_PROBABILITY])) @@ -235,10 +373,15 @@ def addressable_twinkle_effect_to_code(config, effect_id): @register_addressable_effect( - 'addressable_random_twinkle', AddressableRandomTwinkleEffect, "Random Twinkle", { - cv.Optional(CONF_TWINKLE_PROBABILITY, default='5%'): cv.percentage, - cv.Optional(CONF_PROGRESS_INTERVAL, default='32ms'): cv.positive_time_period_milliseconds, - } + "addressable_random_twinkle", + AddressableRandomTwinkleEffect, + "Random Twinkle", + { + cv.Optional(CONF_TWINKLE_PROBABILITY, default="5%"): cv.percentage, + cv.Optional( + CONF_PROGRESS_INTERVAL, default="32ms" + ): cv.positive_time_period_milliseconds, + }, ) def addressable_random_twinkle_effect_to_code(config, effect_id): var = cg.new_Pvariable(effect_id, config[CONF_NAME]) @@ -247,12 +390,19 @@ def addressable_random_twinkle_effect_to_code(config, effect_id): yield var -@register_addressable_effect('addressable_fireworks', AddressableFireworksEffect, "Fireworks", { - cv.Optional(CONF_UPDATE_INTERVAL, default='32ms'): cv.positive_time_period_milliseconds, - cv.Optional(CONF_SPARK_PROBABILITY, default='10%'): cv.percentage, - cv.Optional(CONF_USE_RANDOM_COLOR, default=False): cv.boolean, - cv.Optional(CONF_FADE_OUT_RATE, default=120): cv.uint8_t, -}) +@register_addressable_effect( + "addressable_fireworks", + AddressableFireworksEffect, + "Fireworks", + { + cv.Optional( + CONF_UPDATE_INTERVAL, default="32ms" + ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_SPARK_PROBABILITY, default="10%"): cv.percentage, + cv.Optional(CONF_USE_RANDOM_COLOR, default=False): cv.boolean, + cv.Optional(CONF_FADE_OUT_RATE, default=120): cv.uint8_t, + }, +) def addressable_fireworks_effect_to_code(config, effect_id): var = cg.new_Pvariable(effect_id, config[CONF_NAME]) cg.add(var.set_update_interval(config[CONF_UPDATE_INTERVAL])) @@ -263,10 +413,15 @@ def addressable_fireworks_effect_to_code(config, effect_id): @register_addressable_effect( - 'addressable_flicker', AddressableFlickerEffect, "Addressable Flicker", { - cv.Optional(CONF_UPDATE_INTERVAL, default='16ms'): cv.positive_time_period_milliseconds, - cv.Optional(CONF_INTENSITY, default='5%'): cv.percentage, - } + "addressable_flicker", + AddressableFlickerEffect, + "Addressable Flicker", + { + cv.Optional( + CONF_UPDATE_INTERVAL, default="16ms" + ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_INTENSITY, default="5%"): cv.percentage, + }, ) def addressable_flicker_effect_to_code(config, effect_id): var = cg.new_Pvariable(effect_id, config[CONF_NAME]) @@ -277,22 +432,28 @@ def addressable_flicker_effect_to_code(config, effect_id): def validate_effects(allowed_effects): def validator(value): - value = cv.validate_registry('effect', EFFECTS_REGISTRY)(value) + value = cv.validate_registry("effect", EFFECTS_REGISTRY)(value) errors = [] names = set() for i, x in enumerate(value): key = next(it for it in x.keys()) if key not in allowed_effects: errors.append( - cv.Invalid("The effect '{}' is not allowed for this " - "light type".format(key), [i]) + cv.Invalid( + "The effect '{}' is not allowed for this " + "light type".format(key), + [i], + ) ) continue name = x[key][CONF_NAME] if name in names: errors.append( - cv.Invalid("Found the effect name '{}' twice. All effects must have " - "unique names".format(name), [i]) + cv.Invalid( + "Found the effect name '{}' twice. All effects must have " + "unique names".format(name), + [i], + ) ) continue names.add(name) diff --git a/esphome/components/light/types.py b/esphome/components/light/types.py index 6bcfd5fdb..4bca266b6 100644 --- a/esphome/components/light/types.py +++ b/esphome/components/light/types.py @@ -2,47 +2,62 @@ import esphome.codegen as cg from esphome import automation # Base -light_ns = cg.esphome_ns.namespace('light') -LightState = light_ns.class_('LightState', cg.Nameable, cg.Component) +light_ns = cg.esphome_ns.namespace("light") +LightState = light_ns.class_("LightState", cg.Nameable, cg.Component) # Fake class for addressable lights -AddressableLightState = light_ns.class_('LightState', LightState) -LightOutput = light_ns.class_('LightOutput') -AddressableLight = light_ns.class_('AddressableLight', cg.Component) -AddressableLightRef = AddressableLight.operator('ref') +AddressableLightState = light_ns.class_("LightState", LightState) +LightOutput = light_ns.class_("LightOutput") +AddressableLight = light_ns.class_("AddressableLight", cg.Component) +AddressableLightRef = AddressableLight.operator("ref") -Color = cg.esphome_ns.class_('Color') -LightColorValues = light_ns.class_('LightColorValues') +Color = cg.esphome_ns.class_("Color") +LightColorValues = light_ns.class_("LightColorValues") # Actions -ToggleAction = light_ns.class_('ToggleAction', automation.Action) -LightControlAction = light_ns.class_('LightControlAction', automation.Action) -DimRelativeAction = light_ns.class_('DimRelativeAction', automation.Action) -AddressableSet = light_ns.class_('AddressableSet', automation.Action) -LightIsOnCondition = light_ns.class_('LightIsOnCondition', automation.Condition) -LightIsOffCondition = light_ns.class_('LightIsOffCondition', automation.Condition) +ToggleAction = light_ns.class_("ToggleAction", automation.Action) +LightControlAction = light_ns.class_("LightControlAction", automation.Action) +DimRelativeAction = light_ns.class_("DimRelativeAction", automation.Action) +AddressableSet = light_ns.class_("AddressableSet", automation.Action) +LightIsOnCondition = light_ns.class_("LightIsOnCondition", automation.Condition) +LightIsOffCondition = light_ns.class_("LightIsOffCondition", automation.Condition) # Triggers -LightTurnOnTrigger = light_ns.class_('LightTurnOnTrigger', automation.Trigger.template()) -LightTurnOffTrigger = light_ns.class_('LightTurnOffTrigger', automation.Trigger.template()) +LightTurnOnTrigger = light_ns.class_( + "LightTurnOnTrigger", automation.Trigger.template() +) +LightTurnOffTrigger = light_ns.class_( + "LightTurnOffTrigger", automation.Trigger.template() +) # Effects -LightEffect = light_ns.class_('LightEffect') -RandomLightEffect = light_ns.class_('RandomLightEffect', LightEffect) -LambdaLightEffect = light_ns.class_('LambdaLightEffect', LightEffect) -AutomationLightEffect = light_ns.class_('AutomationLightEffect', LightEffect) -StrobeLightEffect = light_ns.class_('StrobeLightEffect', LightEffect) -StrobeLightEffectColor = light_ns.class_('StrobeLightEffectColor', LightEffect) -FlickerLightEffect = light_ns.class_('FlickerLightEffect', LightEffect) -AddressableLightEffect = light_ns.class_('AddressableLightEffect', LightEffect) -AddressableLambdaLightEffect = light_ns.class_('AddressableLambdaLightEffect', - AddressableLightEffect) -AddressableRainbowLightEffect = light_ns.class_('AddressableRainbowLightEffect', - AddressableLightEffect) -AddressableColorWipeEffect = light_ns.class_('AddressableColorWipeEffect', AddressableLightEffect) -AddressableColorWipeEffectColor = light_ns.struct('AddressableColorWipeEffectColor') -AddressableScanEffect = light_ns.class_('AddressableScanEffect', AddressableLightEffect) -AddressableTwinkleEffect = light_ns.class_('AddressableTwinkleEffect', AddressableLightEffect) -AddressableRandomTwinkleEffect = light_ns.class_('AddressableRandomTwinkleEffect', - AddressableLightEffect) -AddressableFireworksEffect = light_ns.class_('AddressableFireworksEffect', AddressableLightEffect) -AddressableFlickerEffect = light_ns.class_('AddressableFlickerEffect', AddressableLightEffect) +LightEffect = light_ns.class_("LightEffect") +RandomLightEffect = light_ns.class_("RandomLightEffect", LightEffect) +LambdaLightEffect = light_ns.class_("LambdaLightEffect", LightEffect) +AutomationLightEffect = light_ns.class_("AutomationLightEffect", LightEffect) +StrobeLightEffect = light_ns.class_("StrobeLightEffect", LightEffect) +StrobeLightEffectColor = light_ns.class_("StrobeLightEffectColor", LightEffect) +FlickerLightEffect = light_ns.class_("FlickerLightEffect", LightEffect) +AddressableLightEffect = light_ns.class_("AddressableLightEffect", LightEffect) +AddressableLambdaLightEffect = light_ns.class_( + "AddressableLambdaLightEffect", AddressableLightEffect +) +AddressableRainbowLightEffect = light_ns.class_( + "AddressableRainbowLightEffect", AddressableLightEffect +) +AddressableColorWipeEffect = light_ns.class_( + "AddressableColorWipeEffect", AddressableLightEffect +) +AddressableColorWipeEffectColor = light_ns.struct("AddressableColorWipeEffectColor") +AddressableScanEffect = light_ns.class_("AddressableScanEffect", AddressableLightEffect) +AddressableTwinkleEffect = light_ns.class_( + "AddressableTwinkleEffect", AddressableLightEffect +) +AddressableRandomTwinkleEffect = light_ns.class_( + "AddressableRandomTwinkleEffect", AddressableLightEffect +) +AddressableFireworksEffect = light_ns.class_( + "AddressableFireworksEffect", AddressableLightEffect +) +AddressableFlickerEffect = light_ns.class_( + "AddressableFlickerEffect", AddressableLightEffect +) diff --git a/esphome/components/logger/__init__.py b/esphome/components/logger/__init__.py index c447b0eee..5e7383cca 100644 --- a/esphome/components/logger/__init__.py +++ b/esphome/components/logger/__init__.py @@ -4,49 +4,69 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.automation import LambdaAction -from esphome.const import CONF_ARGS, CONF_BAUD_RATE, CONF_FORMAT, CONF_HARDWARE_UART, CONF_ID, \ - CONF_LEVEL, CONF_LOGS, CONF_ON_MESSAGE, CONF_TAG, CONF_TRIGGER_ID, CONF_TX_BUFFER_SIZE +from esphome.const import ( + CONF_ARGS, + CONF_BAUD_RATE, + CONF_FORMAT, + CONF_HARDWARE_UART, + CONF_ID, + CONF_LEVEL, + CONF_LOGS, + CONF_ON_MESSAGE, + CONF_TAG, + CONF_TRIGGER_ID, + CONF_TX_BUFFER_SIZE, +) from esphome.core import CORE, EsphomeError, Lambda, coroutine_with_priority -CODEOWNERS = ['@esphome/core'] -logger_ns = cg.esphome_ns.namespace('logger') +CODEOWNERS = ["@esphome/core"] +logger_ns = cg.esphome_ns.namespace("logger") LOG_LEVELS = { - 'NONE': cg.global_ns.ESPHOME_LOG_LEVEL_NONE, - 'ERROR': cg.global_ns.ESPHOME_LOG_LEVEL_ERROR, - 'WARN': cg.global_ns.ESPHOME_LOG_LEVEL_WARN, - 'INFO': cg.global_ns.ESPHOME_LOG_LEVEL_INFO, - 'DEBUG': cg.global_ns.ESPHOME_LOG_LEVEL_DEBUG, - 'VERBOSE': cg.global_ns.ESPHOME_LOG_LEVEL_VERBOSE, - 'VERY_VERBOSE': cg.global_ns.ESPHOME_LOG_LEVEL_VERY_VERBOSE, + "NONE": cg.global_ns.ESPHOME_LOG_LEVEL_NONE, + "ERROR": cg.global_ns.ESPHOME_LOG_LEVEL_ERROR, + "WARN": cg.global_ns.ESPHOME_LOG_LEVEL_WARN, + "INFO": cg.global_ns.ESPHOME_LOG_LEVEL_INFO, + "DEBUG": cg.global_ns.ESPHOME_LOG_LEVEL_DEBUG, + "VERBOSE": cg.global_ns.ESPHOME_LOG_LEVEL_VERBOSE, + "VERY_VERBOSE": cg.global_ns.ESPHOME_LOG_LEVEL_VERY_VERBOSE, } LOG_LEVEL_TO_ESP_LOG = { - 'ERROR': cg.global_ns.ESP_LOGE, - 'WARN': cg.global_ns.ESP_LOGW, - 'INFO': cg.global_ns.ESP_LOGI, - 'DEBUG': cg.global_ns.ESP_LOGD, - 'VERBOSE': cg.global_ns.ESP_LOGV, - 'VERY_VERBOSE': cg.global_ns.ESP_LOGVV, + "ERROR": cg.global_ns.ESP_LOGE, + "WARN": cg.global_ns.ESP_LOGW, + "INFO": cg.global_ns.ESP_LOGI, + "DEBUG": cg.global_ns.ESP_LOGD, + "VERBOSE": cg.global_ns.ESP_LOGV, + "VERY_VERBOSE": cg.global_ns.ESP_LOGVV, } -LOG_LEVEL_SEVERITY = ['NONE', 'ERROR', 'WARN', 'INFO', 'CONFIG', 'DEBUG', 'VERBOSE', 'VERY_VERBOSE'] +LOG_LEVEL_SEVERITY = [ + "NONE", + "ERROR", + "WARN", + "INFO", + "CONFIG", + "DEBUG", + "VERBOSE", + "VERY_VERBOSE", +] -UART_SELECTION_ESP32 = ['UART0', 'UART1', 'UART2'] +UART_SELECTION_ESP32 = ["UART0", "UART1", "UART2"] -UART_SELECTION_ESP8266 = ['UART0', 'UART0_SWAP', 'UART1'] +UART_SELECTION_ESP8266 = ["UART0", "UART0_SWAP", "UART1"] HARDWARE_UART_TO_UART_SELECTION = { - 'UART0': logger_ns.UART_SELECTION_UART0, - 'UART0_SWAP': logger_ns.UART_SELECTION_UART0_SWAP, - 'UART1': logger_ns.UART_SELECTION_UART1, - 'UART2': logger_ns.UART_SELECTION_UART2, + "UART0": logger_ns.UART_SELECTION_UART0, + "UART0_SWAP": logger_ns.UART_SELECTION_UART0_SWAP, + "UART1": logger_ns.UART_SELECTION_UART1, + "UART2": logger_ns.UART_SELECTION_UART2, } HARDWARE_UART_TO_SERIAL = { - 'UART0': cg.global_ns.Serial, - 'UART0_SWAP': cg.global_ns.Serial, - 'UART1': cg.global_ns.Serial1, - 'UART2': cg.global_ns.Serial2, + "UART0": cg.global_ns.Serial, + "UART0_SWAP": cg.global_ns.Serial, + "UART1": cg.global_ns.Serial1, + "UART2": cg.global_ns.Serial2, } is_log_level = cv.one_of(*LOG_LEVELS, upper=True) @@ -61,45 +81,59 @@ def uart_selection(value): def validate_local_no_higher_than_global(value): - global_level = value.get(CONF_LEVEL, 'DEBUG') + global_level = value.get(CONF_LEVEL, "DEBUG") for tag, level in value.get(CONF_LOGS, {}).items(): if LOG_LEVEL_SEVERITY.index(level) > LOG_LEVEL_SEVERITY.index(global_level): - raise EsphomeError("The local log level {} for {} must be less severe than the " - "global log level {}.".format(level, tag, global_level)) + raise EsphomeError( + "The local log level {} for {} must be less severe than the " + "global log level {}.".format(level, tag, global_level) + ) return value -Logger = logger_ns.class_('Logger', cg.Component) -LoggerMessageTrigger = logger_ns.class_('LoggerMessageTrigger', - automation.Trigger.template(cg.int_, cg.const_char_ptr, - cg.const_char_ptr)) +Logger = logger_ns.class_("Logger", cg.Component) +LoggerMessageTrigger = logger_ns.class_( + "LoggerMessageTrigger", + automation.Trigger.template(cg.int_, cg.const_char_ptr, cg.const_char_ptr), +) -CONF_ESP8266_STORE_LOG_STRINGS_IN_FLASH = 'esp8266_store_log_strings_in_flash' -CONFIG_SCHEMA = cv.All(cv.Schema({ - cv.GenerateID(): cv.declare_id(Logger), - cv.Optional(CONF_BAUD_RATE, default=115200): cv.positive_int, - cv.Optional(CONF_TX_BUFFER_SIZE, default=512): cv.validate_bytes, - cv.Optional(CONF_HARDWARE_UART, default='UART0'): uart_selection, - cv.Optional(CONF_LEVEL, default='DEBUG'): is_log_level, - cv.Optional(CONF_LOGS, default={}): cv.Schema({ - cv.string: is_log_level, - }), - cv.Optional(CONF_ON_MESSAGE): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LoggerMessageTrigger), - cv.Optional(CONF_LEVEL, default='WARN'): is_log_level, - }), - - cv.SplitDefault(CONF_ESP8266_STORE_LOG_STRINGS_IN_FLASH, esp8266=True): - cv.All(cv.only_on_esp8266, cv.boolean), -}).extend(cv.COMPONENT_SCHEMA), validate_local_no_higher_than_global) +CONF_ESP8266_STORE_LOG_STRINGS_IN_FLASH = "esp8266_store_log_strings_in_flash" +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(Logger), + cv.Optional(CONF_BAUD_RATE, default=115200): cv.positive_int, + cv.Optional(CONF_TX_BUFFER_SIZE, default=512): cv.validate_bytes, + cv.Optional(CONF_HARDWARE_UART, default="UART0"): uart_selection, + cv.Optional(CONF_LEVEL, default="DEBUG"): is_log_level, + cv.Optional(CONF_LOGS, default={}): cv.Schema( + { + cv.string: is_log_level, + } + ), + cv.Optional(CONF_ON_MESSAGE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LoggerMessageTrigger), + cv.Optional(CONF_LEVEL, default="WARN"): is_log_level, + } + ), + cv.SplitDefault( + CONF_ESP8266_STORE_LOG_STRINGS_IN_FLASH, esp8266=True + ): cv.All(cv.only_on_esp8266, cv.boolean), + } + ).extend(cv.COMPONENT_SCHEMA), + validate_local_no_higher_than_global, +) @coroutine_with_priority(90.0) def to_code(config): baud_rate = config[CONF_BAUD_RATE] - rhs = Logger.new(baud_rate, - config[CONF_TX_BUFFER_SIZE], - HARDWARE_UART_TO_UART_SELECTION[config[CONF_HARDWARE_UART]]) + rhs = Logger.new( + baud_rate, + config[CONF_TX_BUFFER_SIZE], + HARDWARE_UART_TO_UART_SELECTION[config[CONF_HARDWARE_UART]], + ) log = cg.Pvariable(config[CONF_ID], rhs) cg.add(log.pre_setup()) @@ -107,12 +141,12 @@ def to_code(config): cg.add(log.set_log_level(tag, LOG_LEVELS[level])) level = config[CONF_LEVEL] - cg.add_define('USE_LOGGER') + cg.add_define("USE_LOGGER") this_severity = LOG_LEVEL_SEVERITY.index(level) - cg.add_build_flag('-DESPHOME_LOG_LEVEL={}'.format(LOG_LEVELS[level])) + cg.add_build_flag("-DESPHOME_LOG_LEVEL={}".format(LOG_LEVELS[level])) - verbose_severity = LOG_LEVEL_SEVERITY.index('VERBOSE') - very_verbose_severity = LOG_LEVEL_SEVERITY.index('VERY_VERBOSE') + verbose_severity = LOG_LEVEL_SEVERITY.index("VERBOSE") + very_verbose_severity = LOG_LEVEL_SEVERITY.index("VERY_VERBOSE") is_at_least_verbose = this_severity >= verbose_severity is_at_least_very_verbose = this_severity >= very_verbose_severity has_serial_logging = baud_rate != 0 @@ -122,35 +156,42 @@ def to_code(config): cg.add_build_flag(f"-DDEBUG_ESP_PORT={debug_serial_port}") cg.add_build_flag("-DLWIP_DEBUG") DEBUG_COMPONENTS = { - 'HTTP_CLIENT', - 'HTTP_SERVER', - 'HTTP_UPDATE', - 'OTA', - 'SSL', - 'TLS_MEM', - 'UPDATER', - 'WIFI', + "HTTP_CLIENT", + "HTTP_SERVER", + "HTTP_UPDATE", + "OTA", + "SSL", + "TLS_MEM", + "UPDATER", + "WIFI", # Spams logs too much: # 'MDNS_RESPONDER', } for comp in DEBUG_COMPONENTS: cg.add_build_flag(f"-DDEBUG_ESP_{comp}") if CORE.is_esp32 and is_at_least_verbose: - cg.add_build_flag('-DCORE_DEBUG_LEVEL=5') + cg.add_build_flag("-DCORE_DEBUG_LEVEL=5") if CORE.is_esp32 and is_at_least_very_verbose: - cg.add_build_flag('-DENABLE_I2C_DEBUG_BUFFER') + cg.add_build_flag("-DENABLE_I2C_DEBUG_BUFFER") if config.get(CONF_ESP8266_STORE_LOG_STRINGS_IN_FLASH): - cg.add_build_flag('-DUSE_STORE_LOG_STR_IN_FLASH') + cg.add_build_flag("-DUSE_STORE_LOG_STR_IN_FLASH") # Register at end for safe mode yield cg.register_component(log, config) for conf in config.get(CONF_ON_MESSAGE, []): - trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], log, - LOG_LEVEL_SEVERITY.index(conf[CONF_LEVEL])) - yield automation.build_automation(trigger, [(cg.int_, 'level'), - (cg.const_char_ptr, 'tag'), - (cg.const_char_ptr, 'message')], conf) + trigger = cg.new_Pvariable( + conf[CONF_TRIGGER_ID], log, LOG_LEVEL_SEVERITY.index(conf[CONF_LEVEL]) + ) + yield automation.build_automation( + trigger, + [ + (cg.int_, "level"), + (cg.const_char_ptr, "tag"), + (cg.const_char_ptr, "message"), + ], + conf, + ) def maybe_simple_message(schema): @@ -179,18 +220,27 @@ def validate_printf(value): """ # noqa matches = re.findall(cfmt, value[CONF_FORMAT], flags=re.X) if len(matches) != len(value[CONF_ARGS]): - raise cv.Invalid("Found {} printf-patterns ({}), but {} args were given!" - "".format(len(matches), ', '.join(matches), len(value[CONF_ARGS]))) + raise cv.Invalid( + "Found {} printf-patterns ({}), but {} args were given!" + "".format(len(matches), ", ".join(matches), len(value[CONF_ARGS])) + ) return value -CONF_LOGGER_LOG = 'logger.log' -LOGGER_LOG_ACTION_SCHEMA = cv.All(maybe_simple_message({ - cv.Required(CONF_FORMAT): cv.string, - cv.Optional(CONF_ARGS, default=list): cv.ensure_list(cv.lambda_), - cv.Optional(CONF_LEVEL, default="DEBUG"): cv.one_of(*LOG_LEVEL_TO_ESP_LOG, upper=True), - cv.Optional(CONF_TAG, default="main"): cv.string, -}), validate_printf) +CONF_LOGGER_LOG = "logger.log" +LOGGER_LOG_ACTION_SCHEMA = cv.All( + maybe_simple_message( + { + cv.Required(CONF_FORMAT): cv.string, + cv.Optional(CONF_ARGS, default=list): cv.ensure_list(cv.lambda_), + cv.Optional(CONF_LEVEL, default="DEBUG"): cv.one_of( + *LOG_LEVEL_TO_ESP_LOG, upper=True + ), + cv.Optional(CONF_TAG, default="main"): cv.string, + } + ), + validate_printf, +) @automation.register_action(CONF_LOGGER_LOG, LambdaAction, LOGGER_LOG_ACTION_SCHEMA) diff --git a/esphome/components/max31855/sensor.py b/esphome/components/max31855/sensor.py index 9f105272a..5d3fa461b 100644 --- a/esphome/components/max31855/sensor.py +++ b/esphome/components/max31855/sensor.py @@ -1,18 +1,32 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, spi -from esphome.const import CONF_ID, CONF_REFERENCE_TEMPERATURE, DEVICE_CLASS_TEMPERATURE, \ - ICON_EMPTY, UNIT_CELSIUS +from esphome.const import ( + CONF_ID, + CONF_REFERENCE_TEMPERATURE, + DEVICE_CLASS_TEMPERATURE, + ICON_EMPTY, + UNIT_CELSIUS, +) -max31855_ns = cg.esphome_ns.namespace('max31855') -MAX31855Sensor = max31855_ns.class_('MAX31855Sensor', sensor.Sensor, cg.PollingComponent, - spi.SPIDevice) +max31855_ns = cg.esphome_ns.namespace("max31855") +MAX31855Sensor = max31855_ns.class_( + "MAX31855Sensor", sensor.Sensor, cg.PollingComponent, spi.SPIDevice +) -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE).extend({ - cv.GenerateID(): cv.declare_id(MAX31855Sensor), - cv.Optional(CONF_REFERENCE_TEMPERATURE): - sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 2, DEVICE_CLASS_TEMPERATURE), -}).extend(cv.polling_component_schema('60s')).extend(spi.spi_device_schema()) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE) + .extend( + { + cv.GenerateID(): cv.declare_id(MAX31855Sensor), + cv.Optional(CONF_REFERENCE_TEMPERATURE): sensor.sensor_schema( + UNIT_CELSIUS, ICON_EMPTY, 2, DEVICE_CLASS_TEMPERATURE + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(spi.spi_device_schema()) +) def to_code(config): diff --git a/esphome/components/max31856/sensor.py b/esphome/components/max31856/sensor.py index 95da4e54a..afbb63760 100644 --- a/esphome/components/max31856/sensor.py +++ b/esphome/components/max31856/sensor.py @@ -1,23 +1,38 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, spi -from esphome.const import CONF_ID, CONF_MAINS_FILTER, DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, \ - UNIT_CELSIUS +from esphome.const import ( + CONF_ID, + CONF_MAINS_FILTER, + DEVICE_CLASS_TEMPERATURE, + ICON_EMPTY, + UNIT_CELSIUS, +) -max31856_ns = cg.esphome_ns.namespace('max31856') -MAX31856Sensor = max31856_ns.class_('MAX31856Sensor', sensor.Sensor, cg.PollingComponent, - spi.SPIDevice) +max31856_ns = cg.esphome_ns.namespace("max31856") +MAX31856Sensor = max31856_ns.class_( + "MAX31856Sensor", sensor.Sensor, cg.PollingComponent, spi.SPIDevice +) -MAX31865ConfigFilter = max31856_ns.enum('MAX31856ConfigFilter') +MAX31865ConfigFilter = max31856_ns.enum("MAX31856ConfigFilter") FILTER = { - '50HZ': MAX31865ConfigFilter.FILTER_50HZ, - '60HZ': MAX31865ConfigFilter.FILTER_60HZ, + "50HZ": MAX31865ConfigFilter.FILTER_50HZ, + "60HZ": MAX31865ConfigFilter.FILTER_60HZ, } -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE).extend({ - cv.GenerateID(): cv.declare_id(MAX31856Sensor), - cv.Optional(CONF_MAINS_FILTER, default='60HZ'): cv.enum(FILTER, upper=True, space=''), -}).extend(cv.polling_component_schema('60s')).extend(spi.spi_device_schema()) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE) + .extend( + { + cv.GenerateID(): cv.declare_id(MAX31856Sensor), + cv.Optional(CONF_MAINS_FILTER, default="60HZ"): cv.enum( + FILTER, upper=True, space="" + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(spi.spi_device_schema()) +) def to_code(config): diff --git a/esphome/components/max31865/sensor.py b/esphome/components/max31865/sensor.py index 70913cc8f..bebc42c95 100644 --- a/esphome/components/max31865/sensor.py +++ b/esphome/components/max31865/sensor.py @@ -1,26 +1,48 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, spi -from esphome.const import CONF_ID, CONF_MAINS_FILTER, CONF_REFERENCE_RESISTANCE, \ - CONF_RTD_NOMINAL_RESISTANCE, CONF_RTD_WIRES, DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, UNIT_CELSIUS +from esphome.const import ( + CONF_ID, + CONF_MAINS_FILTER, + CONF_REFERENCE_RESISTANCE, + CONF_RTD_NOMINAL_RESISTANCE, + CONF_RTD_WIRES, + DEVICE_CLASS_TEMPERATURE, + ICON_EMPTY, + UNIT_CELSIUS, +) -max31865_ns = cg.esphome_ns.namespace('max31865') -MAX31865Sensor = max31865_ns.class_('MAX31865Sensor', sensor.Sensor, cg.PollingComponent, - spi.SPIDevice) +max31865_ns = cg.esphome_ns.namespace("max31865") +MAX31865Sensor = max31865_ns.class_( + "MAX31865Sensor", sensor.Sensor, cg.PollingComponent, spi.SPIDevice +) -MAX31865ConfigFilter = max31865_ns.enum('MAX31865ConfigFilter') +MAX31865ConfigFilter = max31865_ns.enum("MAX31865ConfigFilter") FILTER = { - '50HZ': MAX31865ConfigFilter.FILTER_50HZ, - '60HZ': MAX31865ConfigFilter.FILTER_60HZ, + "50HZ": MAX31865ConfigFilter.FILTER_50HZ, + "60HZ": MAX31865ConfigFilter.FILTER_60HZ, } -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 2, DEVICE_CLASS_TEMPERATURE).extend({ - cv.GenerateID(): cv.declare_id(MAX31865Sensor), - cv.Required(CONF_REFERENCE_RESISTANCE): cv.All(cv.resistance, cv.Range(min=100, max=10000)), - cv.Required(CONF_RTD_NOMINAL_RESISTANCE): cv.All(cv.resistance, cv.Range(min=100, max=1000)), - cv.Optional(CONF_MAINS_FILTER, default='60HZ'): cv.enum(FILTER, upper=True, space=''), - cv.Optional(CONF_RTD_WIRES, default=4): cv.int_range(min=2, max=4), -}).extend(cv.polling_component_schema('60s')).extend(spi.spi_device_schema()) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 2, DEVICE_CLASS_TEMPERATURE) + .extend( + { + cv.GenerateID(): cv.declare_id(MAX31865Sensor), + cv.Required(CONF_REFERENCE_RESISTANCE): cv.All( + cv.resistance, cv.Range(min=100, max=10000) + ), + cv.Required(CONF_RTD_NOMINAL_RESISTANCE): cv.All( + cv.resistance, cv.Range(min=100, max=1000) + ), + cv.Optional(CONF_MAINS_FILTER, default="60HZ"): cv.enum( + FILTER, upper=True, space="" + ), + cv.Optional(CONF_RTD_WIRES, default=4): cv.int_range(min=2, max=4), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(spi.spi_device_schema()) +) def to_code(config): diff --git a/esphome/components/max6675/sensor.py b/esphome/components/max6675/sensor.py index f5b537ace..0713654f8 100644 --- a/esphome/components/max6675/sensor.py +++ b/esphome/components/max6675/sensor.py @@ -3,13 +3,21 @@ import esphome.config_validation as cv from esphome.components import sensor, spi from esphome.const import CONF_ID, DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, UNIT_CELSIUS -max6675_ns = cg.esphome_ns.namespace('max6675') -MAX6675Sensor = max6675_ns.class_('MAX6675Sensor', sensor.Sensor, cg.PollingComponent, - spi.SPIDevice) +max6675_ns = cg.esphome_ns.namespace("max6675") +MAX6675Sensor = max6675_ns.class_( + "MAX6675Sensor", sensor.Sensor, cg.PollingComponent, spi.SPIDevice +) -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE).extend({ - cv.GenerateID(): cv.declare_id(MAX6675Sensor), -}).extend(cv.polling_component_schema('60s')).extend(spi.spi_device_schema()) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE) + .extend( + { + cv.GenerateID(): cv.declare_id(MAX6675Sensor), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(spi.spi_device_schema()) +) def to_code(config): diff --git a/esphome/components/max7219/display.py b/esphome/components/max7219/display.py index 05b383004..fba4d7ca7 100644 --- a/esphome/components/max7219/display.py +++ b/esphome/components/max7219/display.py @@ -3,21 +3,28 @@ import esphome.config_validation as cv from esphome.components import display, spi from esphome.const import CONF_ID, CONF_INTENSITY, CONF_LAMBDA, CONF_NUM_CHIPS -DEPENDENCIES = ['spi'] +DEPENDENCIES = ["spi"] -max7219_ns = cg.esphome_ns.namespace('max7219') -MAX7219Component = max7219_ns.class_('MAX7219Component', cg.PollingComponent, spi.SPIDevice) -MAX7219ComponentRef = MAX7219Component.operator('ref') +max7219_ns = cg.esphome_ns.namespace("max7219") +MAX7219Component = max7219_ns.class_( + "MAX7219Component", cg.PollingComponent, spi.SPIDevice +) +MAX7219ComponentRef = MAX7219Component.operator("ref") -CONF_REVERSE_ENABLE = 'reverse_enable' +CONF_REVERSE_ENABLE = "reverse_enable" -CONFIG_SCHEMA = display.BASIC_DISPLAY_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(MAX7219Component), - - cv.Optional(CONF_NUM_CHIPS, default=1): cv.int_range(min=1, max=255), - cv.Optional(CONF_INTENSITY, default=15): cv.int_range(min=0, max=15), - cv.Optional(CONF_REVERSE_ENABLE, default=False): cv.boolean, -}).extend(cv.polling_component_schema('1s')).extend(spi.spi_device_schema()) +CONFIG_SCHEMA = ( + display.BASIC_DISPLAY_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(MAX7219Component), + cv.Optional(CONF_NUM_CHIPS, default=1): cv.int_range(min=1, max=255), + cv.Optional(CONF_INTENSITY, default=15): cv.int_range(min=0, max=15), + cv.Optional(CONF_REVERSE_ENABLE, default=False): cv.boolean, + } + ) + .extend(cv.polling_component_schema("1s")) + .extend(spi.spi_device_schema()) +) def to_code(config): @@ -31,6 +38,7 @@ def to_code(config): cg.add(var.set_reverse(config[CONF_REVERSE_ENABLE])) if CONF_LAMBDA in config: - lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], [(MAX7219ComponentRef, 'it')], - return_type=cg.void) + lambda_ = yield cg.process_lambda( + config[CONF_LAMBDA], [(MAX7219ComponentRef, "it")], return_type=cg.void + ) cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/mcp23008/__init__.py b/esphome/components/mcp23008/__init__.py index 858b37b60..4736765e6 100644 --- a/esphome/components/mcp23008/__init__.py +++ b/esphome/components/mcp23008/__init__.py @@ -2,26 +2,38 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.components import i2c -from esphome.const import CONF_ID, CONF_NUMBER, CONF_MODE, CONF_INVERTED, CONF_OPEN_DRAIN_INTERRUPT +from esphome.const import ( + CONF_ID, + CONF_NUMBER, + CONF_MODE, + CONF_INVERTED, + CONF_OPEN_DRAIN_INTERRUPT, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] MULTI_CONF = True -mcp23008_ns = cg.esphome_ns.namespace('mcp23008') -MCP23008GPIOMode = mcp23008_ns.enum('MCP23008GPIOMode') +mcp23008_ns = cg.esphome_ns.namespace("mcp23008") +MCP23008GPIOMode = mcp23008_ns.enum("MCP23008GPIOMode") MCP23008_GPIO_MODES = { - 'INPUT': MCP23008GPIOMode.MCP23008_INPUT, - 'INPUT_PULLUP': MCP23008GPIOMode.MCP23008_INPUT_PULLUP, - 'OUTPUT': MCP23008GPIOMode.MCP23008_OUTPUT, + "INPUT": MCP23008GPIOMode.MCP23008_INPUT, + "INPUT_PULLUP": MCP23008GPIOMode.MCP23008_INPUT_PULLUP, + "OUTPUT": MCP23008GPIOMode.MCP23008_OUTPUT, } -MCP23008 = mcp23008_ns.class_('MCP23008', cg.Component, i2c.I2CDevice) -MCP23008GPIOPin = mcp23008_ns.class_('MCP23008GPIOPin', cg.GPIOPin) +MCP23008 = mcp23008_ns.class_("MCP23008", cg.Component, i2c.I2CDevice) +MCP23008GPIOPin = mcp23008_ns.class_("MCP23008GPIOPin", cg.GPIOPin) -CONFIG_SCHEMA = cv.Schema({ - cv.Required(CONF_ID): cv.declare_id(MCP23008), - cv.Optional(CONF_OPEN_DRAIN_INTERRUPT, default=False): cv.boolean, -}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x20)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(MCP23008), + cv.Optional(CONF_OPEN_DRAIN_INTERRUPT, default=False): cv.boolean, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x20)) +) def to_code(config): @@ -31,23 +43,34 @@ def to_code(config): cg.add(var.set_open_drain_ints(config[CONF_OPEN_DRAIN_INTERRUPT])) -CONF_MCP23008 = 'mcp23008' -MCP23008_OUTPUT_PIN_SCHEMA = cv.Schema({ - cv.Required(CONF_MCP23008): cv.use_id(MCP23008), - cv.Required(CONF_NUMBER): cv.int_, - cv.Optional(CONF_MODE, default="OUTPUT"): cv.enum(MCP23008_GPIO_MODES, upper=True), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) -MCP23008_INPUT_PIN_SCHEMA = cv.Schema({ - cv.Required(CONF_MCP23008): cv.use_id(MCP23008), - cv.Required(CONF_NUMBER): cv.int_, - cv.Optional(CONF_MODE, default="INPUT"): cv.enum(MCP23008_GPIO_MODES, upper=True), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) +CONF_MCP23008 = "mcp23008" +MCP23008_OUTPUT_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_MCP23008): cv.use_id(MCP23008), + cv.Required(CONF_NUMBER): cv.int_, + cv.Optional(CONF_MODE, default="OUTPUT"): cv.enum( + MCP23008_GPIO_MODES, upper=True + ), + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) +MCP23008_INPUT_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_MCP23008): cv.use_id(MCP23008), + cv.Required(CONF_NUMBER): cv.int_, + cv.Optional(CONF_MODE, default="INPUT"): cv.enum( + MCP23008_GPIO_MODES, upper=True + ), + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) -@pins.PIN_SCHEMA_REGISTRY.register(CONF_MCP23008, - (MCP23008_OUTPUT_PIN_SCHEMA, MCP23008_INPUT_PIN_SCHEMA)) +@pins.PIN_SCHEMA_REGISTRY.register( + CONF_MCP23008, (MCP23008_OUTPUT_PIN_SCHEMA, MCP23008_INPUT_PIN_SCHEMA) +) def mcp23008_pin_to_code(config): parent = yield cg.get_variable(config[CONF_MCP23008]) - yield MCP23008GPIOPin.new(parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED]) + yield MCP23008GPIOPin.new( + parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED] + ) diff --git a/esphome/components/mcp23016/__init__.py b/esphome/components/mcp23016/__init__.py index 93c3d3843..2aa29c9cd 100644 --- a/esphome/components/mcp23016/__init__.py +++ b/esphome/components/mcp23016/__init__.py @@ -4,22 +4,28 @@ from esphome import pins from esphome.components import i2c from esphome.const import CONF_ID, CONF_NUMBER, CONF_MODE, CONF_INVERTED -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] MULTI_CONF = True -mcp23016_ns = cg.esphome_ns.namespace('mcp23016') -MCP23016GPIOMode = mcp23016_ns.enum('MCP23016GPIOMode') +mcp23016_ns = cg.esphome_ns.namespace("mcp23016") +MCP23016GPIOMode = mcp23016_ns.enum("MCP23016GPIOMode") MCP23016_GPIO_MODES = { - 'INPUT': MCP23016GPIOMode.MCP23016_INPUT, - 'OUTPUT': MCP23016GPIOMode.MCP23016_OUTPUT, + "INPUT": MCP23016GPIOMode.MCP23016_INPUT, + "OUTPUT": MCP23016GPIOMode.MCP23016_OUTPUT, } -MCP23016 = mcp23016_ns.class_('MCP23016', cg.Component, i2c.I2CDevice) -MCP23016GPIOPin = mcp23016_ns.class_('MCP23016GPIOPin', cg.GPIOPin) +MCP23016 = mcp23016_ns.class_("MCP23016", cg.Component, i2c.I2CDevice) +MCP23016GPIOPin = mcp23016_ns.class_("MCP23016GPIOPin", cg.GPIOPin) -CONFIG_SCHEMA = cv.Schema({ - cv.Required(CONF_ID): cv.declare_id(MCP23016), -}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x20)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(MCP23016), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x20)) +) def to_code(config): @@ -28,23 +34,34 @@ def to_code(config): yield i2c.register_i2c_device(var, config) -CONF_MCP23016 = 'mcp23016' -MCP23016_OUTPUT_PIN_SCHEMA = cv.Schema({ - cv.Required(CONF_MCP23016): cv.use_id(MCP23016), - cv.Required(CONF_NUMBER): cv.int_, - cv.Optional(CONF_MODE, default="OUTPUT"): cv.enum(MCP23016_GPIO_MODES, upper=True), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) -MCP23016_INPUT_PIN_SCHEMA = cv.Schema({ - cv.Required(CONF_MCP23016): cv.use_id(MCP23016), - cv.Required(CONF_NUMBER): cv.int_, - cv.Optional(CONF_MODE, default="INPUT"): cv.enum(MCP23016_GPIO_MODES, upper=True), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) +CONF_MCP23016 = "mcp23016" +MCP23016_OUTPUT_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_MCP23016): cv.use_id(MCP23016), + cv.Required(CONF_NUMBER): cv.int_, + cv.Optional(CONF_MODE, default="OUTPUT"): cv.enum( + MCP23016_GPIO_MODES, upper=True + ), + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) +MCP23016_INPUT_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_MCP23016): cv.use_id(MCP23016), + cv.Required(CONF_NUMBER): cv.int_, + cv.Optional(CONF_MODE, default="INPUT"): cv.enum( + MCP23016_GPIO_MODES, upper=True + ), + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) -@pins.PIN_SCHEMA_REGISTRY.register(CONF_MCP23016, - (MCP23016_OUTPUT_PIN_SCHEMA, MCP23016_INPUT_PIN_SCHEMA)) +@pins.PIN_SCHEMA_REGISTRY.register( + CONF_MCP23016, (MCP23016_OUTPUT_PIN_SCHEMA, MCP23016_INPUT_PIN_SCHEMA) +) def mcp23016_pin_to_code(config): parent = yield cg.get_variable(config[CONF_MCP23016]) - yield MCP23016GPIOPin.new(parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED]) + yield MCP23016GPIOPin.new( + parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED] + ) diff --git a/esphome/components/mcp23017/__init__.py b/esphome/components/mcp23017/__init__.py index 34f94b293..dae7a6fea 100644 --- a/esphome/components/mcp23017/__init__.py +++ b/esphome/components/mcp23017/__init__.py @@ -2,26 +2,38 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.components import i2c -from esphome.const import CONF_ID, CONF_NUMBER, CONF_MODE, CONF_INVERTED, CONF_OPEN_DRAIN_INTERRUPT +from esphome.const import ( + CONF_ID, + CONF_NUMBER, + CONF_MODE, + CONF_INVERTED, + CONF_OPEN_DRAIN_INTERRUPT, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] MULTI_CONF = True -mcp23017_ns = cg.esphome_ns.namespace('mcp23017') -MCP23017GPIOMode = mcp23017_ns.enum('MCP23017GPIOMode') +mcp23017_ns = cg.esphome_ns.namespace("mcp23017") +MCP23017GPIOMode = mcp23017_ns.enum("MCP23017GPIOMode") MCP23017_GPIO_MODES = { - 'INPUT': MCP23017GPIOMode.MCP23017_INPUT, - 'INPUT_PULLUP': MCP23017GPIOMode.MCP23017_INPUT_PULLUP, - 'OUTPUT': MCP23017GPIOMode.MCP23017_OUTPUT, + "INPUT": MCP23017GPIOMode.MCP23017_INPUT, + "INPUT_PULLUP": MCP23017GPIOMode.MCP23017_INPUT_PULLUP, + "OUTPUT": MCP23017GPIOMode.MCP23017_OUTPUT, } -MCP23017 = mcp23017_ns.class_('MCP23017', cg.Component, i2c.I2CDevice) -MCP23017GPIOPin = mcp23017_ns.class_('MCP23017GPIOPin', cg.GPIOPin) +MCP23017 = mcp23017_ns.class_("MCP23017", cg.Component, i2c.I2CDevice) +MCP23017GPIOPin = mcp23017_ns.class_("MCP23017GPIOPin", cg.GPIOPin) -CONFIG_SCHEMA = cv.Schema({ - cv.Required(CONF_ID): cv.declare_id(MCP23017), - cv.Optional(CONF_OPEN_DRAIN_INTERRUPT, default=False): cv.boolean, -}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x20)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(MCP23017), + cv.Optional(CONF_OPEN_DRAIN_INTERRUPT, default=False): cv.boolean, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x20)) +) def to_code(config): @@ -31,23 +43,34 @@ def to_code(config): cg.add(var.set_open_drain_ints(config[CONF_OPEN_DRAIN_INTERRUPT])) -CONF_MCP23017 = 'mcp23017' -MCP23017_OUTPUT_PIN_SCHEMA = cv.Schema({ - cv.Required(CONF_MCP23017): cv.use_id(MCP23017), - cv.Required(CONF_NUMBER): cv.int_, - cv.Optional(CONF_MODE, default="OUTPUT"): cv.enum(MCP23017_GPIO_MODES, upper=True), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) -MCP23017_INPUT_PIN_SCHEMA = cv.Schema({ - cv.Required(CONF_MCP23017): cv.use_id(MCP23017), - cv.Required(CONF_NUMBER): cv.int_, - cv.Optional(CONF_MODE, default="INPUT"): cv.enum(MCP23017_GPIO_MODES, upper=True), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) +CONF_MCP23017 = "mcp23017" +MCP23017_OUTPUT_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_MCP23017): cv.use_id(MCP23017), + cv.Required(CONF_NUMBER): cv.int_, + cv.Optional(CONF_MODE, default="OUTPUT"): cv.enum( + MCP23017_GPIO_MODES, upper=True + ), + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) +MCP23017_INPUT_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_MCP23017): cv.use_id(MCP23017), + cv.Required(CONF_NUMBER): cv.int_, + cv.Optional(CONF_MODE, default="INPUT"): cv.enum( + MCP23017_GPIO_MODES, upper=True + ), + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) -@pins.PIN_SCHEMA_REGISTRY.register(CONF_MCP23017, - (MCP23017_OUTPUT_PIN_SCHEMA, MCP23017_INPUT_PIN_SCHEMA)) +@pins.PIN_SCHEMA_REGISTRY.register( + CONF_MCP23017, (MCP23017_OUTPUT_PIN_SCHEMA, MCP23017_INPUT_PIN_SCHEMA) +) def mcp23017_pin_to_code(config): parent = yield cg.get_variable(config[CONF_MCP23017]) - yield MCP23017GPIOPin.new(parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED]) + yield MCP23017GPIOPin.new( + parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED] + ) diff --git a/esphome/components/mcp23s08/__init__.py b/esphome/components/mcp23s08/__init__.py index 1440f74f5..b0e047b6b 100644 --- a/esphome/components/mcp23s08/__init__.py +++ b/esphome/components/mcp23s08/__init__.py @@ -4,28 +4,34 @@ from esphome import pins from esphome.components import spi from esphome.const import CONF_ID, CONF_NUMBER, CONF_MODE, CONF_INVERTED -CODEOWNERS = ['@SenexCrenshaw'] +CODEOWNERS = ["@SenexCrenshaw"] -DEPENDENCIES = ['spi'] +DEPENDENCIES = ["spi"] MULTI_CONF = True CONF_DEVICEADDRESS = "deviceaddress" -mcp23S08_ns = cg.esphome_ns.namespace('mcp23s08') -mcp23S08GPIOMode = mcp23S08_ns.enum('MCP23S08GPIOMode') +mcp23S08_ns = cg.esphome_ns.namespace("mcp23s08") +mcp23S08GPIOMode = mcp23S08_ns.enum("MCP23S08GPIOMode") mcp23S08_GPIO_MODES = { - 'INPUT': mcp23S08GPIOMode.MCP23S08_INPUT, - 'INPUT_PULLUP': mcp23S08GPIOMode.MCP23S08_INPUT_PULLUP, - 'OUTPUT': mcp23S08GPIOMode.MCP23S08_OUTPUT, + "INPUT": mcp23S08GPIOMode.MCP23S08_INPUT, + "INPUT_PULLUP": mcp23S08GPIOMode.MCP23S08_INPUT_PULLUP, + "OUTPUT": mcp23S08GPIOMode.MCP23S08_OUTPUT, } -mcp23S08 = mcp23S08_ns.class_('MCP23S08', cg.Component, spi.SPIDevice) -mcp23S08GPIOPin = mcp23S08_ns.class_('MCP23S08GPIOPin', cg.GPIOPin) +mcp23S08 = mcp23S08_ns.class_("MCP23S08", cg.Component, spi.SPIDevice) +mcp23S08GPIOPin = mcp23S08_ns.class_("MCP23S08GPIOPin", cg.GPIOPin) -CONFIG_SCHEMA = cv.Schema({ - cv.Required(CONF_ID): cv.declare_id(mcp23S08), - cv.Optional(CONF_DEVICEADDRESS, default=0): cv.uint8_t, -}).extend(cv.COMPONENT_SCHEMA).extend(spi.spi_device_schema()) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(mcp23S08), + cv.Optional(CONF_DEVICEADDRESS, default=0): cv.uint8_t, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(spi.spi_device_schema()) +) def to_code(config): @@ -35,24 +41,35 @@ def to_code(config): yield spi.register_spi_device(var, config) -CONF_MCP23S08 = 'mcp23s08' +CONF_MCP23S08 = "mcp23s08" -mcp23S08_OUTPUT_PIN_SCHEMA = cv.Schema({ - cv.GenerateID(CONF_MCP23S08): cv.use_id(mcp23S08), - cv.Required(CONF_NUMBER): cv.int_, - cv.Optional(CONF_MODE, default="OUTPUT"): cv.enum(mcp23S08_GPIO_MODES, upper=True), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) -mcp23S08_INPUT_PIN_SCHEMA = cv.Schema({ - cv.GenerateID(CONF_MCP23S08): cv.use_id(mcp23S08), - cv.Required(CONF_NUMBER): cv.int_range(0, 7), - cv.Optional(CONF_MODE, default="INPUT"): cv.enum(mcp23S08_GPIO_MODES, upper=True), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) +mcp23S08_OUTPUT_PIN_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_MCP23S08): cv.use_id(mcp23S08), + cv.Required(CONF_NUMBER): cv.int_, + cv.Optional(CONF_MODE, default="OUTPUT"): cv.enum( + mcp23S08_GPIO_MODES, upper=True + ), + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) +mcp23S08_INPUT_PIN_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_MCP23S08): cv.use_id(mcp23S08), + cv.Required(CONF_NUMBER): cv.int_range(0, 7), + cv.Optional(CONF_MODE, default="INPUT"): cv.enum( + mcp23S08_GPIO_MODES, upper=True + ), + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) -@pins.PIN_SCHEMA_REGISTRY.register(CONF_MCP23S08, - (mcp23S08_OUTPUT_PIN_SCHEMA, mcp23S08_INPUT_PIN_SCHEMA)) +@pins.PIN_SCHEMA_REGISTRY.register( + CONF_MCP23S08, (mcp23S08_OUTPUT_PIN_SCHEMA, mcp23S08_INPUT_PIN_SCHEMA) +) def mcp23S08_pin_to_code(config): parent = yield cg.get_variable(config[CONF_MCP23S08]) - yield mcp23S08GPIOPin.new(parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED]) + yield mcp23S08GPIOPin.new( + parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED] + ) diff --git a/esphome/components/mcp23s17/__init__.py b/esphome/components/mcp23s17/__init__.py index c0c06d495..85f22874a 100644 --- a/esphome/components/mcp23s17/__init__.py +++ b/esphome/components/mcp23s17/__init__.py @@ -4,28 +4,34 @@ from esphome import pins from esphome.components import spi from esphome.const import CONF_ID, CONF_NUMBER, CONF_MODE, CONF_INVERTED -CODEOWNERS = ['@SenexCrenshaw'] +CODEOWNERS = ["@SenexCrenshaw"] -DEPENDENCIES = ['spi'] +DEPENDENCIES = ["spi"] MULTI_CONF = True CONF_DEVICEADDRESS = "deviceaddress" -mcp23S17_ns = cg.esphome_ns.namespace('mcp23s17') -mcp23S17GPIOMode = mcp23S17_ns.enum('MCP23S17GPIOMode') +mcp23S17_ns = cg.esphome_ns.namespace("mcp23s17") +mcp23S17GPIOMode = mcp23S17_ns.enum("MCP23S17GPIOMode") mcp23S17_GPIO_MODES = { - 'INPUT': mcp23S17GPIOMode.MCP23S17_INPUT, - 'INPUT_PULLUP': mcp23S17GPIOMode.MCP23S17_INPUT_PULLUP, - 'OUTPUT': mcp23S17GPIOMode.MCP23S17_OUTPUT, + "INPUT": mcp23S17GPIOMode.MCP23S17_INPUT, + "INPUT_PULLUP": mcp23S17GPIOMode.MCP23S17_INPUT_PULLUP, + "OUTPUT": mcp23S17GPIOMode.MCP23S17_OUTPUT, } -mcp23S17 = mcp23S17_ns.class_('MCP23S17', cg.Component, spi.SPIDevice) -mcp23S17GPIOPin = mcp23S17_ns.class_('MCP23S17GPIOPin', cg.GPIOPin) +mcp23S17 = mcp23S17_ns.class_("MCP23S17", cg.Component, spi.SPIDevice) +mcp23S17GPIOPin = mcp23S17_ns.class_("MCP23S17GPIOPin", cg.GPIOPin) -CONFIG_SCHEMA = cv.Schema({ - cv.Required(CONF_ID): cv.declare_id(mcp23S17), - cv.Optional(CONF_DEVICEADDRESS, default=0): cv.uint8_t, -}).extend(cv.COMPONENT_SCHEMA).extend(spi.spi_device_schema()) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(mcp23S17), + cv.Optional(CONF_DEVICEADDRESS, default=0): cv.uint8_t, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(spi.spi_device_schema()) +) def to_code(config): @@ -35,24 +41,35 @@ def to_code(config): yield spi.register_spi_device(var, config) -CONF_MCP23S17 = 'mcp23s17' +CONF_MCP23S17 = "mcp23s17" -mcp23S17_OUTPUT_PIN_SCHEMA = cv.Schema({ - cv.GenerateID(CONF_MCP23S17): cv.use_id(mcp23S17), - cv.Required(CONF_NUMBER): cv.int_, - cv.Optional(CONF_MODE, default="OUTPUT"): cv.enum(mcp23S17_GPIO_MODES, upper=True), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) -mcp23S17_INPUT_PIN_SCHEMA = cv.Schema({ - cv.Required(CONF_MCP23S17): cv.use_id(mcp23S17), - cv.Required(CONF_NUMBER): cv.int_range(0, 15), - cv.Optional(CONF_MODE, default="INPUT"): cv.enum(mcp23S17_GPIO_MODES, upper=True), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) +mcp23S17_OUTPUT_PIN_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_MCP23S17): cv.use_id(mcp23S17), + cv.Required(CONF_NUMBER): cv.int_, + cv.Optional(CONF_MODE, default="OUTPUT"): cv.enum( + mcp23S17_GPIO_MODES, upper=True + ), + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) +mcp23S17_INPUT_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_MCP23S17): cv.use_id(mcp23S17), + cv.Required(CONF_NUMBER): cv.int_range(0, 15), + cv.Optional(CONF_MODE, default="INPUT"): cv.enum( + mcp23S17_GPIO_MODES, upper=True + ), + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) -@pins.PIN_SCHEMA_REGISTRY.register(CONF_MCP23S17, - (mcp23S17_OUTPUT_PIN_SCHEMA, mcp23S17_INPUT_PIN_SCHEMA)) +@pins.PIN_SCHEMA_REGISTRY.register( + CONF_MCP23S17, (mcp23S17_OUTPUT_PIN_SCHEMA, mcp23S17_INPUT_PIN_SCHEMA) +) def mcp23S17_pin_to_code(config): parent = yield cg.get_variable(config[CONF_MCP23S17]) - yield mcp23S17GPIOPin.new(parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED]) + yield mcp23S17GPIOPin.new( + parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED] + ) diff --git a/esphome/components/mcp2515/canbus.py b/esphome/components/mcp2515/canbus.py index a877507e3..68e28d45b 100644 --- a/esphome/components/mcp2515/canbus.py +++ b/esphome/components/mcp2515/canbus.py @@ -4,33 +4,35 @@ from esphome.components import spi, canbus from esphome.const import CONF_ID, CONF_MODE from esphome.components.canbus import CanbusComponent -CODEOWNERS = ['@mvturnho', '@danielschramm'] -DEPENDENCIES = ['spi'] +CODEOWNERS = ["@mvturnho", "@danielschramm"] +DEPENDENCIES = ["spi"] -CONF_CLOCK = 'clock' +CONF_CLOCK = "clock" -mcp2515_ns = cg.esphome_ns.namespace('mcp2515') -mcp2515 = mcp2515_ns.class_('MCP2515', CanbusComponent, spi.SPIDevice) -CanClock = mcp2515_ns.enum('CAN_CLOCK') -McpMode = mcp2515_ns.enum('CANCTRL_REQOP_MODE') +mcp2515_ns = cg.esphome_ns.namespace("mcp2515") +mcp2515 = mcp2515_ns.class_("MCP2515", CanbusComponent, spi.SPIDevice) +CanClock = mcp2515_ns.enum("CAN_CLOCK") +McpMode = mcp2515_ns.enum("CANCTRL_REQOP_MODE") CAN_CLOCK = { - '8MHZ': CanClock.MCP_8MHZ, - '16MHZ': CanClock.MCP_16MHZ, - '20MHZ': CanClock.MCP_20MHZ, + "8MHZ": CanClock.MCP_8MHZ, + "16MHZ": CanClock.MCP_16MHZ, + "20MHZ": CanClock.MCP_20MHZ, } MCP_MODE = { - 'NORMAL': McpMode.CANCTRL_REQOP_NORMAL, - 'LOOPBACK': McpMode.CANCTRL_REQOP_LOOPBACK, - 'LISTENONLY': McpMode.CANCTRL_REQOP_LISTENONLY, + "NORMAL": McpMode.CANCTRL_REQOP_NORMAL, + "LOOPBACK": McpMode.CANCTRL_REQOP_LOOPBACK, + "LISTENONLY": McpMode.CANCTRL_REQOP_LISTENONLY, } -CONFIG_SCHEMA = canbus.CONFIG_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(mcp2515), - cv.Optional(CONF_CLOCK, default='8MHZ'): cv.enum(CAN_CLOCK, upper=True), - cv.Optional(CONF_MODE, default='NORMAL'): cv.enum(MCP_MODE, upper=True), -}).extend(spi.spi_device_schema(True)) +CONFIG_SCHEMA = canbus.CONFIG_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(mcp2515), + cv.Optional(CONF_CLOCK, default="8MHZ"): cv.enum(CAN_CLOCK, upper=True), + cv.Optional(CONF_MODE, default="NORMAL"): cv.enum(MCP_MODE, upper=True), + } +).extend(spi.spi_device_schema(True)) def to_code(config): diff --git a/esphome/components/mcp3008/__init__.py b/esphome/components/mcp3008/__init__.py index acacc9615..6a0410a75 100644 --- a/esphome/components/mcp3008/__init__.py +++ b/esphome/components/mcp3008/__init__.py @@ -3,18 +3,20 @@ import esphome.config_validation as cv from esphome.components import spi from esphome.const import CONF_ID -DEPENDENCIES = ['spi'] -AUTO_LOAD = ['sensor'] +DEPENDENCIES = ["spi"] +AUTO_LOAD = ["sensor"] MULTI_CONF = True -CONF_MCP3008 = 'mcp3008' +CONF_MCP3008 = "mcp3008" -mcp3008_ns = cg.esphome_ns.namespace('mcp3008') -MCP3008 = mcp3008_ns.class_('MCP3008', cg.Component, spi.SPIDevice) +mcp3008_ns = cg.esphome_ns.namespace("mcp3008") +MCP3008 = mcp3008_ns.class_("MCP3008", cg.Component, spi.SPIDevice) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(MCP3008), -}).extend(spi.spi_device_schema(cs_pin_required=True)) +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(MCP3008), + } +).extend(spi.spi_device_schema(cs_pin_required=True)) def to_code(config): diff --git a/esphome/components/mcp3008/sensor.py b/esphome/components/mcp3008/sensor.py index 9248d51a4..b14615855 100644 --- a/esphome/components/mcp3008/sensor.py +++ b/esphome/components/mcp3008/sensor.py @@ -4,26 +4,34 @@ from esphome.components import sensor, voltage_sampler from esphome.const import CONF_ID, CONF_NUMBER, CONF_NAME from . import mcp3008_ns, MCP3008 -AUTO_LOAD = ['voltage_sampler'] +AUTO_LOAD = ["voltage_sampler"] -DEPENDENCIES = ['mcp3008'] +DEPENDENCIES = ["mcp3008"] -MCP3008Sensor = mcp3008_ns.class_('MCP3008Sensor', sensor.Sensor, cg.PollingComponent, - voltage_sampler.VoltageSampler) -CONF_REFERENCE_VOLTAGE = 'reference_voltage' -CONF_MCP3008_ID = 'mcp3008_id' +MCP3008Sensor = mcp3008_ns.class_( + "MCP3008Sensor", sensor.Sensor, cg.PollingComponent, voltage_sampler.VoltageSampler +) +CONF_REFERENCE_VOLTAGE = "reference_voltage" +CONF_MCP3008_ID = "mcp3008_id" -CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(MCP3008Sensor), - cv.GenerateID(CONF_MCP3008_ID): cv.use_id(MCP3008), - cv.Required(CONF_NUMBER): cv.int_, - cv.Optional(CONF_REFERENCE_VOLTAGE, default='3.3V'): cv.voltage, -}).extend(cv.polling_component_schema('1s')) +CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(MCP3008Sensor), + cv.GenerateID(CONF_MCP3008_ID): cv.use_id(MCP3008), + cv.Required(CONF_NUMBER): cv.int_, + cv.Optional(CONF_REFERENCE_VOLTAGE, default="3.3V"): cv.voltage, + } +).extend(cv.polling_component_schema("1s")) def to_code(config): parent = yield cg.get_variable(config[CONF_MCP3008_ID]) - var = cg.new_Pvariable(config[CONF_ID], parent, config[CONF_NAME], - config[CONF_NUMBER], config[CONF_REFERENCE_VOLTAGE]) + var = cg.new_Pvariable( + config[CONF_ID], + parent, + config[CONF_NAME], + config[CONF_NUMBER], + config[CONF_REFERENCE_VOLTAGE], + ) yield cg.register_component(var, config) yield sensor.register_sensor(var, config) diff --git a/esphome/components/mcp4725/output.py b/esphome/components/mcp4725/output.py index f9593db1f..a010ca997 100644 --- a/esphome/components/mcp4725/output.py +++ b/esphome/components/mcp4725/output.py @@ -3,14 +3,20 @@ import esphome.codegen as cg from esphome.components import output, i2c from esphome.const import CONF_ID -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -mcp4725 = cg.esphome_ns.namespace('mcp4725') -MCP4725 = mcp4725.class_('MCP4725', output.FloatOutput, cg.Component, i2c.I2CDevice) +mcp4725 = cg.esphome_ns.namespace("mcp4725") +MCP4725 = mcp4725.class_("MCP4725", output.FloatOutput, cg.Component, i2c.I2CDevice) -CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend({ - cv.Required(CONF_ID): cv.declare_id(MCP4725), -}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x60)) +CONFIG_SCHEMA = ( + output.FLOAT_OUTPUT_SCHEMA.extend( + { + cv.Required(CONF_ID): cv.declare_id(MCP4725), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x60)) +) def to_code(config): diff --git a/esphome/components/mcp9808/sensor.py b/esphome/components/mcp9808/sensor.py index 0489dd5e1..4973d41ff 100644 --- a/esphome/components/mcp9808/sensor.py +++ b/esphome/components/mcp9808/sensor.py @@ -3,16 +3,24 @@ import esphome.config_validation as cv from esphome.components import i2c, sensor from esphome.const import CONF_ID, DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, UNIT_CELSIUS -CODEOWNERS = ['@k7hpn'] -DEPENDENCIES = ['i2c'] +CODEOWNERS = ["@k7hpn"] +DEPENDENCIES = ["i2c"] -mcp9808_ns = cg.esphome_ns.namespace('mcp9808') -MCP9808Sensor = mcp9808_ns.class_('MCP9808Sensor', sensor.Sensor, cg.PollingComponent, - i2c.I2CDevice) +mcp9808_ns = cg.esphome_ns.namespace("mcp9808") +MCP9808Sensor = mcp9808_ns.class_( + "MCP9808Sensor", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice +) -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE).extend({ - cv.GenerateID(): cv.declare_id(MCP9808Sensor), -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x18)) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE) + .extend( + { + cv.GenerateID(): cv.declare_id(MCP9808Sensor), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x18)) +) def to_code(config): diff --git a/esphome/components/mhz19/sensor.py b/esphome/components/mhz19/sensor.py index aa7db6b77..6989814ad 100644 --- a/esphome/components/mhz19/sensor.py +++ b/esphome/components/mhz19/sensor.py @@ -3,27 +3,46 @@ import esphome.config_validation as cv from esphome import automation from esphome.automation import maybe_simple_id from esphome.components import sensor, uart -from esphome.const import CONF_CO2, CONF_ID, CONF_TEMPERATURE, DEVICE_CLASS_EMPTY, \ - DEVICE_CLASS_TEMPERATURE, ICON_MOLECULE_CO2, UNIT_PARTS_PER_MILLION, UNIT_CELSIUS, ICON_EMPTY +from esphome.const import ( + CONF_CO2, + CONF_ID, + CONF_TEMPERATURE, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_TEMPERATURE, + ICON_MOLECULE_CO2, + UNIT_PARTS_PER_MILLION, + UNIT_CELSIUS, + ICON_EMPTY, +) -DEPENDENCIES = ['uart'] +DEPENDENCIES = ["uart"] -CONF_AUTOMATIC_BASELINE_CALIBRATION = 'automatic_baseline_calibration' +CONF_AUTOMATIC_BASELINE_CALIBRATION = "automatic_baseline_calibration" -mhz19_ns = cg.esphome_ns.namespace('mhz19') -MHZ19Component = mhz19_ns.class_('MHZ19Component', cg.PollingComponent, uart.UARTDevice) -MHZ19CalibrateZeroAction = mhz19_ns.class_('MHZ19CalibrateZeroAction', automation.Action) -MHZ19ABCEnableAction = mhz19_ns.class_('MHZ19ABCEnableAction', automation.Action) -MHZ19ABCDisableAction = mhz19_ns.class_('MHZ19ABCDisableAction', automation.Action) +mhz19_ns = cg.esphome_ns.namespace("mhz19") +MHZ19Component = mhz19_ns.class_("MHZ19Component", cg.PollingComponent, uart.UARTDevice) +MHZ19CalibrateZeroAction = mhz19_ns.class_( + "MHZ19CalibrateZeroAction", automation.Action +) +MHZ19ABCEnableAction = mhz19_ns.class_("MHZ19ABCEnableAction", automation.Action) +MHZ19ABCDisableAction = mhz19_ns.class_("MHZ19ABCDisableAction", automation.Action) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(MHZ19Component), - cv.Required(CONF_CO2): sensor.sensor_schema( - UNIT_PARTS_PER_MILLION, ICON_MOLECULE_CO2, 0, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( - UNIT_CELSIUS, ICON_EMPTY, 0, DEVICE_CLASS_TEMPERATURE), - cv.Optional(CONF_AUTOMATIC_BASELINE_CALIBRATION): cv.boolean, -}).extend(cv.polling_component_schema('60s')).extend(uart.UART_DEVICE_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(MHZ19Component), + cv.Required(CONF_CO2): sensor.sensor_schema( + UNIT_PARTS_PER_MILLION, ICON_MOLECULE_CO2, 0, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( + UNIT_CELSIUS, ICON_EMPTY, 0, DEVICE_CLASS_TEMPERATURE + ), + cv.Optional(CONF_AUTOMATIC_BASELINE_CALIBRATION): cv.boolean, + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(uart.UART_DEVICE_SCHEMA) +) def to_code(config): @@ -43,17 +62,22 @@ def to_code(config): cg.add(var.set_abc_enabled(config[CONF_AUTOMATIC_BASELINE_CALIBRATION])) -CALIBRATION_ACTION_SCHEMA = maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(MHZ19Component), -}) +CALIBRATION_ACTION_SCHEMA = maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(MHZ19Component), + } +) -@automation.register_action('mhz19.calibrate_zero', MHZ19CalibrateZeroAction, - CALIBRATION_ACTION_SCHEMA) -@automation.register_action('mhz19.abc_enable', MHZ19ABCEnableAction, - CALIBRATION_ACTION_SCHEMA) -@automation.register_action('mhz19.abc_disable', MHZ19ABCDisableAction, - CALIBRATION_ACTION_SCHEMA) +@automation.register_action( + "mhz19.calibrate_zero", MHZ19CalibrateZeroAction, CALIBRATION_ACTION_SCHEMA +) +@automation.register_action( + "mhz19.abc_enable", MHZ19ABCEnableAction, CALIBRATION_ACTION_SCHEMA +) +@automation.register_action( + "mhz19.abc_disable", MHZ19ABCDisableAction, CALIBRATION_ACTION_SCHEMA +) def mhz19_calibration_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) diff --git a/esphome/components/mitsubishi/climate.py b/esphome/components/mitsubishi/climate.py index 933e53baf..c08baf7e5 100644 --- a/esphome/components/mitsubishi/climate.py +++ b/esphome/components/mitsubishi/climate.py @@ -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"] -mitsubishi_ns = cg.esphome_ns.namespace('mitsubishi') -MitsubishiClimate = mitsubishi_ns.class_('MitsubishiClimate', climate_ir.ClimateIR) +mitsubishi_ns = cg.esphome_ns.namespace("mitsubishi") +MitsubishiClimate = mitsubishi_ns.class_("MitsubishiClimate", climate_ir.ClimateIR) -CONFIG_SCHEMA = climate_ir.CLIMATE_IR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(MitsubishiClimate), -}) +CONFIG_SCHEMA = climate_ir.CLIMATE_IR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(MitsubishiClimate), + } +) def to_code(config): diff --git a/esphome/components/modbus/__init__.py b/esphome/components/modbus/__init__.py index cada83590..e71f196fc 100644 --- a/esphome/components/modbus/__init__.py +++ b/esphome/components/modbus/__init__.py @@ -4,17 +4,23 @@ from esphome.components import uart from esphome.const import CONF_ID, CONF_ADDRESS from esphome.core import coroutine -DEPENDENCIES = ['uart'] +DEPENDENCIES = ["uart"] -modbus_ns = cg.esphome_ns.namespace('modbus') -Modbus = modbus_ns.class_('Modbus', cg.Component, uart.UARTDevice) -ModbusDevice = modbus_ns.class_('ModbusDevice') +modbus_ns = cg.esphome_ns.namespace("modbus") +Modbus = modbus_ns.class_("Modbus", cg.Component, uart.UARTDevice) +ModbusDevice = modbus_ns.class_("ModbusDevice") MULTI_CONF = True -CONF_MODBUS_ID = 'modbus_id' -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(Modbus), -}).extend(cv.COMPONENT_SCHEMA).extend(uart.UART_DEVICE_SCHEMA) +CONF_MODBUS_ID = "modbus_id" +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(Modbus), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(uart.UART_DEVICE_SCHEMA) +) def to_code(config): diff --git a/esphome/components/monochromatic/light.py b/esphome/components/monochromatic/light.py index 79faacff6..32d9981a5 100644 --- a/esphome/components/monochromatic/light.py +++ b/esphome/components/monochromatic/light.py @@ -3,13 +3,17 @@ import esphome.config_validation as cv from esphome.components import light, output from esphome.const import CONF_OUTPUT_ID, CONF_OUTPUT -monochromatic_ns = cg.esphome_ns.namespace('monochromatic') -MonochromaticLightOutput = monochromatic_ns.class_('MonochromaticLightOutput', light.LightOutput) +monochromatic_ns = cg.esphome_ns.namespace("monochromatic") +MonochromaticLightOutput = monochromatic_ns.class_( + "MonochromaticLightOutput", light.LightOutput +) -CONFIG_SCHEMA = light.BRIGHTNESS_ONLY_LIGHT_SCHEMA.extend({ - cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(MonochromaticLightOutput), - cv.Required(CONF_OUTPUT): cv.use_id(output.FloatOutput), -}) +CONFIG_SCHEMA = light.BRIGHTNESS_ONLY_LIGHT_SCHEMA.extend( + { + cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(MonochromaticLightOutput), + cv.Required(CONF_OUTPUT): cv.use_id(output.FloatOutput), + } +) def to_code(config): diff --git a/esphome/components/mpr121/__init__.py b/esphome/components/mpr121/__init__.py index b1ef9eaef..eb3043c2b 100644 --- a/esphome/components/mpr121/__init__.py +++ b/esphome/components/mpr121/__init__.py @@ -8,21 +8,31 @@ CONF_RELEASE_THRESHOLD = "release_threshold" CONF_TOUCH_DEBOUNCE = "touch_debounce" CONF_RELEASE_DEBOUNCE = "release_debounce" -DEPENDENCIES = ['i2c'] -AUTO_LOAD = ['binary_sensor'] +DEPENDENCIES = ["i2c"] +AUTO_LOAD = ["binary_sensor"] -mpr121_ns = cg.esphome_ns.namespace('mpr121') -CONF_MPR121_ID = 'mpr121_id' -MPR121Component = mpr121_ns.class_('MPR121Component', cg.Component, i2c.I2CDevice) +mpr121_ns = cg.esphome_ns.namespace("mpr121") +CONF_MPR121_ID = "mpr121_id" +MPR121Component = mpr121_ns.class_("MPR121Component", cg.Component, i2c.I2CDevice) MULTI_CONF = True -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(MPR121Component), - cv.Optional(CONF_RELEASE_DEBOUNCE, default=0): cv.int_range(min=0, max=7), - cv.Optional(CONF_TOUCH_DEBOUNCE, default=0): cv.int_range(min=0, max=7), - cv.Optional(CONF_TOUCH_THRESHOLD, default=0x0b): cv.int_range(min=0x05, max=0x30), - cv.Optional(CONF_RELEASE_THRESHOLD, default=0x06): cv.int_range(min=0x05, max=0x30), -}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x5A)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(MPR121Component), + cv.Optional(CONF_RELEASE_DEBOUNCE, default=0): cv.int_range(min=0, max=7), + cv.Optional(CONF_TOUCH_DEBOUNCE, default=0): cv.int_range(min=0, max=7), + cv.Optional(CONF_TOUCH_THRESHOLD, default=0x0B): cv.int_range( + min=0x05, max=0x30 + ), + cv.Optional(CONF_RELEASE_THRESHOLD, default=0x06): cv.int_range( + min=0x05, max=0x30 + ), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x5A)) +) def to_code(config): diff --git a/esphome/components/mpr121/binary_sensor.py b/esphome/components/mpr121/binary_sensor.py index dddfeb40e..68e56075f 100644 --- a/esphome/components/mpr121/binary_sensor.py +++ b/esphome/components/mpr121/binary_sensor.py @@ -2,19 +2,26 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import binary_sensor from esphome.const import CONF_CHANNEL, CONF_ID -from . import mpr121_ns, MPR121Component, CONF_MPR121_ID, CONF_TOUCH_THRESHOLD, \ - CONF_RELEASE_THRESHOLD +from . import ( + mpr121_ns, + MPR121Component, + CONF_MPR121_ID, + CONF_TOUCH_THRESHOLD, + CONF_RELEASE_THRESHOLD, +) -DEPENDENCIES = ['mpr121'] -MPR121Channel = mpr121_ns.class_('MPR121Channel', binary_sensor.BinarySensor) +DEPENDENCIES = ["mpr121"] +MPR121Channel = mpr121_ns.class_("MPR121Channel", binary_sensor.BinarySensor) -CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(MPR121Channel), - cv.GenerateID(CONF_MPR121_ID): cv.use_id(MPR121Component), - cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=11), - cv.Optional(CONF_TOUCH_THRESHOLD): cv.int_range(min=0x05, max=0x30), - cv.Optional(CONF_RELEASE_THRESHOLD): cv.int_range(min=0x05, max=0x30), -}) +CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(MPR121Channel), + cv.GenerateID(CONF_MPR121_ID): cv.use_id(MPR121Component), + cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=11), + cv.Optional(CONF_TOUCH_THRESHOLD): cv.int_range(min=0x05, max=0x30), + cv.Optional(CONF_RELEASE_THRESHOLD): cv.int_range(min=0x05, max=0x30), + } +) def to_code(config): diff --git a/esphome/components/mpu6050/sensor.py b/esphome/components/mpu6050/sensor.py index 1a02d2ce7..11d491006 100644 --- a/esphome/components/mpu6050/sensor.py +++ b/esphome/components/mpu6050/sensor.py @@ -1,38 +1,59 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, sensor -from esphome.const import CONF_ID, CONF_TEMPERATURE, DEVICE_CLASS_EMPTY, DEVICE_CLASS_TEMPERATURE, \ - ICON_BRIEFCASE_DOWNLOAD, ICON_EMPTY, UNIT_METER_PER_SECOND_SQUARED, \ - ICON_SCREEN_ROTATION, UNIT_DEGREE_PER_SECOND, UNIT_CELSIUS +from esphome.const import ( + CONF_ID, + CONF_TEMPERATURE, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_TEMPERATURE, + ICON_BRIEFCASE_DOWNLOAD, + ICON_EMPTY, + UNIT_METER_PER_SECOND_SQUARED, + ICON_SCREEN_ROTATION, + UNIT_DEGREE_PER_SECOND, + UNIT_CELSIUS, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -CONF_ACCEL_X = 'accel_x' -CONF_ACCEL_Y = 'accel_y' -CONF_ACCEL_Z = 'accel_z' -CONF_GYRO_X = 'gyro_x' -CONF_GYRO_Y = 'gyro_y' -CONF_GYRO_Z = 'gyro_z' +CONF_ACCEL_X = "accel_x" +CONF_ACCEL_Y = "accel_y" +CONF_ACCEL_Z = "accel_z" +CONF_GYRO_X = "gyro_x" +CONF_GYRO_Y = "gyro_y" +CONF_GYRO_Z = "gyro_z" -mpu6050_ns = cg.esphome_ns.namespace('mpu6050') -MPU6050Component = mpu6050_ns.class_('MPU6050Component', cg.PollingComponent, i2c.I2CDevice) +mpu6050_ns = cg.esphome_ns.namespace("mpu6050") +MPU6050Component = mpu6050_ns.class_( + "MPU6050Component", cg.PollingComponent, i2c.I2CDevice +) -accel_schema = sensor.sensor_schema(UNIT_METER_PER_SECOND_SQUARED, ICON_BRIEFCASE_DOWNLOAD, 2, - DEVICE_CLASS_EMPTY) -gyro_schema = sensor.sensor_schema(UNIT_DEGREE_PER_SECOND, ICON_SCREEN_ROTATION, 2, - DEVICE_CLASS_EMPTY) -temperature_schema = sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE) +accel_schema = sensor.sensor_schema( + UNIT_METER_PER_SECOND_SQUARED, ICON_BRIEFCASE_DOWNLOAD, 2, DEVICE_CLASS_EMPTY +) +gyro_schema = sensor.sensor_schema( + UNIT_DEGREE_PER_SECOND, ICON_SCREEN_ROTATION, 2, DEVICE_CLASS_EMPTY +) +temperature_schema = sensor.sensor_schema( + UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(MPU6050Component), - cv.Optional(CONF_ACCEL_X): accel_schema, - cv.Optional(CONF_ACCEL_Y): accel_schema, - cv.Optional(CONF_ACCEL_Z): accel_schema, - cv.Optional(CONF_GYRO_X): gyro_schema, - cv.Optional(CONF_GYRO_Y): gyro_schema, - cv.Optional(CONF_GYRO_Z): gyro_schema, - cv.Optional(CONF_TEMPERATURE): temperature_schema, -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x68)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(MPU6050Component), + cv.Optional(CONF_ACCEL_X): accel_schema, + cv.Optional(CONF_ACCEL_Y): accel_schema, + cv.Optional(CONF_ACCEL_Z): accel_schema, + cv.Optional(CONF_GYRO_X): gyro_schema, + cv.Optional(CONF_GYRO_Y): gyro_schema, + cv.Optional(CONF_GYRO_Z): gyro_schema, + cv.Optional(CONF_TEMPERATURE): temperature_schema, + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x68)) +) def to_code(config): @@ -40,15 +61,15 @@ def to_code(config): yield cg.register_component(var, config) yield i2c.register_i2c_device(var, config) - for d in ['x', 'y', 'z']: - accel_key = f'accel_{d}' + for d in ["x", "y", "z"]: + accel_key = f"accel_{d}" if accel_key in config: sens = yield sensor.new_sensor(config[accel_key]) - cg.add(getattr(var, f'set_accel_{d}_sensor')(sens)) - accel_key = f'gyro_{d}' + cg.add(getattr(var, f"set_accel_{d}_sensor")(sens)) + accel_key = f"gyro_{d}" if accel_key in config: sens = yield sensor.new_sensor(config[accel_key]) - cg.add(getattr(var, f'set_gyro_{d}_sensor')(sens)) + cg.add(getattr(var, f"set_gyro_{d}_sensor")(sens)) if CONF_TEMPERATURE in config: sens = yield sensor.new_sensor(config[CONF_TEMPERATURE]) diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index db99334d0..e90f90cd6 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -5,17 +5,42 @@ import esphome.config_validation as cv from esphome import automation from esphome.automation import Condition from esphome.components import logger -from esphome.const import CONF_AVAILABILITY, CONF_BIRTH_MESSAGE, CONF_BROKER, CONF_CLIENT_ID, \ - CONF_COMMAND_TOPIC, CONF_DISCOVERY, CONF_DISCOVERY_PREFIX, CONF_DISCOVERY_RETAIN, \ - CONF_ID, CONF_KEEPALIVE, CONF_LEVEL, CONF_LOG_TOPIC, CONF_ON_JSON_MESSAGE, CONF_ON_MESSAGE, \ - CONF_PASSWORD, CONF_PAYLOAD, CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_PORT, \ - CONF_QOS, CONF_REBOOT_TIMEOUT, CONF_RETAIN, CONF_SHUTDOWN_MESSAGE, CONF_SSL_FINGERPRINTS, \ - CONF_STATE_TOPIC, CONF_TOPIC, CONF_TOPIC_PREFIX, CONF_TRIGGER_ID, CONF_USERNAME, \ - CONF_WILL_MESSAGE +from esphome.const import ( + CONF_AVAILABILITY, + CONF_BIRTH_MESSAGE, + CONF_BROKER, + CONF_CLIENT_ID, + CONF_COMMAND_TOPIC, + CONF_DISCOVERY, + CONF_DISCOVERY_PREFIX, + CONF_DISCOVERY_RETAIN, + CONF_ID, + CONF_KEEPALIVE, + CONF_LEVEL, + CONF_LOG_TOPIC, + CONF_ON_JSON_MESSAGE, + CONF_ON_MESSAGE, + CONF_PASSWORD, + CONF_PAYLOAD, + CONF_PAYLOAD_AVAILABLE, + CONF_PAYLOAD_NOT_AVAILABLE, + CONF_PORT, + CONF_QOS, + CONF_REBOOT_TIMEOUT, + CONF_RETAIN, + CONF_SHUTDOWN_MESSAGE, + CONF_SSL_FINGERPRINTS, + CONF_STATE_TOPIC, + CONF_TOPIC, + CONF_TOPIC_PREFIX, + CONF_TRIGGER_ID, + CONF_USERNAME, + CONF_WILL_MESSAGE, +) from esphome.core import coroutine_with_priority, coroutine, CORE -DEPENDENCIES = ['network'] -AUTO_LOAD = ['json', 'async_tcp'] +DEPENDENCIES = ["network"] +AUTO_LOAD = ["json", "async_tcp"] def validate_message_just_topic(value): @@ -23,39 +48,49 @@ def validate_message_just_topic(value): return MQTT_MESSAGE_BASE({CONF_TOPIC: value}) -MQTT_MESSAGE_BASE = cv.Schema({ - cv.Required(CONF_TOPIC): cv.publish_topic, - cv.Optional(CONF_QOS, default=0): cv.mqtt_qos, - cv.Optional(CONF_RETAIN, default=True): cv.boolean, -}) +MQTT_MESSAGE_BASE = cv.Schema( + { + cv.Required(CONF_TOPIC): cv.publish_topic, + cv.Optional(CONF_QOS, default=0): cv.mqtt_qos, + cv.Optional(CONF_RETAIN, default=True): cv.boolean, + } +) -MQTT_MESSAGE_TEMPLATE_SCHEMA = cv.Any(None, MQTT_MESSAGE_BASE, validate_message_just_topic) +MQTT_MESSAGE_TEMPLATE_SCHEMA = cv.Any( + None, MQTT_MESSAGE_BASE, validate_message_just_topic +) -MQTT_MESSAGE_SCHEMA = cv.Any(None, MQTT_MESSAGE_BASE.extend({ - cv.Required(CONF_PAYLOAD): cv.mqtt_payload, -})) +MQTT_MESSAGE_SCHEMA = cv.Any( + None, + MQTT_MESSAGE_BASE.extend( + { + cv.Required(CONF_PAYLOAD): cv.mqtt_payload, + } + ), +) -mqtt_ns = cg.esphome_ns.namespace('mqtt') -MQTTMessage = mqtt_ns.struct('MQTTMessage') -MQTTClientComponent = mqtt_ns.class_('MQTTClientComponent', cg.Component) -MQTTPublishAction = mqtt_ns.class_('MQTTPublishAction', automation.Action) -MQTTPublishJsonAction = mqtt_ns.class_('MQTTPublishJsonAction', automation.Action) -MQTTMessageTrigger = mqtt_ns.class_('MQTTMessageTrigger', - automation.Trigger.template(cg.std_string), - cg.Component) -MQTTJsonMessageTrigger = mqtt_ns.class_('MQTTJsonMessageTrigger', - automation.Trigger.template(cg.JsonObjectConstRef)) -MQTTComponent = mqtt_ns.class_('MQTTComponent', cg.Component) -MQTTConnectedCondition = mqtt_ns.class_('MQTTConnectedCondition', Condition) +mqtt_ns = cg.esphome_ns.namespace("mqtt") +MQTTMessage = mqtt_ns.struct("MQTTMessage") +MQTTClientComponent = mqtt_ns.class_("MQTTClientComponent", cg.Component) +MQTTPublishAction = mqtt_ns.class_("MQTTPublishAction", automation.Action) +MQTTPublishJsonAction = mqtt_ns.class_("MQTTPublishJsonAction", automation.Action) +MQTTMessageTrigger = mqtt_ns.class_( + "MQTTMessageTrigger", automation.Trigger.template(cg.std_string), cg.Component +) +MQTTJsonMessageTrigger = mqtt_ns.class_( + "MQTTJsonMessageTrigger", automation.Trigger.template(cg.JsonObjectConstRef) +) +MQTTComponent = mqtt_ns.class_("MQTTComponent", cg.Component) +MQTTConnectedCondition = mqtt_ns.class_("MQTTConnectedCondition", Condition) -MQTTBinarySensorComponent = mqtt_ns.class_('MQTTBinarySensorComponent', MQTTComponent) -MQTTClimateComponent = mqtt_ns.class_('MQTTClimateComponent', MQTTComponent) -MQTTCoverComponent = mqtt_ns.class_('MQTTCoverComponent', MQTTComponent) -MQTTFanComponent = mqtt_ns.class_('MQTTFanComponent', MQTTComponent) -MQTTJSONLightComponent = mqtt_ns.class_('MQTTJSONLightComponent', MQTTComponent) -MQTTSensorComponent = mqtt_ns.class_('MQTTSensorComponent', MQTTComponent) -MQTTSwitchComponent = mqtt_ns.class_('MQTTSwitchComponent', MQTTComponent) -MQTTTextSensor = mqtt_ns.class_('MQTTTextSensor', MQTTComponent) +MQTTBinarySensorComponent = mqtt_ns.class_("MQTTBinarySensorComponent", MQTTComponent) +MQTTClimateComponent = mqtt_ns.class_("MQTTClimateComponent", MQTTComponent) +MQTTCoverComponent = mqtt_ns.class_("MQTTCoverComponent", MQTTComponent) +MQTTFanComponent = mqtt_ns.class_("MQTTFanComponent", MQTTComponent) +MQTTJSONLightComponent = mqtt_ns.class_("MQTTJSONLightComponent", MQTTComponent) +MQTTSensorComponent = mqtt_ns.class_("MQTTSensorComponent", MQTTComponent) +MQTTSwitchComponent = mqtt_ns.class_("MQTTSwitchComponent", MQTTComponent) +MQTTTextSensor = mqtt_ns.class_("MQTTTextSensor", MQTTComponent) def validate_config(value): @@ -64,28 +99,28 @@ def validate_config(value): topic_prefix = value[CONF_TOPIC_PREFIX] if CONF_BIRTH_MESSAGE not in value: out[CONF_BIRTH_MESSAGE] = { - CONF_TOPIC: f'{topic_prefix}/status', - CONF_PAYLOAD: 'online', + CONF_TOPIC: f"{topic_prefix}/status", + CONF_PAYLOAD: "online", CONF_QOS: 0, CONF_RETAIN: True, } if CONF_WILL_MESSAGE not in value: out[CONF_WILL_MESSAGE] = { - CONF_TOPIC: f'{topic_prefix}/status', - CONF_PAYLOAD: 'offline', + CONF_TOPIC: f"{topic_prefix}/status", + CONF_PAYLOAD: "offline", CONF_QOS: 0, CONF_RETAIN: True, } if CONF_SHUTDOWN_MESSAGE not in value: out[CONF_SHUTDOWN_MESSAGE] = { - CONF_TOPIC: f'{topic_prefix}/status', - CONF_PAYLOAD: 'offline', + CONF_TOPIC: f"{topic_prefix}/status", + CONF_PAYLOAD: "offline", CONF_QOS: 0, CONF_RETAIN: True, } if CONF_LOG_TOPIC not in value: out[CONF_LOG_TOPIC] = { - CONF_TOPIC: f'{topic_prefix}/debug', + CONF_TOPIC: f"{topic_prefix}/debug", CONF_QOS: 0, CONF_RETAIN: True, } @@ -94,46 +129,68 @@ def validate_config(value): def validate_fingerprint(value): value = cv.string(value) - if re.match(r'^[0-9a-f]{40}$', value) is None: + if re.match(r"^[0-9a-f]{40}$", value) is None: raise cv.Invalid("fingerprint must be valid SHA1 hash") return value -CONFIG_SCHEMA = cv.All(cv.Schema({ - cv.GenerateID(): cv.declare_id(MQTTClientComponent), - cv.Required(CONF_BROKER): cv.string_strict, - cv.Optional(CONF_PORT, default=1883): cv.port, - cv.Optional(CONF_USERNAME, default=''): cv.string, - cv.Optional(CONF_PASSWORD, default=''): cv.string, - cv.Optional(CONF_CLIENT_ID): cv.string, - cv.Optional(CONF_DISCOVERY, default=True): cv.Any(cv.boolean, cv.one_of("CLEAN", upper=True)), - cv.Optional(CONF_DISCOVERY_RETAIN, default=True): cv.boolean, - cv.Optional(CONF_DISCOVERY_PREFIX, default="homeassistant"): cv.publish_topic, - - cv.Optional(CONF_BIRTH_MESSAGE): MQTT_MESSAGE_SCHEMA, - cv.Optional(CONF_WILL_MESSAGE): MQTT_MESSAGE_SCHEMA, - cv.Optional(CONF_SHUTDOWN_MESSAGE): MQTT_MESSAGE_SCHEMA, - cv.Optional(CONF_TOPIC_PREFIX, default=lambda: CORE.name): cv.publish_topic, - cv.Optional(CONF_LOG_TOPIC): cv.Any(None, MQTT_MESSAGE_BASE.extend({ - cv.Optional(CONF_LEVEL): logger.is_log_level, - }), validate_message_just_topic), - - cv.Optional(CONF_SSL_FINGERPRINTS): cv.All(cv.only_on_esp8266, - cv.ensure_list(validate_fingerprint)), - cv.Optional(CONF_KEEPALIVE, default='15s'): cv.positive_time_period_seconds, - cv.Optional(CONF_REBOOT_TIMEOUT, default='15min'): cv.positive_time_period_milliseconds, - cv.Optional(CONF_ON_MESSAGE): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(MQTTMessageTrigger), - cv.Required(CONF_TOPIC): cv.subscribe_topic, - cv.Optional(CONF_QOS, default=0): cv.mqtt_qos, - cv.Optional(CONF_PAYLOAD): cv.string_strict, - }), - cv.Optional(CONF_ON_JSON_MESSAGE): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(MQTTJsonMessageTrigger), - cv.Required(CONF_TOPIC): cv.subscribe_topic, - cv.Optional(CONF_QOS, default=0): cv.mqtt_qos, - }), -}), validate_config) +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(MQTTClientComponent), + cv.Required(CONF_BROKER): cv.string_strict, + cv.Optional(CONF_PORT, default=1883): cv.port, + cv.Optional(CONF_USERNAME, default=""): cv.string, + cv.Optional(CONF_PASSWORD, default=""): cv.string, + cv.Optional(CONF_CLIENT_ID): cv.string, + cv.Optional(CONF_DISCOVERY, default=True): cv.Any( + cv.boolean, cv.one_of("CLEAN", upper=True) + ), + cv.Optional(CONF_DISCOVERY_RETAIN, default=True): cv.boolean, + cv.Optional( + CONF_DISCOVERY_PREFIX, default="homeassistant" + ): cv.publish_topic, + cv.Optional(CONF_BIRTH_MESSAGE): MQTT_MESSAGE_SCHEMA, + cv.Optional(CONF_WILL_MESSAGE): MQTT_MESSAGE_SCHEMA, + cv.Optional(CONF_SHUTDOWN_MESSAGE): MQTT_MESSAGE_SCHEMA, + cv.Optional(CONF_TOPIC_PREFIX, default=lambda: CORE.name): cv.publish_topic, + cv.Optional(CONF_LOG_TOPIC): cv.Any( + None, + MQTT_MESSAGE_BASE.extend( + { + cv.Optional(CONF_LEVEL): logger.is_log_level, + } + ), + validate_message_just_topic, + ), + cv.Optional(CONF_SSL_FINGERPRINTS): cv.All( + cv.only_on_esp8266, cv.ensure_list(validate_fingerprint) + ), + cv.Optional(CONF_KEEPALIVE, default="15s"): cv.positive_time_period_seconds, + cv.Optional( + CONF_REBOOT_TIMEOUT, default="15min" + ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_ON_MESSAGE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(MQTTMessageTrigger), + cv.Required(CONF_TOPIC): cv.subscribe_topic, + cv.Optional(CONF_QOS, default=0): cv.mqtt_qos, + cv.Optional(CONF_PAYLOAD): cv.string_strict, + } + ), + cv.Optional(CONF_ON_JSON_MESSAGE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + MQTTJsonMessageTrigger + ), + cv.Required(CONF_TOPIC): cv.subscribe_topic, + cv.Optional(CONF_QOS, default=0): cv.mqtt_qos, + } + ), + } + ), + validate_config, +) def exp_mqtt_message(config): @@ -141,10 +198,10 @@ def exp_mqtt_message(config): return cg.optional(cg.TemplateArguments(MQTTMessage)) exp = cg.StructInitializer( MQTTMessage, - ('topic', config[CONF_TOPIC]), - ('payload', config.get(CONF_PAYLOAD, "")), - ('qos', config[CONF_QOS]), - ('retain', config[CONF_RETAIN]) + ("topic", config[CONF_TOPIC]), + ("payload", config.get(CONF_PAYLOAD, "")), + ("qos", config[CONF_QOS]), + ("retain", config[CONF_RETAIN]), ) return exp @@ -155,8 +212,8 @@ def to_code(config): yield cg.register_component(var, config) # https://github.com/OttoWinter/async-mqtt-client/blob/master/library.json - cg.add_library('AsyncMqttClient-esphome', '0.8.4') - cg.add_define('USE_MQTT') + cg.add_library("AsyncMqttClient-esphome", "0.8.4") + cg.add_define("USE_MQTT") cg.add_global(mqtt_ns.using) cg.add(var.set_broker_address(config[CONF_BROKER])) @@ -206,9 +263,12 @@ def to_code(config): if CONF_SSL_FINGERPRINTS in config: for fingerprint in config[CONF_SSL_FINGERPRINTS]: - arr = [cg.RawExpression("0x{}".format(fingerprint[i:i + 2])) for i in range(0, 40, 2)] + arr = [ + cg.RawExpression("0x{}".format(fingerprint[i : i + 2])) + for i in range(0, 40, 2) + ] cg.add(var.add_ssl_fingerprint(arr)) - cg.add_build_flag('-DASYNC_TCP_SSL_ENABLED=1') + cg.add_build_flag("-DASYNC_TCP_SSL_ENABLED=1") cg.add(var.set_keep_alive(config[CONF_KEEPALIVE])) @@ -220,23 +280,27 @@ def to_code(config): if CONF_PAYLOAD in conf: cg.add(trig.set_payload(conf[CONF_PAYLOAD])) yield cg.register_component(trig, conf) - yield automation.build_automation(trig, [(cg.std_string, 'x')], conf) + yield automation.build_automation(trig, [(cg.std_string, "x")], conf) for conf in config.get(CONF_ON_JSON_MESSAGE, []): trig = cg.new_Pvariable(conf[CONF_TRIGGER_ID], conf[CONF_TOPIC], conf[CONF_QOS]) - yield automation.build_automation(trig, [(cg.JsonObjectConstRef, 'x')], conf) + yield automation.build_automation(trig, [(cg.JsonObjectConstRef, "x")], conf) -MQTT_PUBLISH_ACTION_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.use_id(MQTTClientComponent), - cv.Required(CONF_TOPIC): cv.templatable(cv.publish_topic), - cv.Required(CONF_PAYLOAD): cv.templatable(cv.mqtt_payload), - cv.Optional(CONF_QOS, default=0): cv.templatable(cv.mqtt_qos), - cv.Optional(CONF_RETAIN, default=False): cv.templatable(cv.boolean), -}) +MQTT_PUBLISH_ACTION_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.use_id(MQTTClientComponent), + cv.Required(CONF_TOPIC): cv.templatable(cv.publish_topic), + cv.Required(CONF_PAYLOAD): cv.templatable(cv.mqtt_payload), + cv.Optional(CONF_QOS, default=0): cv.templatable(cv.mqtt_qos), + cv.Optional(CONF_RETAIN, default=False): cv.templatable(cv.boolean), + } +) -@automation.register_action('mqtt.publish', MQTTPublishAction, MQTT_PUBLISH_ACTION_SCHEMA) +@automation.register_action( + "mqtt.publish", MQTTPublishAction, MQTT_PUBLISH_ACTION_SCHEMA +) def mqtt_publish_action_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) @@ -252,24 +316,27 @@ def mqtt_publish_action_to_code(config, action_id, template_arg, args): yield var -MQTT_PUBLISH_JSON_ACTION_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.use_id(MQTTClientComponent), - cv.Required(CONF_TOPIC): cv.templatable(cv.publish_topic), - cv.Required(CONF_PAYLOAD): cv.lambda_, - cv.Optional(CONF_QOS, default=0): cv.templatable(cv.mqtt_qos), - cv.Optional(CONF_RETAIN, default=False): cv.templatable(cv.boolean), -}) +MQTT_PUBLISH_JSON_ACTION_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.use_id(MQTTClientComponent), + cv.Required(CONF_TOPIC): cv.templatable(cv.publish_topic), + cv.Required(CONF_PAYLOAD): cv.lambda_, + cv.Optional(CONF_QOS, default=0): cv.templatable(cv.mqtt_qos), + cv.Optional(CONF_RETAIN, default=False): cv.templatable(cv.boolean), + } +) -@automation.register_action('mqtt.publish_json', MQTTPublishJsonAction, - MQTT_PUBLISH_JSON_ACTION_SCHEMA) +@automation.register_action( + "mqtt.publish_json", MQTTPublishJsonAction, MQTT_PUBLISH_JSON_ACTION_SCHEMA +) def mqtt_publish_json_action_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) template_ = yield cg.templatable(config[CONF_TOPIC], args, cg.std_string) cg.add(var.set_topic(template_)) - args_ = args + [(cg.JsonObjectRef, 'root')] + args_ = args + [(cg.JsonObjectRef, "root")] lambda_ = yield cg.process_lambda(config[CONF_PAYLOAD], args_, return_type=cg.void) cg.add(var.set_payload(lambda_)) template_ = yield cg.templatable(config[CONF_QOS], args, cg.uint8) @@ -280,10 +347,13 @@ def mqtt_publish_json_action_to_code(config, action_id, template_arg, args): def get_default_topic_for(data, component_type, name, suffix): - allowlist = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_' - sanitized_name = ''.join(x for x in name.lower().replace(' ', '_') if x in allowlist) - return '{}/{}/{}/{}'.format(data.topic_prefix, component_type, - sanitized_name, suffix) + allowlist = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_" + sanitized_name = "".join( + x for x in name.lower().replace(" ", "_") if x in allowlist + ) + return "{}/{}/{}/{}".format( + data.topic_prefix, component_type, sanitized_name, suffix + ) @coroutine @@ -303,14 +373,24 @@ def register_mqtt_component(var, config): if not availability: cg.add(var.disable_availability()) else: - cg.add(var.set_availability(availability[CONF_TOPIC], - availability[CONF_PAYLOAD_AVAILABLE], - availability[CONF_PAYLOAD_NOT_AVAILABLE])) + cg.add( + var.set_availability( + availability[CONF_TOPIC], + availability[CONF_PAYLOAD_AVAILABLE], + availability[CONF_PAYLOAD_NOT_AVAILABLE], + ) + ) -@automation.register_condition('mqtt.connected', MQTTConnectedCondition, cv.Schema({ - cv.GenerateID(): cv.use_id(MQTTClientComponent), -})) +@automation.register_condition( + "mqtt.connected", + MQTTConnectedCondition, + cv.Schema( + { + cv.GenerateID(): cv.use_id(MQTTClientComponent), + } + ), +) def mqtt_connected_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) diff --git a/esphome/components/mqtt_subscribe/__init__.py b/esphome/components/mqtt_subscribe/__init__.py index 82e77f2f7..b17f32137 100644 --- a/esphome/components/mqtt_subscribe/__init__.py +++ b/esphome/components/mqtt_subscribe/__init__.py @@ -1,3 +1,3 @@ import esphome.codegen as cg -mqtt_subscribe_ns = cg.esphome_ns.namespace('mqtt_subscribe') +mqtt_subscribe_ns = cg.esphome_ns.namespace("mqtt_subscribe") diff --git a/esphome/components/mqtt_subscribe/sensor/__init__.py b/esphome/components/mqtt_subscribe/sensor/__init__.py index 0ccad5c72..00c2d324d 100644 --- a/esphome/components/mqtt_subscribe/sensor/__init__.py +++ b/esphome/components/mqtt_subscribe/sensor/__init__.py @@ -1,20 +1,35 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import mqtt, sensor -from esphome.const import CONF_ID, CONF_QOS, CONF_TOPIC, UNIT_EMPTY, ICON_EMPTY, DEVICE_CLASS_EMPTY +from esphome.const import ( + CONF_ID, + CONF_QOS, + CONF_TOPIC, + UNIT_EMPTY, + ICON_EMPTY, + DEVICE_CLASS_EMPTY, +) from .. import mqtt_subscribe_ns -DEPENDENCIES = ['mqtt'] +DEPENDENCIES = ["mqtt"] -CONF_MQTT_PARENT_ID = 'mqtt_parent_id' -MQTTSubscribeSensor = mqtt_subscribe_ns.class_('MQTTSubscribeSensor', sensor.Sensor, cg.Component) +CONF_MQTT_PARENT_ID = "mqtt_parent_id" +MQTTSubscribeSensor = mqtt_subscribe_ns.class_( + "MQTTSubscribeSensor", sensor.Sensor, cg.Component +) -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_EMPTY, ICON_EMPTY, 1, DEVICE_CLASS_EMPTY).extend({ - cv.GenerateID(): cv.declare_id(MQTTSubscribeSensor), - cv.GenerateID(CONF_MQTT_PARENT_ID): cv.use_id(mqtt.MQTTClientComponent), - cv.Required(CONF_TOPIC): cv.subscribe_topic, - cv.Optional(CONF_QOS, default=0): cv.mqtt_qos, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_EMPTY, ICON_EMPTY, 1, DEVICE_CLASS_EMPTY) + .extend( + { + cv.GenerateID(): cv.declare_id(MQTTSubscribeSensor), + cv.GenerateID(CONF_MQTT_PARENT_ID): cv.use_id(mqtt.MQTTClientComponent), + cv.Required(CONF_TOPIC): cv.subscribe_topic, + cv.Optional(CONF_QOS, default=0): cv.mqtt_qos, + } + ) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/mqtt_subscribe/text_sensor/__init__.py b/esphome/components/mqtt_subscribe/text_sensor/__init__.py index c80909669..b5f2c4307 100644 --- a/esphome/components/mqtt_subscribe/text_sensor/__init__.py +++ b/esphome/components/mqtt_subscribe/text_sensor/__init__.py @@ -4,18 +4,21 @@ from esphome.components import text_sensor, mqtt from esphome.const import CONF_ID, CONF_QOS, CONF_TOPIC from .. import mqtt_subscribe_ns -DEPENDENCIES = ['mqtt'] +DEPENDENCIES = ["mqtt"] -CONF_MQTT_PARENT_ID = 'mqtt_parent_id' -MQTTSubscribeTextSensor = mqtt_subscribe_ns.class_('MQTTSubscribeTextSensor', - text_sensor.TextSensor, cg.Component) +CONF_MQTT_PARENT_ID = "mqtt_parent_id" +MQTTSubscribeTextSensor = mqtt_subscribe_ns.class_( + "MQTTSubscribeTextSensor", text_sensor.TextSensor, cg.Component +) -CONFIG_SCHEMA = text_sensor.TEXT_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(MQTTSubscribeTextSensor), - cv.GenerateID(CONF_MQTT_PARENT_ID): cv.use_id(mqtt.MQTTClientComponent), - cv.Required(CONF_TOPIC): cv.subscribe_topic, - cv.Optional(CONF_QOS, default=0): cv.mqtt_qos, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = text_sensor.TEXT_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(MQTTSubscribeTextSensor), + cv.GenerateID(CONF_MQTT_PARENT_ID): cv.use_id(mqtt.MQTTClientComponent), + cv.Required(CONF_TOPIC): cv.subscribe_topic, + cv.Optional(CONF_QOS, default=0): cv.mqtt_qos, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/ms5611/sensor.py b/esphome/components/ms5611/sensor.py index 94ff6cbb0..d18000814 100644 --- a/esphome/components/ms5611/sensor.py +++ b/esphome/components/ms5611/sensor.py @@ -1,22 +1,40 @@ 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, ICON_EMPTY, UNIT_CELSIUS, \ - ICON_GAUGE, UNIT_HECTOPASCAL +from esphome.const import ( + CONF_ID, + CONF_PRESSURE, + CONF_TEMPERATURE, + DEVICE_CLASS_PRESSURE, + DEVICE_CLASS_TEMPERATURE, + ICON_EMPTY, + UNIT_CELSIUS, + ICON_GAUGE, + UNIT_HECTOPASCAL, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -ms5611_ns = cg.esphome_ns.namespace('ms5611') -MS5611Component = ms5611_ns.class_('MS5611Component', cg.PollingComponent, i2c.I2CDevice) +ms5611_ns = cg.esphome_ns.namespace("ms5611") +MS5611Component = ms5611_ns.class_( + "MS5611Component", cg.PollingComponent, i2c.I2CDevice +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(MS5611Component), - cv.Required(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, - DEVICE_CLASS_TEMPERATURE), - cv.Required(CONF_PRESSURE): sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_GAUGE, 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(MS5611Component), + cv.Required(CONF_TEMPERATURE): sensor.sensor_schema( + UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE + ), + cv.Required(CONF_PRESSURE): sensor.sensor_schema( + UNIT_HECTOPASCAL, ICON_GAUGE, 1, DEVICE_CLASS_PRESSURE + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x77)) +) def to_code(config): diff --git a/esphome/components/my9231/__init__.py b/esphome/components/my9231/__init__.py index 7ca0a30ca..ed1edd7b2 100644 --- a/esphome/components/my9231/__init__.py +++ b/esphome/components/my9231/__init__.py @@ -1,22 +1,30 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins -from esphome.const import (CONF_BIT_DEPTH, CONF_CLOCK_PIN, CONF_DATA_PIN, CONF_ID, - CONF_NUM_CHANNELS, CONF_NUM_CHIPS) +from esphome.const import ( + CONF_BIT_DEPTH, + CONF_CLOCK_PIN, + CONF_DATA_PIN, + CONF_ID, + CONF_NUM_CHANNELS, + CONF_NUM_CHIPS, +) -AUTO_LOAD = ['output'] -my9231_ns = cg.esphome_ns.namespace('my9231') -MY9231OutputComponent = my9231_ns.class_('MY9231OutputComponent', cg.Component) +AUTO_LOAD = ["output"] +my9231_ns = cg.esphome_ns.namespace("my9231") +MY9231OutputComponent = my9231_ns.class_("MY9231OutputComponent", cg.Component) MULTI_CONF = True -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(MY9231OutputComponent), - cv.Required(CONF_DATA_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_NUM_CHANNELS, default=6): cv.int_range(min=3, max=1020), - cv.Optional(CONF_NUM_CHIPS, default=2): cv.int_range(min=1, max=255), - cv.Optional(CONF_BIT_DEPTH, default=16): cv.one_of(8, 12, 14, 16, int=True), -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(MY9231OutputComponent), + cv.Required(CONF_DATA_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_NUM_CHANNELS, default=6): cv.int_range(min=3, max=1020), + cv.Optional(CONF_NUM_CHIPS, default=2): cv.int_range(min=1, max=255), + cv.Optional(CONF_BIT_DEPTH, default=16): cv.one_of(8, 12, 14, 16, int=True), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/my9231/output.py b/esphome/components/my9231/output.py index c69649fd5..30db84064 100644 --- a/esphome/components/my9231/output.py +++ b/esphome/components/my9231/output.py @@ -4,17 +4,18 @@ from esphome.components import output from esphome.const import CONF_CHANNEL, CONF_ID from . import MY9231OutputComponent -DEPENDENCIES = ['my9231'] +DEPENDENCIES = ["my9231"] -Channel = MY9231OutputComponent.class_('Channel', output.FloatOutput) +Channel = MY9231OutputComponent.class_("Channel", output.FloatOutput) -CONF_MY9231_ID = 'my9231_id' -CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend({ - cv.GenerateID(CONF_MY9231_ID): cv.use_id(MY9231OutputComponent), - - cv.Required(CONF_ID): cv.declare_id(Channel), - cv.Required(CONF_CHANNEL): cv.uint16_t, -}).extend(cv.COMPONENT_SCHEMA) +CONF_MY9231_ID = "my9231_id" +CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( + { + cv.GenerateID(CONF_MY9231_ID): cv.use_id(MY9231OutputComponent), + cv.Required(CONF_ID): cv.declare_id(Channel), + cv.Required(CONF_CHANNEL): cv.uint16_t, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/neopixelbus/light.py b/esphome/components/neopixelbus/light.py index 32bfd951e..0cf8057b8 100644 --- a/esphome/components/neopixelbus/light.py +++ b/esphome/components/neopixelbus/light.py @@ -2,32 +2,45 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.components import light -from esphome.const import CONF_CLOCK_PIN, CONF_DATA_PIN, CONF_METHOD, CONF_NUM_LEDS, CONF_PIN, \ - CONF_TYPE, CONF_VARIANT, CONF_OUTPUT_ID, CONF_INVERT +from esphome.const import ( + CONF_CLOCK_PIN, + CONF_DATA_PIN, + CONF_METHOD, + CONF_NUM_LEDS, + CONF_PIN, + CONF_TYPE, + CONF_VARIANT, + CONF_OUTPUT_ID, + CONF_INVERT, +) from esphome.core import CORE -neopixelbus_ns = cg.esphome_ns.namespace('neopixelbus') -NeoPixelBusLightOutputBase = neopixelbus_ns.class_('NeoPixelBusLightOutputBase', - light.AddressableLight) -NeoPixelRGBLightOutput = neopixelbus_ns.class_('NeoPixelRGBLightOutput', NeoPixelBusLightOutputBase) -NeoPixelRGBWLightOutput = neopixelbus_ns.class_('NeoPixelRGBWLightOutput', - NeoPixelBusLightOutputBase) -ESPNeoPixelOrder = neopixelbus_ns.namespace('ESPNeoPixelOrder') +neopixelbus_ns = cg.esphome_ns.namespace("neopixelbus") +NeoPixelBusLightOutputBase = neopixelbus_ns.class_( + "NeoPixelBusLightOutputBase", light.AddressableLight +) +NeoPixelRGBLightOutput = neopixelbus_ns.class_( + "NeoPixelRGBLightOutput", NeoPixelBusLightOutputBase +) +NeoPixelRGBWLightOutput = neopixelbus_ns.class_( + "NeoPixelRGBWLightOutput", NeoPixelBusLightOutputBase +) +ESPNeoPixelOrder = neopixelbus_ns.namespace("ESPNeoPixelOrder") NeoRgbFeature = cg.global_ns.NeoRgbFeature NeoRgbwFeature = cg.global_ns.NeoRgbwFeature def validate_type(value): value = cv.string(value).upper() - if 'R' not in value: + if "R" not in value: raise cv.Invalid("Must have R in type") - if 'G' not in value: + if "G" not in value: raise cv.Invalid("Must have G in type") - if 'B' not in value: + if "B" not in value: raise cv.Invalid("Must have B in type") - rest = set(value) - set('RGBW') + rest = set(value) - set("RGBW") if rest: - raise cv.Invalid("Type has invalid color: {}".format(', '.join(rest))) + raise cv.Invalid("Type has invalid color: {}".format(", ".join(rest))) if len(set(value)) != len(value): raise cv.Invalid("Type has duplicate color!") return value @@ -35,45 +48,45 @@ def validate_type(value): def validate_variant(value): value = cv.string(value).upper() - if value == 'WS2813': - value = 'WS2812X' - if value == 'WS2812': - value = '800KBPS' - if value == 'LC8812': - value = 'SK6812' + if value == "WS2813": + value = "WS2812X" + if value == "WS2812": + value = "800KBPS" + if value == "LC8812": + value = "SK6812" return cv.one_of(*VARIANTS)(value) def validate_method(value): if value is None: if CORE.is_esp32: - return 'ESP32_I2S_1' + return "ESP32_I2S_1" if CORE.is_esp8266: - return 'ESP8266_DMA' + return "ESP8266_DMA" raise NotImplementedError if CORE.is_esp32: - return cv.one_of(*ESP32_METHODS, upper=True, space='_')(value) + return cv.one_of(*ESP32_METHODS, upper=True, space="_")(value) if CORE.is_esp8266: - return cv.one_of(*ESP8266_METHODS, upper=True, space='_')(value) + return cv.one_of(*ESP8266_METHODS, upper=True, space="_")(value) raise NotImplementedError def validate_method_pin(value): method = value[CONF_METHOD] method_pins = { - 'ESP8266_DMA': [3], - 'ESP8266_UART0': [1], - 'ESP8266_ASYNC_UART0': [1], - 'ESP8266_UART1': [2], - 'ESP8266_ASYNC_UART1': [2], - 'ESP32_I2S_0': list(range(0, 32)), - 'ESP32_I2S_1': list(range(0, 32)), + "ESP8266_DMA": [3], + "ESP8266_UART0": [1], + "ESP8266_ASYNC_UART0": [1], + "ESP8266_UART1": [2], + "ESP8266_ASYNC_UART1": [2], + "ESP32_I2S_0": list(range(0, 32)), + "ESP32_I2S_1": list(range(0, 32)), } if CORE.is_esp8266: - method_pins['BIT_BANG'] = list(range(0, 16)) + method_pins["BIT_BANG"] = list(range(0, 16)) elif CORE.is_esp32: - method_pins['BIT_BANG'] = list(range(0, 32)) + method_pins["BIT_BANG"] = list(range(0, 32)) pins_ = method_pins.get(method) if pins_ is None: # all pins allowed for this method @@ -81,39 +94,42 @@ def validate_method_pin(value): for opt in (CONF_PIN, CONF_CLOCK_PIN, CONF_DATA_PIN): if opt in value and value[opt] not in pins_: - raise cv.Invalid("Method {} only supports pin(s) {}".format( - method, ', '.join(f'GPIO{x}' for x in pins_) - ), path=[CONF_METHOD]) + raise cv.Invalid( + "Method {} only supports pin(s) {}".format( + method, ", ".join(f"GPIO{x}" for x in pins_) + ), + path=[CONF_METHOD], + ) return value VARIANTS = { - 'WS2812X': 'Ws2812x', - 'SK6812': 'Sk6812', - '800KBPS': '800Kbps', - '400KBPS': '400Kbps', + "WS2812X": "Ws2812x", + "SK6812": "Sk6812", + "800KBPS": "800Kbps", + "400KBPS": "400Kbps", } ESP8266_METHODS = { - 'ESP8266_DMA': 'NeoEsp8266Dma{}Method', - 'ESP8266_UART0': 'NeoEsp8266Uart0{}Method', - 'ESP8266_UART1': 'NeoEsp8266Uart1{}Method', - 'ESP8266_ASYNC_UART0': 'NeoEsp8266AsyncUart0{}Method', - 'ESP8266_ASYNC_UART1': 'NeoEsp8266AsyncUart1{}Method', - 'BIT_BANG': 'NeoEsp8266BitBang{}Method', + "ESP8266_DMA": "NeoEsp8266Dma{}Method", + "ESP8266_UART0": "NeoEsp8266Uart0{}Method", + "ESP8266_UART1": "NeoEsp8266Uart1{}Method", + "ESP8266_ASYNC_UART0": "NeoEsp8266AsyncUart0{}Method", + "ESP8266_ASYNC_UART1": "NeoEsp8266AsyncUart1{}Method", + "BIT_BANG": "NeoEsp8266BitBang{}Method", } ESP32_METHODS = { - 'ESP32_I2S_0': 'NeoEsp32I2s0{}Method', - 'ESP32_I2S_1': 'NeoEsp32I2s1{}Method', - 'ESP32_RMT_0': 'NeoEsp32Rmt0{}Method', - 'ESP32_RMT_1': 'NeoEsp32Rmt1{}Method', - 'ESP32_RMT_2': 'NeoEsp32Rmt2{}Method', - 'ESP32_RMT_3': 'NeoEsp32Rmt3{}Method', - 'ESP32_RMT_4': 'NeoEsp32Rmt4{}Method', - 'ESP32_RMT_5': 'NeoEsp32Rmt5{}Method', - 'ESP32_RMT_6': 'NeoEsp32Rmt6{}Method', - 'ESP32_RMT_7': 'NeoEsp32Rmt7{}Method', - 'BIT_BANG': 'NeoEsp32BitBang{}Method', + "ESP32_I2S_0": "NeoEsp32I2s0{}Method", + "ESP32_I2S_1": "NeoEsp32I2s1{}Method", + "ESP32_RMT_0": "NeoEsp32Rmt0{}Method", + "ESP32_RMT_1": "NeoEsp32Rmt1{}Method", + "ESP32_RMT_2": "NeoEsp32Rmt2{}Method", + "ESP32_RMT_3": "NeoEsp32Rmt3{}Method", + "ESP32_RMT_4": "NeoEsp32Rmt4{}Method", + "ESP32_RMT_5": "NeoEsp32Rmt5{}Method", + "ESP32_RMT_6": "NeoEsp32Rmt6{}Method", + "ESP32_RMT_7": "NeoEsp32Rmt7{}Method", + "BIT_BANG": "NeoEsp32BitBang{}Method", } @@ -122,10 +138,10 @@ def format_method(config): method = config[CONF_METHOD] if config[CONF_INVERT]: - if method == 'ESP8266_DMA': - variant = 'Inverted' + variant + if method == "ESP8266_DMA": + variant = "Inverted" + variant else: - variant += 'Inverted' + variant += "Inverted" if CORE.is_esp8266: return ESP8266_METHODS[method].format(variant) @@ -146,23 +162,27 @@ def validate(config): raise cv.Invalid("Must specify at least one of 'pin' or 'clock_pin'+'data_pin'") -CONFIG_SCHEMA = cv.All(light.ADDRESSABLE_LIGHT_SCHEMA.extend({ - cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(NeoPixelBusLightOutputBase), - - cv.Optional(CONF_TYPE, default='GRB'): validate_type, - cv.Optional(CONF_VARIANT, default='800KBPS'): validate_variant, - cv.Optional(CONF_METHOD, default=None): validate_method, - cv.Optional(CONF_INVERT, default='no'): cv.boolean, - cv.Optional(CONF_PIN): pins.output_pin, - cv.Optional(CONF_CLOCK_PIN): pins.output_pin, - cv.Optional(CONF_DATA_PIN): pins.output_pin, - - cv.Required(CONF_NUM_LEDS): cv.positive_not_null_int, -}).extend(cv.COMPONENT_SCHEMA), validate, validate_method_pin) +CONFIG_SCHEMA = cv.All( + light.ADDRESSABLE_LIGHT_SCHEMA.extend( + { + cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(NeoPixelBusLightOutputBase), + cv.Optional(CONF_TYPE, default="GRB"): validate_type, + cv.Optional(CONF_VARIANT, default="800KBPS"): validate_variant, + cv.Optional(CONF_METHOD, default=None): validate_method, + cv.Optional(CONF_INVERT, default="no"): cv.boolean, + cv.Optional(CONF_PIN): pins.output_pin, + cv.Optional(CONF_CLOCK_PIN): pins.output_pin, + cv.Optional(CONF_DATA_PIN): pins.output_pin, + cv.Required(CONF_NUM_LEDS): cv.positive_not_null_int, + } + ).extend(cv.COMPONENT_SCHEMA), + validate, + validate_method_pin, +) def to_code(config): - has_white = 'W' in config[CONF_TYPE] + has_white = "W" in config[CONF_TYPE] template = cg.TemplateArguments(getattr(cg.global_ns, format_method(config))) if has_white: out_type = NeoPixelRGBWLightOutput.template(template) @@ -176,9 +196,13 @@ def to_code(config): if CONF_PIN in config: cg.add(var.add_leds(config[CONF_NUM_LEDS], config[CONF_PIN])) else: - cg.add(var.add_leds(config[CONF_NUM_LEDS], config[CONF_CLOCK_PIN], config[CONF_DATA_PIN])) + cg.add( + var.add_leds( + config[CONF_NUM_LEDS], config[CONF_CLOCK_PIN], config[CONF_DATA_PIN] + ) + ) cg.add(var.set_pixel_order(getattr(ESPNeoPixelOrder, config[CONF_TYPE]))) # https://github.com/Makuna/NeoPixelBus/blob/master/library.json - cg.add_library('NeoPixelBus-esphome', '2.5.7') + cg.add_library("NeoPixelBus-esphome", "2.5.7") diff --git a/esphome/components/network/__init__.py b/esphome/components/network/__init__.py index a380e32bf..46713d3ff 100644 --- a/esphome/components/network/__init__.py +++ b/esphome/components/network/__init__.py @@ -1,2 +1,2 @@ # Dummy package to allow components to depend on network -CODEOWNERS = ['@esphome/core'] +CODEOWNERS = ["@esphome/core"] diff --git a/esphome/components/nextion/__init__.py b/esphome/components/nextion/__init__.py index 1d90c9249..67a49df9f 100644 --- a/esphome/components/nextion/__init__.py +++ b/esphome/components/nextion/__init__.py @@ -1,3 +1,3 @@ import esphome.codegen as cg -nextion_ns = cg.esphome_ns.namespace('nextion') +nextion_ns = cg.esphome_ns.namespace("nextion") diff --git a/esphome/components/nextion/binary_sensor.py b/esphome/components/nextion/binary_sensor.py index 6003c5980..e822b65eb 100644 --- a/esphome/components/nextion/binary_sensor.py +++ b/esphome/components/nextion/binary_sensor.py @@ -5,19 +5,22 @@ from esphome.const import CONF_COMPONENT_ID, CONF_PAGE_ID, CONF_ID from . import nextion_ns from .display import Nextion -DEPENDENCIES = ['display'] +DEPENDENCIES = ["display"] -CONF_NEXTION_ID = 'nextion_id' +CONF_NEXTION_ID = "nextion_id" -NextionTouchComponent = nextion_ns.class_('NextionTouchComponent', binary_sensor.BinarySensor) +NextionTouchComponent = nextion_ns.class_( + "NextionTouchComponent", binary_sensor.BinarySensor +) -CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(NextionTouchComponent), - cv.GenerateID(CONF_NEXTION_ID): cv.use_id(Nextion), - - cv.Required(CONF_PAGE_ID): cv.uint8_t, - cv.Required(CONF_COMPONENT_ID): cv.uint8_t, -}) +CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(NextionTouchComponent), + cv.GenerateID(CONF_NEXTION_ID): cv.use_id(Nextion), + cv.Required(CONF_PAGE_ID): cv.uint8_t, + cv.Required(CONF_COMPONENT_ID): cv.uint8_t, + } +) def to_code(config): diff --git a/esphome/components/nextion/display.py b/esphome/components/nextion/display.py index 394de6958..483395fe2 100644 --- a/esphome/components/nextion/display.py +++ b/esphome/components/nextion/display.py @@ -4,16 +4,22 @@ from esphome.components import display, uart from esphome.const import CONF_ID, CONF_LAMBDA, CONF_BRIGHTNESS from . import nextion_ns -DEPENDENCIES = ['uart'] -AUTO_LOAD = ['binary_sensor'] +DEPENDENCIES = ["uart"] +AUTO_LOAD = ["binary_sensor"] -Nextion = nextion_ns.class_('Nextion', cg.PollingComponent, uart.UARTDevice) -NextionRef = Nextion.operator('ref') +Nextion = nextion_ns.class_("Nextion", cg.PollingComponent, uart.UARTDevice) +NextionRef = Nextion.operator("ref") -CONFIG_SCHEMA = display.BASIC_DISPLAY_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(Nextion), - cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, -}).extend(cv.polling_component_schema('5s')).extend(uart.UART_DEVICE_SCHEMA) +CONFIG_SCHEMA = ( + display.BASIC_DISPLAY_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(Nextion), + cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, + } + ) + .extend(cv.polling_component_schema("5s")) + .extend(uart.UART_DEVICE_SCHEMA) +) def to_code(config): @@ -24,8 +30,9 @@ def to_code(config): if CONF_BRIGHTNESS in config: cg.add(var.set_brightness(config[CONF_BRIGHTNESS])) if CONF_LAMBDA in config: - lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], [(NextionRef, 'it')], - return_type=cg.void) + lambda_ = yield cg.process_lambda( + config[CONF_LAMBDA], [(NextionRef, "it")], return_type=cg.void + ) cg.add(var.set_writer(lambda_)) yield display.register_display(var, config) diff --git a/esphome/components/nfc/__init__.py b/esphome/components/nfc/__init__.py index ae3c9a4c0..b795a5d5c 100644 --- a/esphome/components/nfc/__init__.py +++ b/esphome/components/nfc/__init__.py @@ -1,7 +1,7 @@ import esphome.codegen as cg -CODEOWNERS = ['@jesserockz'] +CODEOWNERS = ["@jesserockz"] -nfc_ns = cg.esphome_ns.namespace('nfc') +nfc_ns = cg.esphome_ns.namespace("nfc") -NfcTag = nfc_ns.class_('NfcTag') +NfcTag = nfc_ns.class_("NfcTag") diff --git a/esphome/components/ntc/sensor.py b/esphome/components/ntc/sensor.py index 5cafecdc5..f3505eec5 100644 --- a/esphome/components/ntc/sensor.py +++ b/esphome/components/ntc/sensor.py @@ -3,37 +3,50 @@ from math import log import esphome.config_validation as cv import esphome.codegen as cg from esphome.components import sensor -from esphome.const import CONF_CALIBRATION, CONF_ID, CONF_REFERENCE_RESISTANCE, \ - CONF_REFERENCE_TEMPERATURE, CONF_SENSOR, CONF_TEMPERATURE, CONF_VALUE, \ - DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, UNIT_CELSIUS +from esphome.const import ( + CONF_CALIBRATION, + CONF_ID, + CONF_REFERENCE_RESISTANCE, + CONF_REFERENCE_TEMPERATURE, + CONF_SENSOR, + CONF_TEMPERATURE, + CONF_VALUE, + DEVICE_CLASS_TEMPERATURE, + ICON_EMPTY, + UNIT_CELSIUS, +) -ntc_ns = cg.esphome_ns.namespace('ntc') -NTC = ntc_ns.class_('NTC', cg.Component, sensor.Sensor) +ntc_ns = cg.esphome_ns.namespace("ntc") +NTC = ntc_ns.class_("NTC", cg.Component, sensor.Sensor) -CONF_B_CONSTANT = 'b_constant' -CONF_A = 'a' -CONF_B = 'b' -CONF_C = 'c' +CONF_B_CONSTANT = "b_constant" +CONF_A = "a" +CONF_B = "b" +CONF_C = "c" ZERO_POINT = 273.15 def validate_calibration_parameter(value): if isinstance(value, dict): - return cv.Schema({ - cv.Required(CONF_TEMPERATURE): cv.float_, - cv.Required(CONF_VALUE): cv.float_, - })(value) + return cv.Schema( + { + cv.Required(CONF_TEMPERATURE): cv.float_, + cv.Required(CONF_VALUE): cv.float_, + } + )(value) value = cv.string(value) - parts = value.split('->') + parts = value.split("->") if len(parts) != 2: raise cv.Invalid("Calibration parameter must be of form 3000 -> 23°C") voltage = cv.resistance(parts[0].strip()) temperature = cv.temperature(parts[1].strip()) - return validate_calibration_parameter({ - CONF_TEMPERATURE: temperature, - CONF_VALUE: voltage, - }) + return validate_calibration_parameter( + { + CONF_TEMPERATURE: temperature, + CONF_VALUE: voltage, + } + ) def calc_steinhart_hart(value): @@ -48,16 +61,16 @@ def calc_steinhart_hart(value): l2 = log(r2) l3 = log(r3) - y1 = 1/t1 - y2 = 1/t2 - y3 = 1/t3 + y1 = 1 / t1 + y2 = 1 / t2 + y3 = 1 / t3 - g2 = (y2-y1)/(l2-l1) - g3 = (y3-y1)/(l3-l1) + g2 = (y2 - y1) / (l2 - l1) + g3 = (y3 - y1) / (l3 - l1) - c = (g3-g2)/(l3-l2) * 1/(l1+l2+l3) - b = g2 - c*(l1*l1 + l1*l2 + l2*l2) - a = y1 - (b + l1*l1*c) * l1 + c = (g3 - g2) / (l3 - l2) * 1 / (l1 + l2 + l3) + b = g2 - c * (l1 * l1 + l1 * l2 + l2 * l2) + a = y1 - (b + l1 * l1 * c) * l1 return a, b, c @@ -66,8 +79,8 @@ def calc_b(value): t0 = value[CONF_REFERENCE_TEMPERATURE] + ZERO_POINT r0 = value[CONF_REFERENCE_RESISTANCE] - a = (1/t0) - (1/beta) * log(r0) - b = 1/beta + a = (1 / t0) - (1 / beta) * log(r0) + b = 1 / beta c = 0 return a, b, c @@ -75,21 +88,27 @@ def calc_b(value): def process_calibration(value): if isinstance(value, dict): - value = cv.Schema({ - cv.Required(CONF_B_CONSTANT): cv.float_, - cv.Required(CONF_REFERENCE_TEMPERATURE): cv.temperature, - cv.Required(CONF_REFERENCE_RESISTANCE): cv.resistance, - })(value) + value = cv.Schema( + { + cv.Required(CONF_B_CONSTANT): cv.float_, + cv.Required(CONF_REFERENCE_TEMPERATURE): cv.temperature, + cv.Required(CONF_REFERENCE_RESISTANCE): cv.resistance, + } + )(value) a, b, c = calc_b(value) elif isinstance(value, list): if len(value) != 3: - raise cv.Invalid("Steinhart–Hart Calibration must consist of exactly three values") + raise cv.Invalid( + "Steinhart–Hart Calibration must consist of exactly three values" + ) value = cv.Schema([validate_calibration_parameter])(value) a, b, c = calc_steinhart_hart(value) else: - raise cv.Invalid("Calibration parameter accepts either a list for steinhart-hart " - "calibration, or mapping for b-constant calibration, " - "not {}".format(type(value))) + raise cv.Invalid( + "Calibration parameter accepts either a list for steinhart-hart " + "calibration, or mapping for b-constant calibration, " + "not {}".format(type(value)) + ) return { CONF_A: a, @@ -98,11 +117,17 @@ def process_calibration(value): } -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE).extend({ - cv.GenerateID(): cv.declare_id(NTC), - cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor), - cv.Required(CONF_CALIBRATION): process_calibration, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE) + .extend( + { + cv.GenerateID(): cv.declare_id(NTC), + cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor), + cv.Required(CONF_CALIBRATION): process_calibration, + } + ) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/ota/__init__.py b/esphome/components/ota/__init__.py index 8956227c1..25a278f5b 100644 --- a/esphome/components/ota/__init__.py +++ b/esphome/components/ota/__init__.py @@ -2,25 +2,33 @@ from esphome.cpp_generator import RawExpression import esphome.codegen as cg import esphome.config_validation as cv from esphome.const import ( - CONF_ID, CONF_NUM_ATTEMPTS, CONF_PASSWORD, - CONF_PORT, CONF_REBOOT_TIMEOUT, CONF_SAFE_MODE + CONF_ID, + CONF_NUM_ATTEMPTS, + CONF_PASSWORD, + CONF_PORT, + CONF_REBOOT_TIMEOUT, + CONF_SAFE_MODE, ) from esphome.core import CORE, coroutine_with_priority -CODEOWNERS = ['@esphome/core'] -DEPENDENCIES = ['network'] +CODEOWNERS = ["@esphome/core"] +DEPENDENCIES = ["network"] -ota_ns = cg.esphome_ns.namespace('ota') -OTAComponent = ota_ns.class_('OTAComponent', cg.Component) +ota_ns = cg.esphome_ns.namespace("ota") +OTAComponent = ota_ns.class_("OTAComponent", cg.Component) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(OTAComponent), - cv.Optional(CONF_SAFE_MODE, default=True): cv.boolean, - cv.SplitDefault(CONF_PORT, esp8266=8266, esp32=3232): cv.port, - cv.Optional(CONF_PASSWORD, default=''): cv.string, - cv.Optional(CONF_REBOOT_TIMEOUT, default='5min'): cv.positive_time_period_milliseconds, - cv.Optional(CONF_NUM_ATTEMPTS, default='10'): cv.positive_not_null_int -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(OTAComponent), + cv.Optional(CONF_SAFE_MODE, default=True): cv.boolean, + cv.SplitDefault(CONF_PORT, esp8266=8266, esp32=3232): cv.port, + cv.Optional(CONF_PASSWORD, default=""): cv.string, + cv.Optional( + CONF_REBOOT_TIMEOUT, default="5min" + ): cv.positive_time_period_milliseconds, + cv.Optional(CONF_NUM_ATTEMPTS, default="10"): cv.positive_not_null_int, + } +).extend(cv.COMPONENT_SCHEMA) @coroutine_with_priority(50.0) @@ -32,11 +40,12 @@ def to_code(config): yield cg.register_component(var, config) if config[CONF_SAFE_MODE]: - condition = var.should_enter_safe_mode(config[CONF_NUM_ATTEMPTS], - config[CONF_REBOOT_TIMEOUT]) + condition = var.should_enter_safe_mode( + config[CONF_NUM_ATTEMPTS], config[CONF_REBOOT_TIMEOUT] + ) cg.add(RawExpression(f"if ({condition}) return")) if CORE.is_esp8266: - cg.add_library('Update', None) + cg.add_library("Update", None) elif CORE.is_esp32: - cg.add_library('Hash', None) + cg.add_library("Hash", None) diff --git a/esphome/components/output/__init__.py b/esphome/components/output/__init__.py index 34cb7c3f7..487bd8cba 100644 --- a/esphome/components/output/__init__.py +++ b/esphome/components/output/__init__.py @@ -3,34 +3,44 @@ import esphome.config_validation as cv from esphome import automation from esphome.automation import maybe_simple_id from esphome.components import power_supply -from esphome.const import CONF_ID, CONF_INVERTED, CONF_LEVEL, CONF_MAX_POWER, \ - CONF_MIN_POWER, CONF_POWER_SUPPLY +from esphome.const import ( + CONF_ID, + CONF_INVERTED, + CONF_LEVEL, + CONF_MAX_POWER, + CONF_MIN_POWER, + CONF_POWER_SUPPLY, +) from esphome.core import CORE, coroutine -CODEOWNERS = ['@esphome/core'] +CODEOWNERS = ["@esphome/core"] IS_PLATFORM_COMPONENT = True -BINARY_OUTPUT_SCHEMA = cv.Schema({ - cv.Optional(CONF_POWER_SUPPLY): cv.use_id(power_supply.PowerSupply), - cv.Optional(CONF_INVERTED): cv.boolean, -}) +BINARY_OUTPUT_SCHEMA = cv.Schema( + { + cv.Optional(CONF_POWER_SUPPLY): cv.use_id(power_supply.PowerSupply), + cv.Optional(CONF_INVERTED): cv.boolean, + } +) -FLOAT_OUTPUT_SCHEMA = BINARY_OUTPUT_SCHEMA.extend({ - cv.Optional(CONF_MAX_POWER): cv.percentage, - cv.Optional(CONF_MIN_POWER): cv.percentage, -}) +FLOAT_OUTPUT_SCHEMA = BINARY_OUTPUT_SCHEMA.extend( + { + cv.Optional(CONF_MAX_POWER): cv.percentage, + cv.Optional(CONF_MIN_POWER): cv.percentage, + } +) -output_ns = cg.esphome_ns.namespace('output') -BinaryOutput = output_ns.class_('BinaryOutput') -BinaryOutputPtr = BinaryOutput.operator('ptr') -FloatOutput = output_ns.class_('FloatOutput', BinaryOutput) -FloatOutputPtr = FloatOutput.operator('ptr') +output_ns = cg.esphome_ns.namespace("output") +BinaryOutput = output_ns.class_("BinaryOutput") +BinaryOutputPtr = BinaryOutput.operator("ptr") +FloatOutput = output_ns.class_("FloatOutput", BinaryOutput) +FloatOutputPtr = FloatOutput.operator("ptr") # Actions -TurnOffAction = output_ns.class_('TurnOffAction', automation.Action) -TurnOnAction = output_ns.class_('TurnOnAction', automation.Action) -SetLevelAction = output_ns.class_('SetLevelAction', automation.Action) +TurnOffAction = output_ns.class_("TurnOffAction", automation.Action) +TurnOnAction = output_ns.class_("TurnOnAction", automation.Action) +SetLevelAction = output_ns.class_("SetLevelAction", automation.Action) @coroutine @@ -53,27 +63,37 @@ def register_output(var, config): yield setup_output_platform_(var, config) -BINARY_OUTPUT_ACTION_SCHEMA = maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(BinaryOutput), -}) +BINARY_OUTPUT_ACTION_SCHEMA = maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(BinaryOutput), + } +) -@automation.register_action('output.turn_on', TurnOnAction, BINARY_OUTPUT_ACTION_SCHEMA) +@automation.register_action("output.turn_on", TurnOnAction, BINARY_OUTPUT_ACTION_SCHEMA) def output_turn_on_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('output.turn_off', TurnOffAction, BINARY_OUTPUT_ACTION_SCHEMA) +@automation.register_action( + "output.turn_off", TurnOffAction, BINARY_OUTPUT_ACTION_SCHEMA +) def output_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('output.set_level', SetLevelAction, cv.Schema({ - cv.Required(CONF_ID): cv.use_id(FloatOutput), - cv.Required(CONF_LEVEL): cv.templatable(cv.percentage), -})) +@automation.register_action( + "output.set_level", + SetLevelAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(FloatOutput), + cv.Required(CONF_LEVEL): cv.templatable(cv.percentage), + } + ), +) def output_set_level_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) diff --git a/esphome/components/output/switch/__init__.py b/esphome/components/output/switch/__init__.py index 5795271f8..14027de74 100644 --- a/esphome/components/output/switch/__init__.py +++ b/esphome/components/output/switch/__init__.py @@ -4,12 +4,14 @@ from esphome.components import output, switch from esphome.const import CONF_ID, CONF_OUTPUT from .. import output_ns -OutputSwitch = output_ns.class_('OutputSwitch', switch.Switch, cg.Component) +OutputSwitch = output_ns.class_("OutputSwitch", switch.Switch, cg.Component) -CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(OutputSwitch), - cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput), -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(OutputSwitch), + cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/packages/__init__.py b/esphome/components/packages/__init__.py index 55dfe35e3..8c5c9a014 100644 --- a/esphome/components/packages/__init__.py +++ b/esphome/components/packages/__init__.py @@ -4,7 +4,6 @@ from esphome.const import CONF_PACKAGES def _merge_package(full_old, full_new): - def merge(old, new): # pylint: disable=no-else-return if isinstance(new, dict): @@ -30,8 +29,10 @@ def do_packages_pass(config: dict): packages = config[CONF_PACKAGES] with cv.prepend_path(CONF_PACKAGES): if not isinstance(packages, dict): - raise cv.Invalid("Packages must be a key to value mapping, got {} instead" - "".format(type(packages))) + raise cv.Invalid( + "Packages must be a key to value mapping, got {} instead" + "".format(type(packages)) + ) for package_name, package_config in packages.items(): with cv.prepend_path(package_name): diff --git a/esphome/components/partition/light.py b/esphome/components/partition/light.py index ba1059e36..202481b93 100644 --- a/esphome/components/partition/light.py +++ b/esphome/components/partition/light.py @@ -3,34 +3,49 @@ import esphome.config_validation as cv from esphome.components import light from esphome.const import CONF_FROM, CONF_ID, CONF_SEGMENTS, CONF_TO, CONF_OUTPUT_ID -partitions_ns = cg.esphome_ns.namespace('partition') -AddressableSegment = partitions_ns.class_('AddressableSegment') -PartitionLightOutput = partitions_ns.class_('PartitionLightOutput', light.AddressableLight) +partitions_ns = cg.esphome_ns.namespace("partition") +AddressableSegment = partitions_ns.class_("AddressableSegment") +PartitionLightOutput = partitions_ns.class_( + "PartitionLightOutput", light.AddressableLight +) def validate_from_to(value): if value[CONF_FROM] > value[CONF_TO]: - raise cv.Invalid("From ({}) must not be larger than to ({})" - "".format(value[CONF_FROM], value[CONF_TO])) + raise cv.Invalid( + "From ({}) must not be larger than to ({})" + "".format(value[CONF_FROM], value[CONF_TO]) + ) return value -CONFIG_SCHEMA = light.ADDRESSABLE_LIGHT_SCHEMA.extend({ - cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(PartitionLightOutput), - cv.Required(CONF_SEGMENTS): cv.All(cv.ensure_list({ - cv.Required(CONF_ID): cv.use_id(light.AddressableLightState), - cv.Required(CONF_FROM): cv.positive_int, - cv.Required(CONF_TO): cv.positive_int, - }, validate_from_to), cv.Length(min=1)), -}) +CONFIG_SCHEMA = light.ADDRESSABLE_LIGHT_SCHEMA.extend( + { + cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(PartitionLightOutput), + cv.Required(CONF_SEGMENTS): cv.All( + cv.ensure_list( + { + cv.Required(CONF_ID): cv.use_id(light.AddressableLightState), + cv.Required(CONF_FROM): cv.positive_int, + cv.Required(CONF_TO): cv.positive_int, + }, + validate_from_to, + ), + cv.Length(min=1), + ), + } +) def to_code(config): segments = [] for conf in config[CONF_SEGMENTS]: var = yield cg.get_variable(conf[CONF_ID]) - segments.append(AddressableSegment(var, conf[CONF_FROM], - conf[CONF_TO] - conf[CONF_FROM] + 1)) + segments.append( + AddressableSegment( + var, conf[CONF_FROM], conf[CONF_TO] - conf[CONF_FROM] + 1 + ) + ) var = cg.new_Pvariable(config[CONF_OUTPUT_ID], segments) yield cg.register_component(var, config) diff --git a/esphome/components/pca9685/__init__.py b/esphome/components/pca9685/__init__.py index 8e02bd78d..d88012a1c 100644 --- a/esphome/components/pca9685/__init__.py +++ b/esphome/components/pca9685/__init__.py @@ -3,17 +3,24 @@ import esphome.config_validation as cv from esphome.components import i2c from esphome.const import CONF_FREQUENCY, CONF_ID -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] MULTI_CONF = True -pca9685_ns = cg.esphome_ns.namespace('pca9685') -PCA9685Output = pca9685_ns.class_('PCA9685Output', cg.Component, i2c.I2CDevice) +pca9685_ns = cg.esphome_ns.namespace("pca9685") +PCA9685Output = pca9685_ns.class_("PCA9685Output", cg.Component, i2c.I2CDevice) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(PCA9685Output), - cv.Required(CONF_FREQUENCY): cv.All(cv.frequency, - cv.Range(min=23.84, max=1525.88)), -}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x40)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(PCA9685Output), + cv.Required(CONF_FREQUENCY): cv.All( + cv.frequency, cv.Range(min=23.84, max=1525.88) + ), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x40)) +) def to_code(config): diff --git a/esphome/components/pca9685/output.py b/esphome/components/pca9685/output.py index b5f480561..c3cb88eea 100644 --- a/esphome/components/pca9685/output.py +++ b/esphome/components/pca9685/output.py @@ -4,17 +4,18 @@ from esphome.components import output from esphome.const import CONF_CHANNEL, CONF_ID from . import PCA9685Output, pca9685_ns -DEPENDENCIES = ['pca9685'] +DEPENDENCIES = ["pca9685"] -PCA9685Channel = pca9685_ns.class_('PCA9685Channel', output.FloatOutput) -CONF_PCA9685_ID = 'pca9685_id' +PCA9685Channel = pca9685_ns.class_("PCA9685Channel", output.FloatOutput) +CONF_PCA9685_ID = "pca9685_id" -CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend({ - cv.Required(CONF_ID): cv.declare_id(PCA9685Channel), - cv.GenerateID(CONF_PCA9685_ID): cv.use_id(PCA9685Output), - - cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=15), -}) +CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( + { + cv.Required(CONF_ID): cv.declare_id(PCA9685Channel), + cv.GenerateID(CONF_PCA9685_ID): cv.use_id(PCA9685Output), + cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=15), + } +) def to_code(config): diff --git a/esphome/components/pcd8544/display.py b/esphome/components/pcd8544/display.py index f4b625fe8..50cc1b02a 100644 --- a/esphome/components/pcd8544/display.py +++ b/esphome/components/pcd8544/display.py @@ -3,23 +3,37 @@ import esphome.config_validation as cv from esphome import pins from esphome.components import display, spi from esphome.const import ( - CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES, CONF_RESET_PIN, CONF_CS_PIN, CONF_CONTRAST + CONF_DC_PIN, + CONF_ID, + CONF_LAMBDA, + CONF_PAGES, + CONF_RESET_PIN, + CONF_CS_PIN, + CONF_CONTRAST, ) -DEPENDENCIES = ['spi'] +DEPENDENCIES = ["spi"] -pcd8544_ns = cg.esphome_ns.namespace('pcd8544') -PCD8544 = pcd8544_ns.class_('PCD8544', cg.PollingComponent, display.DisplayBuffer, spi.SPIDevice) +pcd8544_ns = cg.esphome_ns.namespace("pcd8544") +PCD8544 = pcd8544_ns.class_( + "PCD8544", cg.PollingComponent, display.DisplayBuffer, spi.SPIDevice +) -CONFIG_SCHEMA = cv.All(display.FULL_DISPLAY_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(PCD8544), - cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_RESET_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_CS_PIN): pins.gpio_output_pin_schema, # CE - cv.Optional(CONF_CONTRAST, default=0x7f): cv.int_, -}).extend(cv.polling_component_schema('1s')).extend(spi.spi_device_schema()), - cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) +CONFIG_SCHEMA = cv.All( + display.FULL_DISPLAY_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(PCD8544), + cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_CS_PIN): pins.gpio_output_pin_schema, # CE + cv.Optional(CONF_CONTRAST, default=0x7F): cv.int_, + } + ) + .extend(cv.polling_component_schema("1s")) + .extend(spi.spi_device_schema()), + cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), +) def to_code(config): @@ -37,6 +51,7 @@ def to_code(config): cg.add(var.set_contrast(config[CONF_CONTRAST])) if CONF_LAMBDA in config: - lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], [(display.DisplayBufferRef, 'it')], - return_type=cg.void) + lambda_ = yield cg.process_lambda( + config[CONF_LAMBDA], [(display.DisplayBufferRef, "it")], return_type=cg.void + ) cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/pcf8574/__init__.py b/esphome/components/pcf8574/__init__.py index daf367c08..8c028fabc 100644 --- a/esphome/components/pcf8574/__init__.py +++ b/esphome/components/pcf8574/__init__.py @@ -4,25 +4,31 @@ from esphome import pins from esphome.components import i2c from esphome.const import CONF_ID, CONF_NUMBER, CONF_MODE, CONF_INVERTED -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] MULTI_CONF = True -pcf8574_ns = cg.esphome_ns.namespace('pcf8574') -PCF8574GPIOMode = pcf8574_ns.enum('PCF8574GPIOMode') +pcf8574_ns = cg.esphome_ns.namespace("pcf8574") +PCF8574GPIOMode = pcf8574_ns.enum("PCF8574GPIOMode") PCF8674_GPIO_MODES = { - 'INPUT': PCF8574GPIOMode.PCF8574_INPUT, - 'OUTPUT': PCF8574GPIOMode.PCF8574_OUTPUT, + "INPUT": PCF8574GPIOMode.PCF8574_INPUT, + "OUTPUT": PCF8574GPIOMode.PCF8574_OUTPUT, } -PCF8574Component = pcf8574_ns.class_('PCF8574Component', cg.Component, i2c.I2CDevice) -PCF8574GPIOPin = pcf8574_ns.class_('PCF8574GPIOPin', cg.GPIOPin) +PCF8574Component = pcf8574_ns.class_("PCF8574Component", cg.Component, i2c.I2CDevice) +PCF8574GPIOPin = pcf8574_ns.class_("PCF8574GPIOPin", cg.GPIOPin) -CONF_PCF8574 = 'pcf8574' -CONF_PCF8575 = 'pcf8575' -CONFIG_SCHEMA = cv.Schema({ - cv.Required(CONF_ID): cv.declare_id(PCF8574Component), - cv.Optional(CONF_PCF8575, default=False): cv.boolean, -}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x21)) +CONF_PCF8574 = "pcf8574" +CONF_PCF8575 = "pcf8575" +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(PCF8574Component), + cv.Optional(CONF_PCF8575, default=False): cv.boolean, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x21)) +) def to_code(config): @@ -34,27 +40,37 @@ def to_code(config): def validate_pcf8574_gpio_mode(value): value = cv.string(value) - if value.upper() == 'INPUT_PULLUP': - raise cv.Invalid("INPUT_PULLUP mode has been removed in 1.14 and been combined into " - "INPUT mode (they were the same thing). Please use INPUT instead.") + if value.upper() == "INPUT_PULLUP": + raise cv.Invalid( + "INPUT_PULLUP mode has been removed in 1.14 and been combined into " + "INPUT mode (they were the same thing). Please use INPUT instead." + ) return cv.enum(PCF8674_GPIO_MODES, upper=True)(value) -PCF8574_OUTPUT_PIN_SCHEMA = cv.Schema({ - cv.Required(CONF_PCF8574): cv.use_id(PCF8574Component), - cv.Required(CONF_NUMBER): cv.int_, - cv.Optional(CONF_MODE, default="OUTPUT"): validate_pcf8574_gpio_mode, - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) -PCF8574_INPUT_PIN_SCHEMA = cv.Schema({ - cv.Required(CONF_PCF8574): cv.use_id(PCF8574Component), - cv.Required(CONF_NUMBER): cv.int_, - cv.Optional(CONF_MODE, default="INPUT"): validate_pcf8574_gpio_mode, - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) +PCF8574_OUTPUT_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_PCF8574): cv.use_id(PCF8574Component), + cv.Required(CONF_NUMBER): cv.int_, + cv.Optional(CONF_MODE, default="OUTPUT"): validate_pcf8574_gpio_mode, + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) +PCF8574_INPUT_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_PCF8574): cv.use_id(PCF8574Component), + cv.Required(CONF_NUMBER): cv.int_, + cv.Optional(CONF_MODE, default="INPUT"): validate_pcf8574_gpio_mode, + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) -@pins.PIN_SCHEMA_REGISTRY.register('pcf8574', (PCF8574_OUTPUT_PIN_SCHEMA, PCF8574_INPUT_PIN_SCHEMA)) +@pins.PIN_SCHEMA_REGISTRY.register( + "pcf8574", (PCF8574_OUTPUT_PIN_SCHEMA, PCF8574_INPUT_PIN_SCHEMA) +) def pcf8574_pin_to_code(config): parent = yield cg.get_variable(config[CONF_PCF8574]) - yield PCF8574GPIOPin.new(parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED]) + yield PCF8574GPIOPin.new( + parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED] + ) diff --git a/esphome/components/pid/__init__.py b/esphome/components/pid/__init__.py index 6f14e1003..71a87b6ae 100644 --- a/esphome/components/pid/__init__.py +++ b/esphome/components/pid/__init__.py @@ -1 +1 @@ -CODEOWNERS = ['@OttoWinter'] +CODEOWNERS = ["@OttoWinter"] diff --git a/esphome/components/pid/climate.py b/esphome/components/pid/climate.py index 446c614f1..c16f1726a 100644 --- a/esphome/components/pid/climate.py +++ b/esphome/components/pid/climate.py @@ -4,40 +4,51 @@ from esphome import automation from esphome.components import climate, sensor, output from esphome.const import CONF_ID, CONF_SENSOR -pid_ns = cg.esphome_ns.namespace('pid') -PIDClimate = pid_ns.class_('PIDClimate', climate.Climate, cg.Component) -PIDAutotuneAction = pid_ns.class_('PIDAutotuneAction', automation.Action) -PIDResetIntegralTermAction = pid_ns.class_('PIDResetIntegralTermAction', automation.Action) -PIDSetControlParametersAction = pid_ns.class_('PIDSetControlParametersAction', automation.Action) +pid_ns = cg.esphome_ns.namespace("pid") +PIDClimate = pid_ns.class_("PIDClimate", climate.Climate, cg.Component) +PIDAutotuneAction = pid_ns.class_("PIDAutotuneAction", automation.Action) +PIDResetIntegralTermAction = pid_ns.class_( + "PIDResetIntegralTermAction", automation.Action +) +PIDSetControlParametersAction = pid_ns.class_( + "PIDSetControlParametersAction", automation.Action +) -CONF_DEFAULT_TARGET_TEMPERATURE = 'default_target_temperature' +CONF_DEFAULT_TARGET_TEMPERATURE = "default_target_temperature" -CONF_KP = 'kp' -CONF_KI = 'ki' -CONF_KD = 'kd' -CONF_CONTROL_PARAMETERS = 'control_parameters' -CONF_COOL_OUTPUT = 'cool_output' -CONF_HEAT_OUTPUT = 'heat_output' -CONF_NOISEBAND = 'noiseband' -CONF_POSITIVE_OUTPUT = 'positive_output' -CONF_NEGATIVE_OUTPUT = 'negative_output' -CONF_MIN_INTEGRAL = 'min_integral' -CONF_MAX_INTEGRAL = 'max_integral' +CONF_KP = "kp" +CONF_KI = "ki" +CONF_KD = "kd" +CONF_CONTROL_PARAMETERS = "control_parameters" +CONF_COOL_OUTPUT = "cool_output" +CONF_HEAT_OUTPUT = "heat_output" +CONF_NOISEBAND = "noiseband" +CONF_POSITIVE_OUTPUT = "positive_output" +CONF_NEGATIVE_OUTPUT = "negative_output" +CONF_MIN_INTEGRAL = "min_integral" +CONF_MAX_INTEGRAL = "max_integral" -CONFIG_SCHEMA = cv.All(climate.CLIMATE_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(PIDClimate), - cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor), - cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE): cv.temperature, - cv.Optional(CONF_COOL_OUTPUT): cv.use_id(output.FloatOutput), - cv.Optional(CONF_HEAT_OUTPUT): cv.use_id(output.FloatOutput), - cv.Required(CONF_CONTROL_PARAMETERS): cv.Schema({ - cv.Required(CONF_KP): cv.float_, - cv.Optional(CONF_KI, default=0.0): cv.float_, - cv.Optional(CONF_KD, default=0.0): cv.float_, - cv.Optional(CONF_MIN_INTEGRAL, default=-1): cv.float_, - cv.Optional(CONF_MAX_INTEGRAL, default=1): cv.float_, - }), -}), cv.has_at_least_one_key(CONF_COOL_OUTPUT, CONF_HEAT_OUTPUT)) +CONFIG_SCHEMA = cv.All( + climate.CLIMATE_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(PIDClimate), + cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor), + cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE): cv.temperature, + cv.Optional(CONF_COOL_OUTPUT): cv.use_id(output.FloatOutput), + cv.Optional(CONF_HEAT_OUTPUT): cv.use_id(output.FloatOutput), + cv.Required(CONF_CONTROL_PARAMETERS): cv.Schema( + { + cv.Required(CONF_KP): cv.float_, + cv.Optional(CONF_KI, default=0.0): cv.float_, + cv.Optional(CONF_KD, default=0.0): cv.float_, + cv.Optional(CONF_MIN_INTEGRAL, default=-1): cv.float_, + cv.Optional(CONF_MAX_INTEGRAL, default=1): cv.float_, + } + ), + } + ), + cv.has_at_least_one_key(CONF_COOL_OUTPUT, CONF_HEAT_OUTPUT), +) def to_code(config): @@ -67,23 +78,35 @@ def to_code(config): @automation.register_action( - 'climate.pid.reset_integral_term', + "climate.pid.reset_integral_term", PIDResetIntegralTermAction, - automation.maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(PIDClimate), - }) + automation.maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(PIDClimate), + } + ), ) def pid_reset_integral_term(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('climate.pid.autotune', PIDAutotuneAction, automation.maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(PIDClimate), - cv.Optional(CONF_NOISEBAND, default=0.25): cv.float_, - cv.Optional(CONF_POSITIVE_OUTPUT, default=1.0): cv.possibly_negative_percentage, - cv.Optional(CONF_NEGATIVE_OUTPUT, default=-1.0): cv.possibly_negative_percentage, -})) +@automation.register_action( + "climate.pid.autotune", + PIDAutotuneAction, + automation.maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(PIDClimate), + cv.Optional(CONF_NOISEBAND, default=0.25): cv.float_, + cv.Optional( + CONF_POSITIVE_OUTPUT, default=1.0 + ): cv.possibly_negative_percentage, + cv.Optional( + CONF_NEGATIVE_OUTPUT, default=-1.0 + ): cv.possibly_negative_percentage, + } + ), +) 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) @@ -94,14 +117,16 @@ def esp8266_set_frequency_to_code(config, action_id, template_arg, args): @automation.register_action( - 'climate.pid.set_control_parameters', + "climate.pid.set_control_parameters", PIDSetControlParametersAction, - automation.maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(PIDClimate), - cv.Required(CONF_KP): cv.templatable(cv.float_), - cv.Optional(CONF_KI, default=0.0): cv.templatable(cv.float_), - cv.Optional(CONF_KD, default=0.0): cv.templatable(cv.float_), - }) + automation.maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(PIDClimate), + cv.Required(CONF_KP): cv.templatable(cv.float_), + cv.Optional(CONF_KI, default=0.0): cv.templatable(cv.float_), + cv.Optional(CONF_KD, default=0.0): cv.templatable(cv.float_), + } + ), ) def set_control_parameters(config, action_id, template_arg, args): paren = yield cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/pid/sensor/__init__.py b/esphome/components/pid/sensor/__init__.py index e655480a4..d29fb6b66 100644 --- a/esphome/components/pid/sensor/__init__.py +++ b/esphome/components/pid/sensor/__init__.py @@ -1,32 +1,43 @@ 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, UNIT_PERCENT, ICON_GAUGE, CONF_TYPE +from esphome.const import ( + CONF_ID, + DEVICE_CLASS_EMPTY, + UNIT_PERCENT, + ICON_GAUGE, + CONF_TYPE, +) from ..climate import pid_ns, PIDClimate -PIDClimateSensor = pid_ns.class_('PIDClimateSensor', sensor.Sensor, cg.Component) -PIDClimateSensorType = pid_ns.enum('PIDClimateSensorType') +PIDClimateSensor = pid_ns.class_("PIDClimateSensor", sensor.Sensor, cg.Component) +PIDClimateSensorType = pid_ns.enum("PIDClimateSensorType") PID_CLIMATE_SENSOR_TYPES = { - 'RESULT': PIDClimateSensorType.PID_SENSOR_TYPE_RESULT, - 'ERROR': PIDClimateSensorType.PID_SENSOR_TYPE_ERROR, - 'PROPORTIONAL': PIDClimateSensorType.PID_SENSOR_TYPE_PROPORTIONAL, - 'INTEGRAL': PIDClimateSensorType.PID_SENSOR_TYPE_INTEGRAL, - 'DERIVATIVE': PIDClimateSensorType.PID_SENSOR_TYPE_DERIVATIVE, - 'HEAT': PIDClimateSensorType.PID_SENSOR_TYPE_HEAT, - 'COOL': PIDClimateSensorType.PID_SENSOR_TYPE_COOL, - 'KP': PIDClimateSensorType.PID_SENSOR_TYPE_KP, - 'KI': PIDClimateSensorType.PID_SENSOR_TYPE_KI, - 'KD': PIDClimateSensorType.PID_SENSOR_TYPE_KD, + "RESULT": PIDClimateSensorType.PID_SENSOR_TYPE_RESULT, + "ERROR": PIDClimateSensorType.PID_SENSOR_TYPE_ERROR, + "PROPORTIONAL": PIDClimateSensorType.PID_SENSOR_TYPE_PROPORTIONAL, + "INTEGRAL": PIDClimateSensorType.PID_SENSOR_TYPE_INTEGRAL, + "DERIVATIVE": PIDClimateSensorType.PID_SENSOR_TYPE_DERIVATIVE, + "HEAT": PIDClimateSensorType.PID_SENSOR_TYPE_HEAT, + "COOL": PIDClimateSensorType.PID_SENSOR_TYPE_COOL, + "KP": PIDClimateSensorType.PID_SENSOR_TYPE_KP, + "KI": PIDClimateSensorType.PID_SENSOR_TYPE_KI, + "KD": PIDClimateSensorType.PID_SENSOR_TYPE_KD, } -CONF_CLIMATE_ID = 'climate_id' -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_PERCENT, ICON_GAUGE, 1, DEVICE_CLASS_EMPTY).extend({ - cv.GenerateID(): cv.declare_id(PIDClimateSensor), - cv.GenerateID(CONF_CLIMATE_ID): cv.use_id(PIDClimate), - - cv.Required(CONF_TYPE): cv.enum(PID_CLIMATE_SENSOR_TYPES, upper=True), -}).extend(cv.COMPONENT_SCHEMA) +CONF_CLIMATE_ID = "climate_id" +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_PERCENT, ICON_GAUGE, 1, DEVICE_CLASS_EMPTY) + .extend( + { + cv.GenerateID(): cv.declare_id(PIDClimateSensor), + cv.GenerateID(CONF_CLIMATE_ID): cv.use_id(PIDClimate), + cv.Required(CONF_TYPE): cv.enum(PID_CLIMATE_SENSOR_TYPES, upper=True), + } + ) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/pmsx003/sensor.py b/esphome/components/pmsx003/sensor.py index aa1be62ad..05becfb71 100644 --- a/esphome/components/pmsx003/sensor.py +++ b/esphome/components/pmsx003/sensor.py @@ -1,22 +1,36 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, uart -from esphome.const import CONF_FORMALDEHYDE, CONF_HUMIDITY, CONF_ID, CONF_PM_10_0, \ - CONF_PM_1_0, CONF_PM_2_5, CONF_TEMPERATURE, CONF_TYPE, DEVICE_CLASS_EMPTY, \ - DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_TEMPERATURE, ICON_CHEMICAL_WEAPON, ICON_EMPTY, \ - UNIT_MICROGRAMS_PER_CUBIC_METER, UNIT_CELSIUS, UNIT_PERCENT +from esphome.const import ( + CONF_FORMALDEHYDE, + CONF_HUMIDITY, + CONF_ID, + CONF_PM_10_0, + CONF_PM_1_0, + CONF_PM_2_5, + CONF_TEMPERATURE, + CONF_TYPE, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_TEMPERATURE, + ICON_CHEMICAL_WEAPON, + ICON_EMPTY, + UNIT_MICROGRAMS_PER_CUBIC_METER, + UNIT_CELSIUS, + UNIT_PERCENT, +) -DEPENDENCIES = ['uart'] +DEPENDENCIES = ["uart"] -pmsx003_ns = cg.esphome_ns.namespace('pmsx003') -PMSX003Component = pmsx003_ns.class_('PMSX003Component', uart.UARTDevice, cg.Component) -PMSX003Sensor = pmsx003_ns.class_('PMSX003Sensor', sensor.Sensor) +pmsx003_ns = cg.esphome_ns.namespace("pmsx003") +PMSX003Component = pmsx003_ns.class_("PMSX003Component", uart.UARTDevice, cg.Component) +PMSX003Sensor = pmsx003_ns.class_("PMSX003Sensor", sensor.Sensor) -TYPE_PMSX003 = 'PMSX003' -TYPE_PMS5003T = 'PMS5003T' -TYPE_PMS5003ST = 'PMS5003ST' +TYPE_PMSX003 = "PMSX003" +TYPE_PMS5003T = "PMS5003T" +TYPE_PMS5003ST = "PMS5003ST" -PMSX003Type = pmsx003_ns.enum('PMSX003Type') +PMSX003Type = pmsx003_ns.enum("PMSX003Type") PMSX003_TYPES = { TYPE_PMSX003: PMSX003Type.PMSX003_TYPE_X003, TYPE_PMS5003T: PMSX003Type.PMSX003_TYPE_5003T, @@ -36,31 +50,52 @@ SENSORS_TO_TYPE = { def validate_pmsx003_sensors(value): for key, types in SENSORS_TO_TYPE.items(): if key in value and value[CONF_TYPE] not in types: - raise cv.Invalid("{} does not have {} sensor!".format(value[CONF_TYPE], key)) + raise cv.Invalid( + "{} does not have {} sensor!".format(value[CONF_TYPE], key) + ) return value -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(PMSX003Component), - cv.Required(CONF_TYPE): cv.enum(PMSX003_TYPES, upper=True), - - cv.Optional(CONF_PM_1_0): - sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_CHEMICAL_WEAPON, 0, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_PM_2_5): - sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_CHEMICAL_WEAPON, 0, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_PM_10_0): - sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_CHEMICAL_WEAPON, 0, - DEVICE_CLASS_EMPTY), - 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), - cv.Optional(CONF_FORMALDEHYDE): - sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_CHEMICAL_WEAPON, 0, - DEVICE_CLASS_EMPTY), -}).extend(cv.COMPONENT_SCHEMA).extend(uart.UART_DEVICE_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(PMSX003Component), + cv.Required(CONF_TYPE): cv.enum(PMSX003_TYPES, upper=True), + cv.Optional(CONF_PM_1_0): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, + 0, + DEVICE_CLASS_EMPTY, + ), + cv.Optional(CONF_PM_2_5): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, + 0, + DEVICE_CLASS_EMPTY, + ), + cv.Optional(CONF_PM_10_0): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, + 0, + DEVICE_CLASS_EMPTY, + ), + 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 + ), + cv.Optional(CONF_FORMALDEHYDE): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, + 0, + DEVICE_CLASS_EMPTY, + ), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(uart.UART_DEVICE_SCHEMA) +) def to_code(config): diff --git a/esphome/components/pn532/__init__.py b/esphome/components/pn532/__init__.py index c96ebe2b4..5403ebe5c 100644 --- a/esphome/components/pn532/__init__.py +++ b/esphome/components/pn532/__init__.py @@ -5,38 +5,52 @@ from esphome.components import nfc from esphome.const import CONF_ID, CONF_ON_TAG, CONF_TRIGGER_ID from esphome.core import coroutine -CODEOWNERS = ['@OttoWinter', '@jesserockz'] -AUTO_LOAD = ['binary_sensor', 'nfc'] +CODEOWNERS = ["@OttoWinter", "@jesserockz"] +AUTO_LOAD = ["binary_sensor", "nfc"] MULTI_CONF = True -CONF_PN532_ID = 'pn532_id' -CONF_ON_FINISHED_WRITE = 'on_finished_write' +CONF_PN532_ID = "pn532_id" +CONF_ON_FINISHED_WRITE = "on_finished_write" -pn532_ns = cg.esphome_ns.namespace('pn532') -PN532 = pn532_ns.class_('PN532', cg.PollingComponent) +pn532_ns = cg.esphome_ns.namespace("pn532") +PN532 = pn532_ns.class_("PN532", cg.PollingComponent) -PN532OnTagTrigger = pn532_ns.class_('PN532OnTagTrigger', - automation.Trigger.template(cg.std_string, nfc.NfcTag)) -PN532OnFinishedWriteTrigger = pn532_ns.class_('PN532OnFinishedWriteTrigger', - automation.Trigger.template()) +PN532OnTagTrigger = pn532_ns.class_( + "PN532OnTagTrigger", automation.Trigger.template(cg.std_string, nfc.NfcTag) +) +PN532OnFinishedWriteTrigger = pn532_ns.class_( + "PN532OnFinishedWriteTrigger", automation.Trigger.template() +) -PN532IsWritingCondition = pn532_ns.class_('PN532IsWritingCondition', automation.Condition) +PN532IsWritingCondition = pn532_ns.class_( + "PN532IsWritingCondition", automation.Condition +) -PN532_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(PN532), - cv.Optional(CONF_ON_TAG): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PN532OnTagTrigger), - }), - cv.Optional(CONF_ON_FINISHED_WRITE): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PN532OnFinishedWriteTrigger), - }), -}).extend(cv.polling_component_schema('1s')) +PN532_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(PN532), + cv.Optional(CONF_ON_TAG): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PN532OnTagTrigger), + } + ), + cv.Optional(CONF_ON_FINISHED_WRITE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + PN532OnFinishedWriteTrigger + ), + } + ), + } +).extend(cv.polling_component_schema("1s")) def CONFIG_SCHEMA(conf): if conf: - raise cv.Invalid("This component has been moved in 1.16, please see the docs for updated " - "instructions. https://esphome.io/components/binary_sensor/pn532.html") + raise cv.Invalid( + "This component has been moved in 1.16, please see the docs for updated " + "instructions. https://esphome.io/components/binary_sensor/pn532.html" + ) @coroutine @@ -46,17 +60,24 @@ def setup_pn532(var, config): for conf in config.get(CONF_ON_TAG, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID]) cg.add(var.register_trigger(trigger)) - yield automation.build_automation(trigger, [(cg.std_string, 'x'), (nfc.NfcTag, 'tag')], - conf) + yield automation.build_automation( + trigger, [(cg.std_string, "x"), (nfc.NfcTag, "tag")], conf + ) for conf in config.get(CONF_ON_FINISHED_WRITE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) yield automation.build_automation(trigger, [], conf) -@automation.register_condition('pn532.is_writing', PN532IsWritingCondition, cv.Schema({ - cv.GenerateID(): cv.use_id(PN532), -})) +@automation.register_condition( + "pn532.is_writing", + PN532IsWritingCondition, + cv.Schema( + { + cv.GenerateID(): cv.use_id(PN532), + } + ), +) def pn532_is_writing_to_code(config, condition_id, template_arg, args): var = cg.new_Pvariable(condition_id, template_arg) yield cg.register_parented(var, config[CONF_ID]) diff --git a/esphome/components/pn532/binary_sensor.py b/esphome/components/pn532/binary_sensor.py index 2404bc9e9..5e6bf6c2b 100644 --- a/esphome/components/pn532/binary_sensor.py +++ b/esphome/components/pn532/binary_sensor.py @@ -5,31 +5,39 @@ from esphome.const import CONF_UID, CONF_ID from esphome.core import HexInt from . import pn532_ns, PN532, CONF_PN532_ID -DEPENDENCIES = ['pn532'] +DEPENDENCIES = ["pn532"] def validate_uid(value): value = cv.string_strict(value) - for x in value.split('-'): + for x in value.split("-"): if len(x) != 2: - raise cv.Invalid("Each part (separated by '-') of the UID must be two characters " - "long.") + raise cv.Invalid( + "Each part (separated by '-') of the UID must be two characters " + "long." + ) try: x = int(x, 16) except ValueError as err: - raise cv.Invalid("Valid characters for parts of a UID are 0123456789ABCDEF.") from err + raise cv.Invalid( + "Valid characters for parts of a UID are 0123456789ABCDEF." + ) from err if x < 0 or x > 255: - raise cv.Invalid("Valid values for UID parts (separated by '-') are 00 to FF") + raise cv.Invalid( + "Valid values for UID parts (separated by '-') are 00 to FF" + ) return value -PN532BinarySensor = pn532_ns.class_('PN532BinarySensor', binary_sensor.BinarySensor) +PN532BinarySensor = pn532_ns.class_("PN532BinarySensor", binary_sensor.BinarySensor) -CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(PN532BinarySensor), - cv.GenerateID(CONF_PN532_ID): cv.use_id(PN532), - cv.Required(CONF_UID): validate_uid, -}) +CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(PN532BinarySensor), + cv.GenerateID(CONF_PN532_ID): cv.use_id(PN532), + cv.Required(CONF_UID): validate_uid, + } +) def to_code(config): @@ -38,5 +46,5 @@ def to_code(config): hub = yield cg.get_variable(config[CONF_PN532_ID]) cg.add(hub.register_tag(var)) - addr = [HexInt(int(x, 16)) for x in config[CONF_UID].split('-')] + addr = [HexInt(int(x, 16)) for x in config[CONF_UID].split("-")] cg.add(var.set_uid(addr)) diff --git a/esphome/components/pn532_i2c/__init__.py b/esphome/components/pn532_i2c/__init__.py index f1c50adf4..80995bd01 100644 --- a/esphome/components/pn532_i2c/__init__.py +++ b/esphome/components/pn532_i2c/__init__.py @@ -3,16 +3,20 @@ import esphome.config_validation as cv from esphome.components import i2c, pn532 from esphome.const import CONF_ID -AUTO_LOAD = ['pn532'] -CODEOWNERS = ['@OttoWinter', '@jesserockz'] -DEPENDENCIES = ['i2c'] +AUTO_LOAD = ["pn532"] +CODEOWNERS = ["@OttoWinter", "@jesserockz"] +DEPENDENCIES = ["i2c"] -pn532_i2c_ns = cg.esphome_ns.namespace('pn532_i2c') -PN532I2C = pn532_i2c_ns.class_('PN532I2C', pn532.PN532, i2c.I2CDevice) +pn532_i2c_ns = cg.esphome_ns.namespace("pn532_i2c") +PN532I2C = pn532_i2c_ns.class_("PN532I2C", pn532.PN532, i2c.I2CDevice) -CONFIG_SCHEMA = cv.All(pn532.PN532_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(PN532I2C), -}).extend(i2c.i2c_device_schema(0x24))) +CONFIG_SCHEMA = cv.All( + pn532.PN532_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(PN532I2C), + } + ).extend(i2c.i2c_device_schema(0x24)) +) def to_code(config): diff --git a/esphome/components/pn532_spi/__init__.py b/esphome/components/pn532_spi/__init__.py index e378b96c2..2abe43629 100644 --- a/esphome/components/pn532_spi/__init__.py +++ b/esphome/components/pn532_spi/__init__.py @@ -3,16 +3,20 @@ import esphome.config_validation as cv from esphome.components import spi, pn532 from esphome.const import CONF_ID -AUTO_LOAD = ['pn532'] -CODEOWNERS = ['@OttoWinter', '@jesserockz'] -DEPENDENCIES = ['spi'] +AUTO_LOAD = ["pn532"] +CODEOWNERS = ["@OttoWinter", "@jesserockz"] +DEPENDENCIES = ["spi"] -pn532_spi_ns = cg.esphome_ns.namespace('pn532_spi') -PN532Spi = pn532_spi_ns.class_('PN532Spi', pn532.PN532, spi.SPIDevice) +pn532_spi_ns = cg.esphome_ns.namespace("pn532_spi") +PN532Spi = pn532_spi_ns.class_("PN532Spi", pn532.PN532, spi.SPIDevice) -CONFIG_SCHEMA = cv.All(pn532.PN532_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(PN532Spi), -}).extend(spi.spi_device_schema(cs_pin_required=True))) +CONFIG_SCHEMA = cv.All( + pn532.PN532_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(PN532Spi), + } + ).extend(spi.spi_device_schema(cs_pin_required=True)) +) def to_code(config): diff --git a/esphome/components/power_supply/__init__.py b/esphome/components/power_supply/__init__.py index d50278863..efed5e0d8 100644 --- a/esphome/components/power_supply/__init__.py +++ b/esphome/components/power_supply/__init__.py @@ -3,17 +3,23 @@ import esphome.config_validation as cv from esphome import pins from esphome.const import CONF_ENABLE_TIME, CONF_ID, CONF_KEEP_ON_TIME, CONF_PIN -CODEOWNERS = ['@esphome/core'] -power_supply_ns = cg.esphome_ns.namespace('power_supply') -PowerSupply = power_supply_ns.class_('PowerSupply', cg.Component) +CODEOWNERS = ["@esphome/core"] +power_supply_ns = cg.esphome_ns.namespace("power_supply") +PowerSupply = power_supply_ns.class_("PowerSupply", cg.Component) MULTI_CONF = True -CONFIG_SCHEMA = cv.Schema({ - cv.Required(CONF_ID): cv.declare_id(PowerSupply), - cv.Required(CONF_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_ENABLE_TIME, default='20ms'): cv.positive_time_period_milliseconds, - cv.Optional(CONF_KEEP_ON_TIME, default='10s'): cv.positive_time_period_milliseconds, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(PowerSupply), + cv.Required(CONF_PIN): pins.gpio_output_pin_schema, + cv.Optional( + CONF_ENABLE_TIME, default="20ms" + ): cv.positive_time_period_milliseconds, + cv.Optional( + CONF_KEEP_ON_TIME, default="10s" + ): cv.positive_time_period_milliseconds, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): @@ -25,4 +31,4 @@ def to_code(config): cg.add(var.set_enable_time(config[CONF_ENABLE_TIME])) cg.add(var.set_keep_on_time(config[CONF_KEEP_ON_TIME])) - cg.add_define('USE_POWER_SUPPLY') + cg.add_define("USE_POWER_SUPPLY") diff --git a/esphome/components/prometheus/__init__.py b/esphome/components/prometheus/__init__.py index 9c3deef73..a1b376c76 100644 --- a/esphome/components/prometheus/__init__.py +++ b/esphome/components/prometheus/__init__.py @@ -4,21 +4,25 @@ from esphome.const import CONF_ID from esphome.components.web_server_base import CONF_WEB_SERVER_BASE_ID from esphome.components import web_server_base -AUTO_LOAD = ['web_server_base'] +AUTO_LOAD = ["web_server_base"] -prometheus_ns = cg.esphome_ns.namespace('prometheus') -PrometheusHandler = prometheus_ns.class_('PrometheusHandler', cg.Component) +prometheus_ns = cg.esphome_ns.namespace("prometheus") +PrometheusHandler = prometheus_ns.class_("PrometheusHandler", cg.Component) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(PrometheusHandler), - 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(PrometheusHandler), + cv.GenerateID(CONF_WEB_SERVER_BASE_ID): cv.use_id( + web_server_base.WebServerBase + ), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): paren = yield cg.get_variable(config[CONF_WEB_SERVER_BASE_ID]) - cg.add_define('USE_PROMETHEUS') + cg.add_define("USE_PROMETHEUS") var = cg.new_Pvariable(config[CONF_ID], paren) yield cg.register_component(var, config) diff --git a/esphome/components/pulse_counter/sensor.py b/esphome/components/pulse_counter/sensor.py index a6f54872d..0dff2959e 100644 --- a/esphome/components/pulse_counter/sensor.py +++ b/esphome/components/pulse_counter/sensor.py @@ -2,23 +2,35 @@ 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_COUNT_MODE, CONF_FALLING_EDGE, CONF_ID, CONF_INTERNAL_FILTER, \ - CONF_PIN, CONF_RISING_EDGE, CONF_NUMBER, CONF_TOTAL, DEVICE_CLASS_EMPTY, \ - ICON_PULSE, UNIT_PULSES_PER_MINUTE, UNIT_PULSES +from esphome.const import ( + CONF_COUNT_MODE, + CONF_FALLING_EDGE, + CONF_ID, + CONF_INTERNAL_FILTER, + CONF_PIN, + CONF_RISING_EDGE, + CONF_NUMBER, + CONF_TOTAL, + DEVICE_CLASS_EMPTY, + ICON_PULSE, + UNIT_PULSES_PER_MINUTE, + UNIT_PULSES, +) from esphome.core import CORE -pulse_counter_ns = cg.esphome_ns.namespace('pulse_counter') -PulseCounterCountMode = pulse_counter_ns.enum('PulseCounterCountMode') +pulse_counter_ns = cg.esphome_ns.namespace("pulse_counter") +PulseCounterCountMode = pulse_counter_ns.enum("PulseCounterCountMode") COUNT_MODES = { - 'DISABLE': PulseCounterCountMode.PULSE_COUNTER_DISABLE, - 'INCREMENT': PulseCounterCountMode.PULSE_COUNTER_INCREMENT, - 'DECREMENT': PulseCounterCountMode.PULSE_COUNTER_DECREMENT, + "DISABLE": PulseCounterCountMode.PULSE_COUNTER_DISABLE, + "INCREMENT": PulseCounterCountMode.PULSE_COUNTER_INCREMENT, + "DECREMENT": PulseCounterCountMode.PULSE_COUNTER_DECREMENT, } COUNT_MODE_SCHEMA = cv.enum(COUNT_MODES, upper=True) -PulseCounterSensor = pulse_counter_ns.class_('PulseCounterSensor', - sensor.Sensor, cg.PollingComponent) +PulseCounterSensor = pulse_counter_ns.class_( + "PulseCounterSensor", sensor.Sensor, cg.PollingComponent +) def validate_internal_filter(value): @@ -34,35 +46,52 @@ def validate_internal_filter(value): def validate_pulse_counter_pin(value): value = pins.internal_gpio_input_pin_schema(value) if CORE.is_esp8266 and value[CONF_NUMBER] >= 16: - raise cv.Invalid("Pins GPIO16 and GPIO17 cannot be used as pulse counters on ESP8266.") + raise cv.Invalid( + "Pins GPIO16 and GPIO17 cannot be used as pulse counters on ESP8266." + ) return value def validate_count_mode(value): rising_edge = value[CONF_RISING_EDGE] falling_edge = value[CONF_FALLING_EDGE] - if rising_edge == 'DISABLE' and falling_edge == 'DISABLE': - raise cv.Invalid("Can't set both count modes to DISABLE! This means no counting occurs at " - "all!") + if rising_edge == "DISABLE" and falling_edge == "DISABLE": + raise cv.Invalid( + "Can't set both count modes to DISABLE! This means no counting occurs at " + "all!" + ) return value -CONFIG_SCHEMA = sensor.sensor_schema( - UNIT_PULSES_PER_MINUTE, ICON_PULSE, 2, DEVICE_CLASS_EMPTY -).extend({ - cv.GenerateID(): cv.declare_id(PulseCounterSensor), - cv.Required(CONF_PIN): validate_pulse_counter_pin, - cv.Optional(CONF_COUNT_MODE, default={ - CONF_RISING_EDGE: 'INCREMENT', - CONF_FALLING_EDGE: 'DISABLE', - }): cv.All(cv.Schema({ - cv.Required(CONF_RISING_EDGE): COUNT_MODE_SCHEMA, - cv.Required(CONF_FALLING_EDGE): COUNT_MODE_SCHEMA, - }), validate_count_mode), - cv.Optional(CONF_INTERNAL_FILTER, default='13us'): validate_internal_filter, - cv.Optional(CONF_TOTAL): sensor.sensor_schema(UNIT_PULSES, ICON_PULSE, 0, DEVICE_CLASS_EMPTY), - -}).extend(cv.polling_component_schema('60s')) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_PULSES_PER_MINUTE, ICON_PULSE, 2, DEVICE_CLASS_EMPTY) + .extend( + { + cv.GenerateID(): cv.declare_id(PulseCounterSensor), + cv.Required(CONF_PIN): validate_pulse_counter_pin, + cv.Optional( + CONF_COUNT_MODE, + default={ + CONF_RISING_EDGE: "INCREMENT", + CONF_FALLING_EDGE: "DISABLE", + }, + ): cv.All( + cv.Schema( + { + cv.Required(CONF_RISING_EDGE): COUNT_MODE_SCHEMA, + cv.Required(CONF_FALLING_EDGE): COUNT_MODE_SCHEMA, + } + ), + validate_count_mode, + ), + cv.Optional(CONF_INTERNAL_FILTER, default="13us"): validate_internal_filter, + cv.Optional(CONF_TOTAL): sensor.sensor_schema( + UNIT_PULSES, ICON_PULSE, 0, DEVICE_CLASS_EMPTY + ), + } + ) + .extend(cv.polling_component_schema("60s")) +) def to_code(config): diff --git a/esphome/components/pulse_width/sensor.py b/esphome/components/pulse_width/sensor.py index 01a1c0524..228c5f8df 100644 --- a/esphome/components/pulse_width/sensor.py +++ b/esphome/components/pulse_width/sensor.py @@ -4,15 +4,24 @@ from esphome import pins from esphome.components import sensor from esphome.const import CONF_ID, CONF_PIN, DEVICE_CLASS_EMPTY, UNIT_SECOND, ICON_TIMER -pulse_width_ns = cg.esphome_ns.namespace('pulse_width') +pulse_width_ns = cg.esphome_ns.namespace("pulse_width") -PulseWidthSensor = pulse_width_ns.class_('PulseWidthSensor', sensor.Sensor, cg.PollingComponent) +PulseWidthSensor = pulse_width_ns.class_( + "PulseWidthSensor", sensor.Sensor, cg.PollingComponent +) -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_SECOND, ICON_TIMER, 3, DEVICE_CLASS_EMPTY).extend({ - cv.GenerateID(): cv.declare_id(PulseWidthSensor), - 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_SECOND, ICON_TIMER, 3, DEVICE_CLASS_EMPTY) + .extend( + { + cv.GenerateID(): cv.declare_id(PulseWidthSensor), + 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): diff --git a/esphome/components/pzem004t/sensor.py b/esphome/components/pzem004t/sensor.py index ed7158c05..1228fc4ab 100644 --- a/esphome/components/pzem004t/sensor.py +++ b/esphome/components/pzem004t/sensor.py @@ -1,25 +1,49 @@ 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, CONF_ENERGY, \ - DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, DEVICE_CLASS_POWER, DEVICE_CLASS_VOLTAGE, \ - ICON_EMPTY, UNIT_VOLT, UNIT_AMPERE, UNIT_WATT, UNIT_WATT_HOURS +from esphome.const import ( + CONF_CURRENT, + CONF_ID, + CONF_POWER, + CONF_VOLTAGE, + CONF_ENERGY, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_ENERGY, + DEVICE_CLASS_POWER, + DEVICE_CLASS_VOLTAGE, + ICON_EMPTY, + UNIT_VOLT, + UNIT_AMPERE, + UNIT_WATT, + UNIT_WATT_HOURS, +) -DEPENDENCIES = ['uart'] +DEPENDENCIES = ["uart"] -pzem004t_ns = cg.esphome_ns.namespace('pzem004t') -PZEM004T = pzem004t_ns.class_('PZEM004T', cg.PollingComponent, uart.UARTDevice) +pzem004t_ns = cg.esphome_ns.namespace("pzem004t") +PZEM004T = pzem004t_ns.class_("PZEM004T", cg.PollingComponent, uart.UARTDevice) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(PZEM004T), - - 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, 0, DEVICE_CLASS_POWER), - cv.Optional(CONF_ENERGY): sensor.sensor_schema(UNIT_WATT_HOURS, ICON_EMPTY, 0, - DEVICE_CLASS_ENERGY) -}).extend(cv.polling_component_schema('60s')).extend(uart.UART_DEVICE_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(PZEM004T), + 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, 0, DEVICE_CLASS_POWER + ), + cv.Optional(CONF_ENERGY): sensor.sensor_schema( + UNIT_WATT_HOURS, ICON_EMPTY, 0, DEVICE_CLASS_ENERGY + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(uart.UART_DEVICE_SCHEMA) +) def to_code(config): diff --git a/esphome/components/pzemac/sensor.py b/esphome/components/pzemac/sensor.py index 1004d4917..aa30549c2 100644 --- a/esphome/components/pzemac/sensor.py +++ b/esphome/components/pzemac/sensor.py @@ -1,30 +1,62 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, modbus -from esphome.const import CONF_CURRENT, CONF_ENERGY, CONF_ID, CONF_POWER, CONF_VOLTAGE, \ - CONF_FREQUENCY, CONF_POWER_FACTOR, DEVICE_CLASS_EMPTY, DEVICE_CLASS_POWER_FACTOR, \ - DEVICE_CLASS_VOLTAGE, DEVICE_CLASS_CURRENT, DEVICE_CLASS_POWER, DEVICE_CLASS_ENERGY, \ - ICON_EMPTY, ICON_CURRENT_AC, UNIT_HERTZ, UNIT_VOLT, UNIT_AMPERE, UNIT_WATT, UNIT_EMPTY, \ - UNIT_WATT_HOURS +from esphome.const import ( + CONF_CURRENT, + CONF_ENERGY, + CONF_ID, + CONF_POWER, + CONF_VOLTAGE, + CONF_FREQUENCY, + CONF_POWER_FACTOR, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_POWER_FACTOR, + DEVICE_CLASS_VOLTAGE, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_POWER, + DEVICE_CLASS_ENERGY, + ICON_EMPTY, + ICON_CURRENT_AC, + UNIT_HERTZ, + UNIT_VOLT, + UNIT_AMPERE, + UNIT_WATT, + UNIT_EMPTY, + UNIT_WATT_HOURS, +) -AUTO_LOAD = ['modbus'] +AUTO_LOAD = ["modbus"] -pzemac_ns = cg.esphome_ns.namespace('pzemac') -PZEMAC = pzemac_ns.class_('PZEMAC', cg.PollingComponent, modbus.ModbusDevice) +pzemac_ns = cg.esphome_ns.namespace("pzemac") +PZEMAC = pzemac_ns.class_("PZEMAC", cg.PollingComponent, modbus.ModbusDevice) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(PZEMAC), - 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, 3, - DEVICE_CLASS_CURRENT), - cv.Optional(CONF_POWER): sensor.sensor_schema(UNIT_WATT, ICON_EMPTY, 2, DEVICE_CLASS_POWER), - cv.Optional(CONF_ENERGY): sensor.sensor_schema(UNIT_WATT_HOURS, ICON_EMPTY, 0, - DEVICE_CLASS_ENERGY), - cv.Optional(CONF_FREQUENCY): sensor.sensor_schema(UNIT_HERTZ, ICON_CURRENT_AC, 1, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_POWER_FACTOR): sensor.sensor_schema(UNIT_EMPTY, ICON_EMPTY, 2, - DEVICE_CLASS_POWER_FACTOR), -}).extend(cv.polling_component_schema('60s')).extend(modbus.modbus_device_schema(0x01)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(PZEMAC), + 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, 3, DEVICE_CLASS_CURRENT + ), + cv.Optional(CONF_POWER): sensor.sensor_schema( + UNIT_WATT, ICON_EMPTY, 2, DEVICE_CLASS_POWER + ), + cv.Optional(CONF_ENERGY): sensor.sensor_schema( + UNIT_WATT_HOURS, ICON_EMPTY, 0, DEVICE_CLASS_ENERGY + ), + cv.Optional(CONF_FREQUENCY): sensor.sensor_schema( + UNIT_HERTZ, ICON_CURRENT_AC, 1, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_POWER_FACTOR): sensor.sensor_schema( + UNIT_EMPTY, ICON_EMPTY, 2, DEVICE_CLASS_POWER_FACTOR + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(modbus.modbus_device_schema(0x01)) +) def to_code(config): diff --git a/esphome/components/pzemdc/sensor.py b/esphome/components/pzemdc/sensor.py index a4fc9ab26..962c97035 100644 --- a/esphome/components/pzemdc/sensor.py +++ b/esphome/components/pzemdc/sensor.py @@ -1,22 +1,43 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, modbus -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, +) -AUTO_LOAD = ['modbus'] +AUTO_LOAD = ["modbus"] -pzemdc_ns = cg.esphome_ns.namespace('pzemdc') -PZEMDC = pzemdc_ns.class_('PZEMDC', cg.PollingComponent, modbus.ModbusDevice) +pzemdc_ns = cg.esphome_ns.namespace("pzemdc") +PZEMDC = pzemdc_ns.class_("PZEMDC", cg.PollingComponent, modbus.ModbusDevice) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(PZEMDC), - 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, 3, - 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(modbus.modbus_device_schema(0x01)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(PZEMDC), + 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, 3, 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(modbus.modbus_device_schema(0x01)) +) def to_code(config): diff --git a/esphome/components/qmc5883l/sensor.py b/esphome/components/qmc5883l/sensor.py index 3beaa8bd7..435942762 100644 --- a/esphome/components/qmc5883l/sensor.py +++ b/esphome/components/qmc5883l/sensor.py @@ -1,23 +1,33 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, sensor -from esphome.const import CONF_ADDRESS, CONF_ID, CONF_OVERSAMPLING, CONF_RANGE, \ - DEVICE_CLASS_EMPTY, ICON_MAGNET, UNIT_MICROTESLA, UNIT_DEGREES, ICON_SCREEN_ROTATION, \ - CONF_UPDATE_INTERVAL +from esphome.const import ( + CONF_ADDRESS, + CONF_ID, + CONF_OVERSAMPLING, + CONF_RANGE, + DEVICE_CLASS_EMPTY, + ICON_MAGNET, + UNIT_MICROTESLA, + UNIT_DEGREES, + ICON_SCREEN_ROTATION, + CONF_UPDATE_INTERVAL, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -qmc5883l_ns = cg.esphome_ns.namespace('qmc5883l') +qmc5883l_ns = cg.esphome_ns.namespace("qmc5883l") -CONF_FIELD_STRENGTH_X = 'field_strength_x' -CONF_FIELD_STRENGTH_Y = 'field_strength_y' -CONF_FIELD_STRENGTH_Z = 'field_strength_z' -CONF_HEADING = 'heading' +CONF_FIELD_STRENGTH_X = "field_strength_x" +CONF_FIELD_STRENGTH_Y = "field_strength_y" +CONF_FIELD_STRENGTH_Z = "field_strength_z" +CONF_HEADING = "heading" QMC5883LComponent = qmc5883l_ns.class_( - 'QMC5883LComponent', cg.PollingComponent, i2c.I2CDevice) + "QMC5883LComponent", cg.PollingComponent, i2c.I2CDevice +) -QMC5883LDatarate = qmc5883l_ns.enum('QMC5883LDatarate') +QMC5883LDatarate = qmc5883l_ns.enum("QMC5883LDatarate") QMC5883LDatarates = { 10: QMC5883LDatarate.QMC5883L_DATARATE_10_HZ, 50: QMC5883LDatarate.QMC5883L_DATARATE_50_HZ, @@ -25,13 +35,13 @@ QMC5883LDatarates = { 200: QMC5883LDatarate.QMC5883L_DATARATE_200_HZ, } -QMC5883LRange = qmc5883l_ns.enum('QMC5883LRange') +QMC5883LRange = qmc5883l_ns.enum("QMC5883LRange") QMC5883L_RANGES = { 200: QMC5883LRange.QMC5883L_RANGE_200_UT, 800: QMC5883LRange.QMC5883L_RANGE_800_UT, } -QMC5883LOversampling = qmc5883l_ns.enum('QMC5883LOversampling') +QMC5883LOversampling = qmc5883l_ns.enum("QMC5883LOversampling") QMC5883LOversamplings = { 512: QMC5883LOversampling.QMC5883L_SAMPLING_512, 256: QMC5883LOversampling.QMC5883L_SAMPLING_256, @@ -51,30 +61,45 @@ def validate_enum(enum_values, units=None, int=True): value = cv.string(value) for unit in _units: if value.endswith(unit): - value = value[:-len(unit)] + value = value[: -len(unit)] break return enum_bound(value) + return validate_enum_bound -field_strength_schema = sensor.sensor_schema(UNIT_MICROTESLA, ICON_MAGNET, 1, DEVICE_CLASS_EMPTY) -heading_schema = sensor.sensor_schema(UNIT_DEGREES, ICON_SCREEN_ROTATION, 1, DEVICE_CLASS_EMPTY) +field_strength_schema = sensor.sensor_schema( + UNIT_MICROTESLA, ICON_MAGNET, 1, DEVICE_CLASS_EMPTY +) +heading_schema = sensor.sensor_schema( + UNIT_DEGREES, ICON_SCREEN_ROTATION, 1, DEVICE_CLASS_EMPTY +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(QMC5883LComponent), - cv.Optional(CONF_ADDRESS): cv.i2c_address, - cv.Optional(CONF_RANGE, default='200µT'): validate_enum(QMC5883L_RANGES, units=["uT", "µT"]), - cv.Optional(CONF_OVERSAMPLING, default="512x"): validate_enum(QMC5883LOversamplings, units="x"), - cv.Optional(CONF_FIELD_STRENGTH_X): field_strength_schema, - cv.Optional(CONF_FIELD_STRENGTH_Y): field_strength_schema, - cv.Optional(CONF_FIELD_STRENGTH_Z): field_strength_schema, - cv.Optional(CONF_HEADING): heading_schema, -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x0D)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(QMC5883LComponent), + cv.Optional(CONF_ADDRESS): cv.i2c_address, + cv.Optional(CONF_RANGE, default="200µT"): validate_enum( + QMC5883L_RANGES, units=["uT", "µT"] + ), + cv.Optional(CONF_OVERSAMPLING, default="512x"): validate_enum( + QMC5883LOversamplings, units="x" + ), + cv.Optional(CONF_FIELD_STRENGTH_X): field_strength_schema, + cv.Optional(CONF_FIELD_STRENGTH_Y): field_strength_schema, + cv.Optional(CONF_FIELD_STRENGTH_Z): field_strength_schema, + cv.Optional(CONF_HEADING): heading_schema, + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x0D)) +) def auto_data_rate(config): interval_sec = config[CONF_UPDATE_INTERVAL].seconds - interval_hz = 1.0/interval_sec + interval_hz = 1.0 / interval_sec for datarate in sorted(QMC5883LDatarates.keys()): if float(datarate) >= interval_hz: return QMC5883LDatarates[datarate] diff --git a/esphome/components/rc522/__init__.py b/esphome/components/rc522/__init__.py index 7b4df37ce..970b867e7 100644 --- a/esphome/components/rc522/__init__.py +++ b/esphome/components/rc522/__init__.py @@ -5,23 +5,29 @@ from esphome.components import i2c from esphome.const import CONF_ON_TAG, CONF_TRIGGER_ID, CONF_RESET_PIN from esphome.core import coroutine -CODEOWNERS = ['@glmnet'] -AUTO_LOAD = ['binary_sensor'] +CODEOWNERS = ["@glmnet"] +AUTO_LOAD = ["binary_sensor"] MULTI_CONF = True -CONF_RC522_ID = 'rc522_id' +CONF_RC522_ID = "rc522_id" -rc522_ns = cg.esphome_ns.namespace('rc522') -RC522 = rc522_ns.class_('RC522', cg.PollingComponent, i2c.I2CDevice) -RC522Trigger = rc522_ns.class_('RC522Trigger', automation.Trigger.template(cg.std_string)) +rc522_ns = cg.esphome_ns.namespace("rc522") +RC522 = rc522_ns.class_("RC522", cg.PollingComponent, i2c.I2CDevice) +RC522Trigger = rc522_ns.class_( + "RC522Trigger", automation.Trigger.template(cg.std_string) +) -RC522_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(RC522), - cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_ON_TAG): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(RC522Trigger), - }), -}).extend(cv.polling_component_schema('1s')) +RC522_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(RC522), + cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_ON_TAG): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(RC522Trigger), + } + ), + } +).extend(cv.polling_component_schema("1s")) @coroutine @@ -35,4 +41,4 @@ def setup_rc522(var, config): for conf in config.get(CONF_ON_TAG, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID]) cg.add(var.register_trigger(trigger)) - yield automation.build_automation(trigger, [(cg.std_string, 'x')], conf) + yield automation.build_automation(trigger, [(cg.std_string, "x")], conf) diff --git a/esphome/components/rc522/binary_sensor.py b/esphome/components/rc522/binary_sensor.py index 675db2f13..89eef2f97 100644 --- a/esphome/components/rc522/binary_sensor.py +++ b/esphome/components/rc522/binary_sensor.py @@ -5,31 +5,39 @@ from esphome.const import CONF_UID, CONF_ID from esphome.core import HexInt, coroutine from . import rc522_ns, RC522, CONF_RC522_ID -DEPENDENCIES = ['rc522'] +DEPENDENCIES = ["rc522"] def validate_uid(value): value = cv.string_strict(value) - for x in value.split('-'): + for x in value.split("-"): if len(x) != 2: - raise cv.Invalid("Each part (separated by '-') of the UID must be two characters " - "long.") + raise cv.Invalid( + "Each part (separated by '-') of the UID must be two characters " + "long." + ) try: x = int(x, 16) except ValueError as err: - raise cv.Invalid("Valid characters for parts of a UID are 0123456789ABCDEF.") from err + raise cv.Invalid( + "Valid characters for parts of a UID are 0123456789ABCDEF." + ) from err if x < 0 or x > 255: - raise cv.Invalid("Valid values for UID parts (separated by '-') are 00 to FF") + raise cv.Invalid( + "Valid values for UID parts (separated by '-') are 00 to FF" + ) return value -RC522BinarySensor = rc522_ns.class_('RC522BinarySensor', binary_sensor.BinarySensor) +RC522BinarySensor = rc522_ns.class_("RC522BinarySensor", binary_sensor.BinarySensor) -CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(RC522BinarySensor), - cv.GenerateID(CONF_RC522_ID): cv.use_id(RC522), - cv.Required(CONF_UID): validate_uid, -}) +CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(RC522BinarySensor), + cv.GenerateID(CONF_RC522_ID): cv.use_id(RC522), + cv.Required(CONF_UID): validate_uid, + } +) @coroutine @@ -39,5 +47,5 @@ def to_code(config): hub = yield cg.get_variable(config[CONF_RC522_ID]) cg.add(hub.register_tag(var)) - addr = [HexInt(int(x, 16)) for x in config[CONF_UID].split('-')] + addr = [HexInt(int(x, 16)) for x in config[CONF_UID].split("-")] cg.add(var.set_uid(addr)) diff --git a/esphome/components/rc522_i2c/__init__.py b/esphome/components/rc522_i2c/__init__.py index c5bb72ee5..532adfce7 100644 --- a/esphome/components/rc522_i2c/__init__.py +++ b/esphome/components/rc522_i2c/__init__.py @@ -3,17 +3,21 @@ import esphome.config_validation as cv from esphome.components import i2c, rc522 from esphome.const import CONF_ID -CODEOWNERS = ['@glmnet'] -DEPENDENCIES = ['i2c'] -AUTO_LOAD = ['rc522'] +CODEOWNERS = ["@glmnet"] +DEPENDENCIES = ["i2c"] +AUTO_LOAD = ["rc522"] -rc522_i2c_ns = cg.esphome_ns.namespace('rc522_i2c') -RC522I2C = rc522_i2c_ns.class_('RC522I2C', rc522.RC522, i2c.I2CDevice) +rc522_i2c_ns = cg.esphome_ns.namespace("rc522_i2c") +RC522I2C = rc522_i2c_ns.class_("RC522I2C", rc522.RC522, i2c.I2CDevice) -CONFIG_SCHEMA = cv.All(rc522.RC522_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(RC522I2C), -}).extend(i2c.i2c_device_schema(0x2c))) +CONFIG_SCHEMA = cv.All( + rc522.RC522_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(RC522I2C), + } + ).extend(i2c.i2c_device_schema(0x2C)) +) def to_code(config): diff --git a/esphome/components/rc522_spi/__init__.py b/esphome/components/rc522_spi/__init__.py index 37f78b66d..6ae163bcb 100644 --- a/esphome/components/rc522_spi/__init__.py +++ b/esphome/components/rc522_spi/__init__.py @@ -3,16 +3,20 @@ import esphome.config_validation as cv from esphome.components import spi, rc522 from esphome.const import CONF_ID -CODEOWNERS = ['@glmnet'] -DEPENDENCIES = ['spi'] -AUTO_LOAD = ['rc522'] +CODEOWNERS = ["@glmnet"] +DEPENDENCIES = ["spi"] +AUTO_LOAD = ["rc522"] -rc522_spi_ns = cg.esphome_ns.namespace('rc522_spi') -RC522Spi = rc522_spi_ns.class_('RC522Spi', rc522.RC522, spi.SPIDevice) +rc522_spi_ns = cg.esphome_ns.namespace("rc522_spi") +RC522Spi = rc522_spi_ns.class_("RC522Spi", rc522.RC522, spi.SPIDevice) -CONFIG_SCHEMA = cv.All(rc522.RC522_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(RC522Spi), -}).extend(spi.spi_device_schema(cs_pin_required=True))) +CONFIG_SCHEMA = cv.All( + rc522.RC522_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(RC522Spi), + } + ).extend(spi.spi_device_schema(cs_pin_required=True)) +) def to_code(config): diff --git a/esphome/components/rc522_spi/binary_sensor.py b/esphome/components/rc522_spi/binary_sensor.py index 1f0eafe6a..f5400a233 100644 --- a/esphome/components/rc522_spi/binary_sensor.py +++ b/esphome/components/rc522_spi/binary_sensor.py @@ -1,6 +1,6 @@ import esphome.components.rc522.binary_sensor as rc522_binary_sensor -DEPENDENCIES = ['rc522'] +DEPENDENCIES = ["rc522"] CONFIG_SCHEMA = rc522_binary_sensor.CONFIG_SCHEMA diff --git a/esphome/components/rdm6300/__init__.py b/esphome/components/rdm6300/__init__.py index ee5077c31..a416d95a1 100644 --- a/esphome/components/rdm6300/__init__.py +++ b/esphome/components/rdm6300/__init__.py @@ -4,19 +4,29 @@ from esphome import automation from esphome.components import uart from esphome.const import CONF_ID, CONF_ON_TAG, CONF_TRIGGER_ID -DEPENDENCIES = ['uart'] -AUTO_LOAD = ['binary_sensor'] +DEPENDENCIES = ["uart"] +AUTO_LOAD = ["binary_sensor"] -rdm6300_ns = cg.esphome_ns.namespace('rdm6300') -RDM6300Component = rdm6300_ns.class_('RDM6300Component', cg.Component, uart.UARTDevice) -RDM6300Trigger = rdm6300_ns.class_('RDM6300Trigger', automation.Trigger.template(cg.uint32)) +rdm6300_ns = cg.esphome_ns.namespace("rdm6300") +RDM6300Component = rdm6300_ns.class_("RDM6300Component", cg.Component, uart.UARTDevice) +RDM6300Trigger = rdm6300_ns.class_( + "RDM6300Trigger", automation.Trigger.template(cg.uint32) +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(RDM6300Component), - cv.Optional(CONF_ON_TAG): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(RDM6300Trigger), - }), -}).extend(cv.COMPONENT_SCHEMA).extend(uart.UART_DEVICE_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(RDM6300Component), + cv.Optional(CONF_ON_TAG): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(RDM6300Trigger), + } + ), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(uart.UART_DEVICE_SCHEMA) +) def to_code(config): @@ -27,4 +37,4 @@ def to_code(config): for conf in config.get(CONF_ON_TAG, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID]) cg.add(var.register_trigger(trigger)) - yield automation.build_automation(trigger, [(cg.uint32, 'x')], conf) + yield automation.build_automation(trigger, [(cg.uint32, "x")], conf) diff --git a/esphome/components/rdm6300/binary_sensor.py b/esphome/components/rdm6300/binary_sensor.py index 81b24bed0..02e0b6ceb 100644 --- a/esphome/components/rdm6300/binary_sensor.py +++ b/esphome/components/rdm6300/binary_sensor.py @@ -4,16 +4,20 @@ from esphome.components import binary_sensor, rdm6300 from esphome.const import CONF_UID, CONF_ID from . import rdm6300_ns -DEPENDENCIES = ['rdm6300'] +DEPENDENCIES = ["rdm6300"] -CONF_RDM6300_ID = 'rdm6300_id' -RDM6300BinarySensor = rdm6300_ns.class_('RDM6300BinarySensor', binary_sensor.BinarySensor) +CONF_RDM6300_ID = "rdm6300_id" +RDM6300BinarySensor = rdm6300_ns.class_( + "RDM6300BinarySensor", binary_sensor.BinarySensor +) -CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(RDM6300BinarySensor), - cv.GenerateID(CONF_RDM6300_ID): cv.use_id(rdm6300.RDM6300Component), - cv.Required(CONF_UID): cv.uint32_t, -}) +CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(RDM6300BinarySensor), + cv.GenerateID(CONF_RDM6300_ID): cv.use_id(rdm6300.RDM6300Component), + cv.Required(CONF_UID): cv.uint32_t, + } +) def to_code(config): diff --git a/esphome/components/remote_base/__init__.py b/esphome/components/remote_base/__init__.py index cc48ffc5b..7e81daa1e 100644 --- a/esphome/components/remote_base/__init__.py +++ b/esphome/components/remote_base/__init__.py @@ -2,29 +2,55 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.components import binary_sensor -from esphome.const import CONF_DATA, CONF_TRIGGER_ID, CONF_NBITS, CONF_ADDRESS, \ - CONF_COMMAND, CONF_CODE, CONF_PULSE_LENGTH, CONF_SYNC, CONF_ZERO, CONF_ONE, CONF_INVERTED, \ - CONF_PROTOCOL, CONF_GROUP, CONF_DEVICE, CONF_STATE, CONF_CHANNEL, CONF_FAMILY, CONF_REPEAT, \ - CONF_WAIT_TIME, CONF_TIMES, CONF_TYPE_ID, CONF_CARRIER_FREQUENCY, CONF_RC_CODE_1, CONF_RC_CODE_2 +from esphome.const import ( + CONF_DATA, + CONF_TRIGGER_ID, + CONF_NBITS, + CONF_ADDRESS, + CONF_COMMAND, + CONF_CODE, + CONF_PULSE_LENGTH, + CONF_SYNC, + CONF_ZERO, + CONF_ONE, + CONF_INVERTED, + CONF_PROTOCOL, + CONF_GROUP, + CONF_DEVICE, + CONF_STATE, + CONF_CHANNEL, + CONF_FAMILY, + CONF_REPEAT, + CONF_WAIT_TIME, + CONF_TIMES, + CONF_TYPE_ID, + CONF_CARRIER_FREQUENCY, + CONF_RC_CODE_1, + CONF_RC_CODE_2, +) from esphome.core import coroutine from esphome.util import Registry, SimpleRegistry -AUTO_LOAD = ['binary_sensor'] +AUTO_LOAD = ["binary_sensor"] -CONF_RECEIVER_ID = 'receiver_id' -CONF_TRANSMITTER_ID = 'transmitter_id' +CONF_RECEIVER_ID = "receiver_id" +CONF_TRANSMITTER_ID = "transmitter_id" -ns = remote_base_ns = cg.esphome_ns.namespace('remote_base') -RemoteProtocol = ns.class_('RemoteProtocol') -RemoteReceiverListener = ns.class_('RemoteReceiverListener') -RemoteReceiverBinarySensorBase = ns.class_('RemoteReceiverBinarySensorBase', - binary_sensor.BinarySensor, cg.Component) -RemoteReceiverTrigger = ns.class_('RemoteReceiverTrigger', automation.Trigger, - RemoteReceiverListener) -RemoteTransmitterDumper = ns.class_('RemoteTransmitterDumper') -RemoteTransmitterActionBase = ns.class_('RemoteTransmitterActionBase', automation.Action) -RemoteReceiverBase = ns.class_('RemoteReceiverBase') -RemoteTransmitterBase = ns.class_('RemoteTransmitterBase') +ns = remote_base_ns = cg.esphome_ns.namespace("remote_base") +RemoteProtocol = ns.class_("RemoteProtocol") +RemoteReceiverListener = ns.class_("RemoteReceiverListener") +RemoteReceiverBinarySensorBase = ns.class_( + "RemoteReceiverBinarySensorBase", binary_sensor.BinarySensor, cg.Component +) +RemoteReceiverTrigger = ns.class_( + "RemoteReceiverTrigger", automation.Trigger, RemoteReceiverListener +) +RemoteTransmitterDumper = ns.class_("RemoteTransmitterDumper") +RemoteTransmitterActionBase = ns.class_( + "RemoteTransmitterActionBase", automation.Action +) +RemoteReceiverBase = ns.class_("RemoteReceiverBase") +RemoteTransmitterBase = ns.class_("RemoteTransmitterBase") def templatize(value): @@ -47,11 +73,13 @@ def register_binary_sensor(name, type, schema): def register_trigger(name, type, data_type): - validator = automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(type), - cv.GenerateID(CONF_RECEIVER_ID): cv.use_id(RemoteReceiverBase), - }) - registerer = TRIGGER_REGISTRY.register(f'on_{name}', validator) + validator = automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(type), + cv.GenerateID(CONF_RECEIVER_ID): cv.use_id(RemoteReceiverBase), + } + ) + registerer = TRIGGER_REGISTRY.register(f"on_{name}", validator) def decorator(func): @coroutine @@ -59,7 +87,7 @@ def register_trigger(name, type, data_type): var = cg.new_Pvariable(config[CONF_TRIGGER_ID]) yield register_listener(var, config) yield coroutine(func)(var, config) - yield automation.build_automation(var, [(data_type, 'x')], config) + yield automation.build_automation(var, [(data_type, "x")], config) yield var return registerer(new_func) @@ -84,21 +112,27 @@ def register_dumper(name, type): def validate_repeat(value): if isinstance(value, dict): - return cv.Schema({ - cv.Required(CONF_TIMES): cv.templatable(cv.positive_int), - cv.Optional(CONF_WAIT_TIME, default='25ms'): - cv.templatable(cv.positive_time_period_microseconds), - })(value) + return cv.Schema( + { + cv.Required(CONF_TIMES): cv.templatable(cv.positive_int), + cv.Optional(CONF_WAIT_TIME, default="25ms"): cv.templatable( + cv.positive_time_period_microseconds + ), + } + )(value) return validate_repeat({CONF_TIMES: value}) def register_action(name, type_, schema): - validator = templatize(schema).extend({ - cv.GenerateID(CONF_TRANSMITTER_ID): cv.use_id(RemoteTransmitterBase), - cv.Optional(CONF_REPEAT): validate_repeat, - }) - registerer = automation.register_action(f'remote_transmitter.transmit_{name}', - type_, validator) + validator = templatize(schema).extend( + { + cv.GenerateID(CONF_TRANSMITTER_ID): cv.use_id(RemoteTransmitterBase), + cv.Optional(CONF_REPEAT): validate_repeat, + } + ) + registerer = automation.register_action( + f"remote_transmitter.transmit_{name}", type_, validator + ) def decorator(func): @coroutine @@ -121,28 +155,36 @@ def register_action(name, type_, schema): def declare_protocol(name): - data = ns.struct(f'{name}Data') - binary_sensor_ = ns.class_(f'{name}BinarySensor', RemoteReceiverBinarySensorBase) - trigger = ns.class_(f'{name}Trigger', RemoteReceiverTrigger) - action = ns.class_(f'{name}Action', RemoteTransmitterActionBase) - dumper = ns.class_(f'{name}Dumper', RemoteTransmitterDumper) + data = ns.struct(f"{name}Data") + binary_sensor_ = ns.class_(f"{name}BinarySensor", RemoteReceiverBinarySensorBase) + trigger = ns.class_(f"{name}Trigger", RemoteReceiverTrigger) + action = ns.class_(f"{name}Action", RemoteTransmitterActionBase) + dumper = ns.class_(f"{name}Dumper", RemoteTransmitterDumper) return data, binary_sensor_, trigger, action, dumper -BINARY_SENSOR_REGISTRY = Registry(binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.GenerateID(CONF_RECEIVER_ID): cv.use_id(RemoteReceiverBase), -})) -validate_binary_sensor = cv.validate_registry_entry('remote receiver', BINARY_SENSOR_REGISTRY) +BINARY_SENSOR_REGISTRY = Registry( + binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(CONF_RECEIVER_ID): cv.use_id(RemoteReceiverBase), + } + ) +) +validate_binary_sensor = cv.validate_registry_entry( + "remote receiver", BINARY_SENSOR_REGISTRY +) TRIGGER_REGISTRY = SimpleRegistry() -DUMPER_REGISTRY = Registry({ - cv.GenerateID(CONF_RECEIVER_ID): cv.use_id(RemoteReceiverBase), -}) +DUMPER_REGISTRY = Registry( + { + cv.GenerateID(CONF_RECEIVER_ID): cv.use_id(RemoteReceiverBase), + } +) def validate_dumpers(value): - if isinstance(value, str) and value.lower() == 'all': + if isinstance(value, str) and value.lower() == "all": return validate_dumpers(list(DUMPER_REGISTRY.keys())) - return cv.validate_registry('dumper', DUMPER_REGISTRY)(value) + return cv.validate_registry("dumper", DUMPER_REGISTRY)(value) def validate_triggers(base_schema): @@ -160,7 +202,9 @@ def validate_triggers(base_schema): @coroutine def build_binary_sensor(full_config): - registry_entry, config = cg.extract_registry_entry_config(BINARY_SENSOR_REGISTRY, full_config) + registry_entry, config = cg.extract_registry_entry_config( + BINARY_SENSOR_REGISTRY, full_config + ) type_id = full_config[CONF_TYPE_ID] builder = registry_entry.coroutine_fun var = cg.new_Pvariable(type_id) @@ -190,62 +234,72 @@ def build_dumpers(config): # JVC -JVCData, JVCBinarySensor, JVCTrigger, JVCAction, JVCDumper = declare_protocol('JVC') +JVCData, JVCBinarySensor, JVCTrigger, JVCAction, JVCDumper = declare_protocol("JVC") JVC_SCHEMA = cv.Schema({cv.Required(CONF_DATA): cv.hex_uint32_t}) -@register_binary_sensor('jvc', JVCBinarySensor, JVC_SCHEMA) +@register_binary_sensor("jvc", JVCBinarySensor, JVC_SCHEMA) def jvc_binary_sensor(var, config): - cg.add(var.set_data(cg.StructInitializer( - JVCData, - ('data', config[CONF_DATA]), - ))) + cg.add( + var.set_data( + cg.StructInitializer( + JVCData, + ("data", config[CONF_DATA]), + ) + ) + ) -@register_trigger('jvc', JVCTrigger, JVCData) +@register_trigger("jvc", JVCTrigger, JVCData) def jvc_trigger(var, config): pass -@register_dumper('jvc', JVCDumper) +@register_dumper("jvc", JVCDumper) def jvc_dumper(var, config): pass -@register_action('jvc', JVCAction, JVC_SCHEMA) +@register_action("jvc", JVCAction, JVC_SCHEMA) def jvc_action(var, config, args): template_ = yield cg.templatable(config[CONF_DATA], args, cg.uint32) cg.add(var.set_data(template_)) # LG -LGData, LGBinarySensor, LGTrigger, LGAction, LGDumper = declare_protocol('LG') -LG_SCHEMA = cv.Schema({ - cv.Required(CONF_DATA): cv.hex_uint32_t, - cv.Optional(CONF_NBITS, default=28): cv.one_of(28, 32, int=True), -}) +LGData, LGBinarySensor, LGTrigger, LGAction, LGDumper = declare_protocol("LG") +LG_SCHEMA = cv.Schema( + { + cv.Required(CONF_DATA): cv.hex_uint32_t, + cv.Optional(CONF_NBITS, default=28): cv.one_of(28, 32, int=True), + } +) -@register_binary_sensor('lg', LGBinarySensor, LG_SCHEMA) +@register_binary_sensor("lg", LGBinarySensor, LG_SCHEMA) def lg_binary_sensor(var, config): - cg.add(var.set_data(cg.StructInitializer( - LGData, - ('data', config[CONF_DATA]), - ('nbits', config[CONF_NBITS]), - ))) + cg.add( + var.set_data( + cg.StructInitializer( + LGData, + ("data", config[CONF_DATA]), + ("nbits", config[CONF_NBITS]), + ) + ) + ) -@register_trigger('lg', LGTrigger, LGData) +@register_trigger("lg", LGTrigger, LGData) def lg_trigger(var, config): pass -@register_dumper('lg', LGDumper) +@register_dumper("lg", LGDumper) def lg_dumper(var, config): pass -@register_action('lg', LGAction, LG_SCHEMA) +@register_action("lg", LGAction, LG_SCHEMA) def lg_action(var, config, args): template_ = yield cg.templatable(config[CONF_DATA], args, cg.uint32) cg.add(var.set_data(template_)) @@ -254,33 +308,39 @@ def lg_action(var, config, args): # NEC -NECData, NECBinarySensor, NECTrigger, NECAction, NECDumper = declare_protocol('NEC') -NEC_SCHEMA = cv.Schema({ - cv.Required(CONF_ADDRESS): cv.hex_uint16_t, - cv.Required(CONF_COMMAND): cv.hex_uint16_t, -}) +NECData, NECBinarySensor, NECTrigger, NECAction, NECDumper = declare_protocol("NEC") +NEC_SCHEMA = cv.Schema( + { + cv.Required(CONF_ADDRESS): cv.hex_uint16_t, + cv.Required(CONF_COMMAND): cv.hex_uint16_t, + } +) -@register_binary_sensor('nec', NECBinarySensor, NEC_SCHEMA) +@register_binary_sensor("nec", NECBinarySensor, NEC_SCHEMA) def nec_binary_sensor(var, config): - cg.add(var.set_data(cg.StructInitializer( - NECData, - ('address', config[CONF_ADDRESS]), - ('command', config[CONF_COMMAND]), - ))) + cg.add( + var.set_data( + cg.StructInitializer( + NECData, + ("address", config[CONF_ADDRESS]), + ("command", config[CONF_COMMAND]), + ) + ) + ) -@register_trigger('nec', NECTrigger, NECData) +@register_trigger("nec", NECTrigger, NECData) def nec_trigger(var, config): pass -@register_dumper('nec', NECDumper) +@register_dumper("nec", NECDumper) def nec_dumper(var, config): pass -@register_action('nec', NECAction, NEC_SCHEMA) +@register_action("nec", NECAction, NEC_SCHEMA) def nec_action(var, config, args): template_ = yield cg.templatable(config[CONF_ADDRESS], args, cg.uint16) cg.add(var.set_address(template_)) @@ -289,34 +349,45 @@ def nec_action(var, config, args): # Pioneer -(PioneerData, PioneerBinarySensor, PioneerTrigger, PioneerAction, - PioneerDumper) = declare_protocol('Pioneer') -PIONEER_SCHEMA = cv.Schema({ - cv.Required(CONF_RC_CODE_1): cv.hex_uint16_t, - cv.Optional(CONF_RC_CODE_2, default=0): cv.hex_uint16_t, -}) +( + PioneerData, + PioneerBinarySensor, + PioneerTrigger, + PioneerAction, + PioneerDumper, +) = declare_protocol("Pioneer") +PIONEER_SCHEMA = cv.Schema( + { + cv.Required(CONF_RC_CODE_1): cv.hex_uint16_t, + cv.Optional(CONF_RC_CODE_2, default=0): cv.hex_uint16_t, + } +) -@register_binary_sensor('pioneer', PioneerBinarySensor, PIONEER_SCHEMA) +@register_binary_sensor("pioneer", PioneerBinarySensor, PIONEER_SCHEMA) def pioneer_binary_sensor(var, config): - cg.add(var.set_data(cg.StructInitializer( - PioneerData, - ('rc_code_1', config[CONF_RC_CODE_1]), - ('rc_code_2', config[CONF_RC_CODE_2]), - ))) + cg.add( + var.set_data( + cg.StructInitializer( + PioneerData, + ("rc_code_1", config[CONF_RC_CODE_1]), + ("rc_code_2", config[CONF_RC_CODE_2]), + ) + ) + ) -@register_trigger('pioneer', PioneerTrigger, PioneerData) +@register_trigger("pioneer", PioneerTrigger, PioneerData) def pioneer_trigger(var, config): pass -@register_dumper('pioneer', PioneerDumper) +@register_dumper("pioneer", PioneerDumper) def pioneer_dumper(var, config): pass -@register_action('pioneer', PioneerAction, PIONEER_SCHEMA) +@register_action("pioneer", PioneerAction, PIONEER_SCHEMA) def pioneer_action(var, config, args): template_ = yield cg.templatable(config[CONF_RC_CODE_1], args, cg.uint16) cg.add(var.set_rc_code_1(template_)) @@ -325,33 +396,41 @@ def pioneer_action(var, config, args): # Sony -SonyData, SonyBinarySensor, SonyTrigger, SonyAction, SonyDumper = declare_protocol('Sony') -SONY_SCHEMA = cv.Schema({ - cv.Required(CONF_DATA): cv.hex_uint32_t, - cv.Optional(CONF_NBITS, default=12): cv.one_of(12, 15, 20, int=True), -}) +SonyData, SonyBinarySensor, SonyTrigger, SonyAction, SonyDumper = declare_protocol( + "Sony" +) +SONY_SCHEMA = cv.Schema( + { + cv.Required(CONF_DATA): cv.hex_uint32_t, + cv.Optional(CONF_NBITS, default=12): cv.one_of(12, 15, 20, int=True), + } +) -@register_binary_sensor('sony', SonyBinarySensor, SONY_SCHEMA) +@register_binary_sensor("sony", SonyBinarySensor, SONY_SCHEMA) def sony_binary_sensor(var, config): - cg.add(var.set_data(cg.StructInitializer( - SonyData, - ('data', config[CONF_DATA]), - ('nbits', config[CONF_NBITS]), - ))) + cg.add( + var.set_data( + cg.StructInitializer( + SonyData, + ("data", config[CONF_DATA]), + ("nbits", config[CONF_NBITS]), + ) + ) + ) -@register_trigger('sony', SonyTrigger, SonyData) +@register_trigger("sony", SonyTrigger, SonyData) def sony_trigger(var, config): pass -@register_dumper('sony', SonyDumper) +@register_dumper("sony", SonyDumper) def sony_dumper(var, config): pass -@register_action('sony', SonyAction, SONY_SCHEMA) +@register_action("sony", SonyAction, SONY_SCHEMA) def sony_action(var, config, args): template_ = yield cg.templatable(config[CONF_DATA], args, cg.uint16) cg.add(var.set_data(template_)) @@ -367,22 +446,30 @@ def validate_raw_alternating(value): this_negative = val < 0 if i != 0: if this_negative == last_negative: - raise cv.Invalid("Values must alternate between being positive and negative, " - "please see index {} and {}".format(i, i + 1), [i]) + raise cv.Invalid( + "Values must alternate between being positive and negative, " + "please see index {} and {}".format(i, i + 1), + [i], + ) last_negative = this_negative return value -RawData, RawBinarySensor, RawTrigger, RawAction, RawDumper = declare_protocol('Raw') -CONF_CODE_STORAGE_ID = 'code_storage_id' -RAW_SCHEMA = cv.Schema({ - cv.Required(CONF_CODE): cv.All([cv.Any(cv.int_, cv.time_period_microseconds)], - cv.Length(min=1), validate_raw_alternating), - cv.GenerateID(CONF_CODE_STORAGE_ID): cv.declare_id(cg.int32), -}) +RawData, RawBinarySensor, RawTrigger, RawAction, RawDumper = declare_protocol("Raw") +CONF_CODE_STORAGE_ID = "code_storage_id" +RAW_SCHEMA = cv.Schema( + { + cv.Required(CONF_CODE): cv.All( + [cv.Any(cv.int_, cv.time_period_microseconds)], + cv.Length(min=1), + validate_raw_alternating, + ), + cv.GenerateID(CONF_CODE_STORAGE_ID): cv.declare_id(cg.int32), + } +) -@register_binary_sensor('raw', RawBinarySensor, RAW_SCHEMA) +@register_binary_sensor("raw", RawBinarySensor, RAW_SCHEMA) def raw_binary_sensor(var, config): code_ = config[CONF_CODE] arr = cg.progmem_array(config[CONF_CODE_STORAGE_ID], code_) @@ -390,19 +477,27 @@ def raw_binary_sensor(var, config): cg.add(var.set_len(len(code_))) -@register_trigger('raw', RawTrigger, cg.std_vector.template(cg.int32)) +@register_trigger("raw", RawTrigger, cg.std_vector.template(cg.int32)) def raw_trigger(var, config): pass -@register_dumper('raw', RawDumper) +@register_dumper("raw", RawDumper) def raw_dumper(var, config): pass -@register_action('raw', RawAction, RAW_SCHEMA.extend({ - cv.Optional(CONF_CARRIER_FREQUENCY, default='0Hz'): cv.All(cv.frequency, cv.int_), -})) +@register_action( + "raw", + RawAction, + RAW_SCHEMA.extend( + { + cv.Optional(CONF_CARRIER_FREQUENCY, default="0Hz"): cv.All( + cv.frequency, cv.int_ + ), + } + ), +) def raw_action(var, config, args): code_ = config[CONF_CODE] if cg.is_template(code_): @@ -417,33 +512,39 @@ def raw_action(var, config, args): # RC5 -RC5Data, RC5BinarySensor, RC5Trigger, RC5Action, RC5Dumper = declare_protocol('RC5') -RC5_SCHEMA = cv.Schema({ - cv.Required(CONF_ADDRESS): cv.All(cv.hex_int, cv.Range(min=0, max=0x1F)), - cv.Required(CONF_COMMAND): cv.All(cv.hex_int, cv.Range(min=0, max=0x7F)), -}) +RC5Data, RC5BinarySensor, RC5Trigger, RC5Action, RC5Dumper = declare_protocol("RC5") +RC5_SCHEMA = cv.Schema( + { + cv.Required(CONF_ADDRESS): cv.All(cv.hex_int, cv.Range(min=0, max=0x1F)), + cv.Required(CONF_COMMAND): cv.All(cv.hex_int, cv.Range(min=0, max=0x7F)), + } +) -@register_binary_sensor('rc5', RC5BinarySensor, RC5_SCHEMA) +@register_binary_sensor("rc5", RC5BinarySensor, RC5_SCHEMA) def rc5_binary_sensor(var, config): - cg.add(var.set_data(cg.StructInitializer( - RC5Data, - ('address', config[CONF_ADDRESS]), - ('command', config[CONF_COMMAND]), - ))) + cg.add( + var.set_data( + cg.StructInitializer( + RC5Data, + ("address", config[CONF_ADDRESS]), + ("command", config[CONF_COMMAND]), + ) + ) + ) -@register_trigger('rc5', RC5Trigger, RC5Data) +@register_trigger("rc5", RC5Trigger, RC5Data) def rc5_trigger(var, config): pass -@register_dumper('rc5', RC5Dumper) +@register_dumper("rc5", RC5Dumper) def rc5_dumper(var, config): pass -@register_action('rc5', RC5Action, RC5_SCHEMA) +@register_action("rc5", RC5Action, RC5_SCHEMA) def rc5_action(var, config, args): template_ = yield cg.templatable(config[CONF_ADDRESS], args, cg.uint8) cg.add(var.set_address(template_)) @@ -456,13 +557,15 @@ RC_SWITCH_TIMING_SCHEMA = cv.All([cv.uint8_t], cv.Length(min=2, max=2)) RC_SWITCH_PROTOCOL_SCHEMA = cv.Any( cv.int_range(min=1, max=8), - cv.Schema({ - cv.Required(CONF_PULSE_LENGTH): cv.uint32_t, - cv.Optional(CONF_SYNC, default=[1, 31]): RC_SWITCH_TIMING_SCHEMA, - cv.Optional(CONF_ZERO, default=[1, 3]): RC_SWITCH_TIMING_SCHEMA, - cv.Optional(CONF_ONE, default=[3, 1]): RC_SWITCH_TIMING_SCHEMA, - cv.Optional(CONF_INVERTED, default=False): cv.boolean, - }) + cv.Schema( + { + cv.Required(CONF_PULSE_LENGTH): cv.uint32_t, + cv.Optional(CONF_SYNC, default=[1, 31]): RC_SWITCH_TIMING_SCHEMA, + cv.Optional(CONF_ZERO, default=[1, 3]): RC_SWITCH_TIMING_SCHEMA, + cv.Optional(CONF_ONE, default=[3, 1]): RC_SWITCH_TIMING_SCHEMA, + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } + ), ) @@ -470,12 +573,16 @@ def validate_rc_switch_code(value): if not isinstance(value, (str, str)): raise cv.Invalid("All RCSwitch codes must be in quotes ('')") for c in value: - if c not in ('0', '1'): - raise cv.Invalid("Invalid RCSwitch code character '{}'. Only '0' and '1' are allowed" - "".format(c)) + if c not in ("0", "1"): + raise cv.Invalid( + "Invalid RCSwitch code character '{}'. Only '0' and '1' are allowed" + "".format(c) + ) if len(value) > 64: - raise cv.Invalid("Maximum length for RCSwitch codes is 64, code '{}' has length {}" - "".format(value, len(value))) + raise cv.Invalid( + "Maximum length for RCSwitch codes is 64, code '{}' has length {}" + "".format(value, len(value)) + ) if not value: raise cv.Invalid("RCSwitch code must not be empty") return value @@ -485,13 +592,17 @@ def validate_rc_switch_raw_code(value): if not isinstance(value, (str, str)): raise cv.Invalid("All RCSwitch raw codes must be in quotes ('')") for c in value: - if c not in ('0', '1', 'x'): + if c not in ("0", "1", "x"): raise cv.Invalid( - "Invalid RCSwitch raw code character '{}'.Only '0', '1' and 'x' are allowed" - .format(c)) + "Invalid RCSwitch raw code character '{}'.Only '0', '1' and 'x' are allowed".format( + c + ) + ) if len(value) > 64: - raise cv.Invalid("Maximum length for RCSwitch raw codes is 64, code '{}' has length {}" - "".format(value, len(value))) + raise cv.Invalid( + "Maximum length for RCSwitch raw codes is 64, code '{}' has length {}" + "".format(value, len(value)) + ) if not value: raise cv.Invalid("RCSwitch raw code must not be empty") return value @@ -501,220 +612,332 @@ def build_rc_switch_protocol(config): if isinstance(config, int): return rc_switch_protocols[config] pl = config[CONF_PULSE_LENGTH] - return RCSwitchBase(config[CONF_SYNC][0] * pl, config[CONF_SYNC][1] * pl, - config[CONF_ZERO][0] * pl, config[CONF_ZERO][1] * pl, - config[CONF_ONE][0] * pl, config[CONF_ONE][1] * pl, - config[CONF_INVERTED]) + return RCSwitchBase( + config[CONF_SYNC][0] * pl, + config[CONF_SYNC][1] * pl, + config[CONF_ZERO][0] * pl, + config[CONF_ZERO][1] * pl, + config[CONF_ONE][0] * pl, + config[CONF_ONE][1] * pl, + config[CONF_INVERTED], + ) -RC_SWITCH_RAW_SCHEMA = cv.Schema({ - cv.Required(CONF_CODE): validate_rc_switch_raw_code, - cv.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA, -}) -RC_SWITCH_TYPE_A_SCHEMA = cv.Schema({ - cv.Required(CONF_GROUP): cv.All(validate_rc_switch_code, cv.Length(min=5, max=5)), - cv.Required(CONF_DEVICE): cv.All(validate_rc_switch_code, cv.Length(min=5, max=5)), - cv.Required(CONF_STATE): cv.boolean, - cv.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA, -}) -RC_SWITCH_TYPE_B_SCHEMA = cv.Schema({ - cv.Required(CONF_ADDRESS): cv.int_range(min=1, max=4), - cv.Required(CONF_CHANNEL): cv.int_range(min=1, max=4), - cv.Required(CONF_STATE): cv.boolean, - cv.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA, -}) -RC_SWITCH_TYPE_C_SCHEMA = cv.Schema({ - cv.Required(CONF_FAMILY): cv.one_of('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', - 'l', 'm', 'n', 'o', 'p', lower=True), - cv.Required(CONF_GROUP): cv.int_range(min=1, max=4), - cv.Required(CONF_DEVICE): cv.int_range(min=1, max=4), - cv.Required(CONF_STATE): cv.boolean, - cv.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA, -}) -RC_SWITCH_TYPE_D_SCHEMA = cv.Schema({ - cv.Required(CONF_GROUP): cv.one_of('a', 'b', 'c', 'd', lower=True), - cv.Required(CONF_DEVICE): cv.int_range(min=1, max=3), - cv.Required(CONF_STATE): cv.boolean, - cv.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA, -}) -RC_SWITCH_TRANSMITTER = cv.Schema({ - cv.Optional(CONF_REPEAT, default={CONF_TIMES: 5}): cv.Schema({ - cv.Required(CONF_TIMES): cv.templatable(cv.positive_int), - cv.Optional(CONF_WAIT_TIME, default='0us'): - cv.templatable(cv.positive_time_period_microseconds), - }), -}) +RC_SWITCH_RAW_SCHEMA = cv.Schema( + { + cv.Required(CONF_CODE): validate_rc_switch_raw_code, + cv.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA, + } +) +RC_SWITCH_TYPE_A_SCHEMA = cv.Schema( + { + cv.Required(CONF_GROUP): cv.All( + validate_rc_switch_code, cv.Length(min=5, max=5) + ), + cv.Required(CONF_DEVICE): cv.All( + validate_rc_switch_code, cv.Length(min=5, max=5) + ), + cv.Required(CONF_STATE): cv.boolean, + cv.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA, + } +) +RC_SWITCH_TYPE_B_SCHEMA = cv.Schema( + { + cv.Required(CONF_ADDRESS): cv.int_range(min=1, max=4), + cv.Required(CONF_CHANNEL): cv.int_range(min=1, max=4), + cv.Required(CONF_STATE): cv.boolean, + cv.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA, + } +) +RC_SWITCH_TYPE_C_SCHEMA = cv.Schema( + { + cv.Required(CONF_FAMILY): cv.one_of( + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + lower=True, + ), + cv.Required(CONF_GROUP): cv.int_range(min=1, max=4), + cv.Required(CONF_DEVICE): cv.int_range(min=1, max=4), + cv.Required(CONF_STATE): cv.boolean, + cv.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA, + } +) +RC_SWITCH_TYPE_D_SCHEMA = cv.Schema( + { + cv.Required(CONF_GROUP): cv.one_of("a", "b", "c", "d", lower=True), + cv.Required(CONF_DEVICE): cv.int_range(min=1, max=3), + cv.Required(CONF_STATE): cv.boolean, + cv.Optional(CONF_PROTOCOL, default=1): RC_SWITCH_PROTOCOL_SCHEMA, + } +) +RC_SWITCH_TRANSMITTER = cv.Schema( + { + cv.Optional(CONF_REPEAT, default={CONF_TIMES: 5}): cv.Schema( + { + cv.Required(CONF_TIMES): cv.templatable(cv.positive_int), + cv.Optional(CONF_WAIT_TIME, default="0us"): cv.templatable( + cv.positive_time_period_microseconds + ), + } + ), + } +) rc_switch_protocols = ns.rc_switch_protocols -RCSwitchData = ns.struct('RCSwitchData') -RCSwitchBase = ns.class_('RCSwitchBase') -RCSwitchTrigger = ns.class_('RCSwitchTrigger', RemoteReceiverTrigger) -RCSwitchDumper = ns.class_('RCSwitchDumper', RemoteTransmitterDumper) -RCSwitchRawAction = ns.class_('RCSwitchRawAction', RemoteTransmitterActionBase) -RCSwitchTypeAAction = ns.class_('RCSwitchTypeAAction', RemoteTransmitterActionBase) -RCSwitchTypeBAction = ns.class_('RCSwitchTypeBAction', RemoteTransmitterActionBase) -RCSwitchTypeCAction = ns.class_('RCSwitchTypeCAction', RemoteTransmitterActionBase) -RCSwitchTypeDAction = ns.class_('RCSwitchTypeDAction', RemoteTransmitterActionBase) -RCSwitchRawReceiver = ns.class_('RCSwitchRawReceiver', RemoteReceiverBinarySensorBase) +RCSwitchData = ns.struct("RCSwitchData") +RCSwitchBase = ns.class_("RCSwitchBase") +RCSwitchTrigger = ns.class_("RCSwitchTrigger", RemoteReceiverTrigger) +RCSwitchDumper = ns.class_("RCSwitchDumper", RemoteTransmitterDumper) +RCSwitchRawAction = ns.class_("RCSwitchRawAction", RemoteTransmitterActionBase) +RCSwitchTypeAAction = ns.class_("RCSwitchTypeAAction", RemoteTransmitterActionBase) +RCSwitchTypeBAction = ns.class_("RCSwitchTypeBAction", RemoteTransmitterActionBase) +RCSwitchTypeCAction = ns.class_("RCSwitchTypeCAction", RemoteTransmitterActionBase) +RCSwitchTypeDAction = ns.class_("RCSwitchTypeDAction", RemoteTransmitterActionBase) +RCSwitchRawReceiver = ns.class_("RCSwitchRawReceiver", RemoteReceiverBinarySensorBase) -@register_binary_sensor('rc_switch_raw', RCSwitchRawReceiver, RC_SWITCH_RAW_SCHEMA) +@register_binary_sensor("rc_switch_raw", RCSwitchRawReceiver, RC_SWITCH_RAW_SCHEMA) def rc_switch_raw_binary_sensor(var, config): cg.add(var.set_protocol(build_rc_switch_protocol(config[CONF_PROTOCOL]))) cg.add(var.set_code(config[CONF_CODE])) -@register_action('rc_switch_raw', RCSwitchRawAction, - RC_SWITCH_RAW_SCHEMA.extend(RC_SWITCH_TRANSMITTER)) +@register_action( + "rc_switch_raw", + RCSwitchRawAction, + RC_SWITCH_RAW_SCHEMA.extend(RC_SWITCH_TRANSMITTER), +) def rc_switch_raw_action(var, config, args): - proto = yield cg.templatable(config[CONF_PROTOCOL], args, RCSwitchBase, - to_exp=build_rc_switch_protocol) + proto = yield cg.templatable( + config[CONF_PROTOCOL], args, RCSwitchBase, to_exp=build_rc_switch_protocol + ) cg.add(var.set_protocol(proto)) cg.add(var.set_code((yield cg.templatable(config[CONF_CODE], args, cg.std_string)))) -@register_binary_sensor('rc_switch_type_a', RCSwitchRawReceiver, RC_SWITCH_TYPE_A_SCHEMA) +@register_binary_sensor( + "rc_switch_type_a", RCSwitchRawReceiver, RC_SWITCH_TYPE_A_SCHEMA +) def rc_switch_type_a_binary_sensor(var, config): cg.add(var.set_protocol(build_rc_switch_protocol(config[CONF_PROTOCOL]))) cg.add(var.set_type_a(config[CONF_GROUP], config[CONF_DEVICE], config[CONF_STATE])) -@register_action('rc_switch_type_a', RCSwitchTypeAAction, - RC_SWITCH_TYPE_A_SCHEMA.extend(RC_SWITCH_TRANSMITTER)) +@register_action( + "rc_switch_type_a", + RCSwitchTypeAAction, + RC_SWITCH_TYPE_A_SCHEMA.extend(RC_SWITCH_TRANSMITTER), +) def rc_switch_type_a_action(var, config, args): - proto = yield cg.templatable(config[CONF_PROTOCOL], args, RCSwitchBase, - to_exp=build_rc_switch_protocol) + proto = yield cg.templatable( + config[CONF_PROTOCOL], args, RCSwitchBase, to_exp=build_rc_switch_protocol + ) cg.add(var.set_protocol(proto)) - cg.add(var.set_group((yield cg.templatable(config[CONF_GROUP], args, cg.std_string)))) - cg.add(var.set_device((yield cg.templatable(config[CONF_DEVICE], args, cg.std_string)))) + cg.add( + var.set_group((yield cg.templatable(config[CONF_GROUP], args, cg.std_string))) + ) + cg.add( + var.set_device((yield cg.templatable(config[CONF_DEVICE], args, cg.std_string))) + ) cg.add(var.set_state((yield cg.templatable(config[CONF_STATE], args, bool)))) -@register_binary_sensor('rc_switch_type_b', RCSwitchRawReceiver, RC_SWITCH_TYPE_B_SCHEMA) +@register_binary_sensor( + "rc_switch_type_b", RCSwitchRawReceiver, RC_SWITCH_TYPE_B_SCHEMA +) def rc_switch_type_b_binary_sensor(var, config): cg.add(var.set_protocol(build_rc_switch_protocol(config[CONF_PROTOCOL]))) - cg.add(var.set_type_b(config[CONF_ADDRESS], config[CONF_CHANNEL], config[CONF_STATE])) + cg.add( + var.set_type_b(config[CONF_ADDRESS], config[CONF_CHANNEL], config[CONF_STATE]) + ) -@register_action('rc_switch_type_b', RCSwitchTypeBAction, - RC_SWITCH_TYPE_B_SCHEMA.extend(RC_SWITCH_TRANSMITTER)) +@register_action( + "rc_switch_type_b", + RCSwitchTypeBAction, + RC_SWITCH_TYPE_B_SCHEMA.extend(RC_SWITCH_TRANSMITTER), +) def rc_switch_type_b_action(var, config, args): - proto = yield cg.templatable(config[CONF_PROTOCOL], args, RCSwitchBase, - to_exp=build_rc_switch_protocol) + proto = yield cg.templatable( + config[CONF_PROTOCOL], args, RCSwitchBase, to_exp=build_rc_switch_protocol + ) cg.add(var.set_protocol(proto)) - cg.add(var.set_address((yield cg.templatable(config[CONF_ADDRESS], args, cg.uint8)))) - cg.add(var.set_channel((yield cg.templatable(config[CONF_CHANNEL], args, cg.uint8)))) + cg.add( + var.set_address((yield cg.templatable(config[CONF_ADDRESS], args, cg.uint8))) + ) + cg.add( + var.set_channel((yield cg.templatable(config[CONF_CHANNEL], args, cg.uint8))) + ) cg.add(var.set_state((yield cg.templatable(config[CONF_STATE], args, bool)))) -@register_binary_sensor('rc_switch_type_c', RCSwitchRawReceiver, RC_SWITCH_TYPE_C_SCHEMA) +@register_binary_sensor( + "rc_switch_type_c", RCSwitchRawReceiver, RC_SWITCH_TYPE_C_SCHEMA +) def rc_switch_type_c_binary_sensor(var, config): cg.add(var.set_protocol(build_rc_switch_protocol(config[CONF_PROTOCOL]))) - cg.add(var.set_type_c(config[CONF_FAMILY], config[CONF_GROUP], config[CONF_DEVICE], - config[CONF_STATE])) + cg.add( + var.set_type_c( + config[CONF_FAMILY], + config[CONF_GROUP], + config[CONF_DEVICE], + config[CONF_STATE], + ) + ) -@register_action('rc_switch_type_c', RCSwitchTypeCAction, - RC_SWITCH_TYPE_C_SCHEMA.extend(RC_SWITCH_TRANSMITTER)) +@register_action( + "rc_switch_type_c", + RCSwitchTypeCAction, + RC_SWITCH_TYPE_C_SCHEMA.extend(RC_SWITCH_TRANSMITTER), +) def rc_switch_type_c_action(var, config, args): - proto = yield cg.templatable(config[CONF_PROTOCOL], args, RCSwitchBase, - to_exp=build_rc_switch_protocol) + proto = yield cg.templatable( + config[CONF_PROTOCOL], args, RCSwitchBase, to_exp=build_rc_switch_protocol + ) cg.add(var.set_protocol(proto)) - cg.add(var.set_family((yield cg.templatable(config[CONF_FAMILY], args, cg.std_string)))) + cg.add( + var.set_family((yield cg.templatable(config[CONF_FAMILY], args, cg.std_string))) + ) cg.add(var.set_group((yield cg.templatable(config[CONF_GROUP], args, cg.uint8)))) cg.add(var.set_device((yield cg.templatable(config[CONF_DEVICE], args, cg.uint8)))) cg.add(var.set_state((yield cg.templatable(config[CONF_STATE], args, bool)))) -@register_binary_sensor('rc_switch_type_d', RCSwitchRawReceiver, - RC_SWITCH_TYPE_D_SCHEMA.extend(RC_SWITCH_TRANSMITTER)) +@register_binary_sensor( + "rc_switch_type_d", + RCSwitchRawReceiver, + RC_SWITCH_TYPE_D_SCHEMA.extend(RC_SWITCH_TRANSMITTER), +) def rc_switch_type_d_binary_sensor(var, config): cg.add(var.set_protocol(build_rc_switch_protocol(config[CONF_PROTOCOL]))) cg.add(var.set_type_d(config[CONF_GROUP], config[CONF_DEVICE], config[CONF_STATE])) -@register_action('rc_switch_type_d', RCSwitchTypeDAction, - RC_SWITCH_TYPE_D_SCHEMA.extend(RC_SWITCH_TRANSMITTER)) +@register_action( + "rc_switch_type_d", + RCSwitchTypeDAction, + RC_SWITCH_TYPE_D_SCHEMA.extend(RC_SWITCH_TRANSMITTER), +) def rc_switch_type_d_action(var, config, args): - proto = yield cg.templatable(config[CONF_PROTOCOL], args, RCSwitchBase, - to_exp=build_rc_switch_protocol) + proto = yield cg.templatable( + config[CONF_PROTOCOL], args, RCSwitchBase, to_exp=build_rc_switch_protocol + ) cg.add(var.set_protocol(proto)) - cg.add(var.set_group((yield cg.templatable(config[CONF_GROUP], args, cg.std_string)))) + cg.add( + var.set_group((yield cg.templatable(config[CONF_GROUP], args, cg.std_string))) + ) cg.add(var.set_device((yield cg.templatable(config[CONF_DEVICE], args, cg.uint8)))) cg.add(var.set_state((yield cg.templatable(config[CONF_STATE], args, bool)))) -@register_trigger('rc_switch', RCSwitchTrigger, RCSwitchData) +@register_trigger("rc_switch", RCSwitchTrigger, RCSwitchData) def rc_switch_trigger(var, config): pass -@register_dumper('rc_switch', RCSwitchDumper) +@register_dumper("rc_switch", RCSwitchDumper) def rc_switch_dumper(var, config): pass # Samsung -(SamsungData, SamsungBinarySensor, SamsungTrigger, SamsungAction, - SamsungDumper) = declare_protocol('Samsung') -SAMSUNG_SCHEMA = cv.Schema({ - cv.Required(CONF_DATA): cv.hex_uint32_t, -}) +( + SamsungData, + SamsungBinarySensor, + SamsungTrigger, + SamsungAction, + SamsungDumper, +) = declare_protocol("Samsung") +SAMSUNG_SCHEMA = cv.Schema( + { + cv.Required(CONF_DATA): cv.hex_uint32_t, + } +) -@register_binary_sensor('samsung', SamsungBinarySensor, SAMSUNG_SCHEMA) +@register_binary_sensor("samsung", SamsungBinarySensor, SAMSUNG_SCHEMA) def samsung_binary_sensor(var, config): - cg.add(var.set_data(cg.StructInitializer( - SamsungData, - ('data', config[CONF_DATA]), - ))) + cg.add( + var.set_data( + cg.StructInitializer( + SamsungData, + ("data", config[CONF_DATA]), + ) + ) + ) -@register_trigger('samsung', SamsungTrigger, SamsungData) +@register_trigger("samsung", SamsungTrigger, SamsungData) def samsung_trigger(var, config): pass -@register_dumper('samsung', SamsungDumper) +@register_dumper("samsung", SamsungDumper) def samsung_dumper(var, config): pass -@register_action('samsung', SamsungAction, SAMSUNG_SCHEMA) +@register_action("samsung", SamsungAction, SAMSUNG_SCHEMA) def samsung_action(var, config, args): template_ = yield cg.templatable(config[CONF_DATA], args, cg.uint32) cg.add(var.set_data(template_)) # Samsung36 -(Samsung36Data, Samsung36BinarySensor, Samsung36Trigger, Samsung36Action, - Samsung36Dumper) = declare_protocol('Samsung36') -SAMSUNG36_SCHEMA = cv.Schema({ - cv.Required(CONF_ADDRESS): cv.hex_uint16_t, - cv.Required(CONF_COMMAND): cv.hex_uint32_t, -}) +( + Samsung36Data, + Samsung36BinarySensor, + Samsung36Trigger, + Samsung36Action, + Samsung36Dumper, +) = declare_protocol("Samsung36") +SAMSUNG36_SCHEMA = cv.Schema( + { + cv.Required(CONF_ADDRESS): cv.hex_uint16_t, + cv.Required(CONF_COMMAND): cv.hex_uint32_t, + } +) -@register_binary_sensor('samsung36', Samsung36BinarySensor, SAMSUNG36_SCHEMA) +@register_binary_sensor("samsung36", Samsung36BinarySensor, SAMSUNG36_SCHEMA) def samsung36_binary_sensor(var, config): - cg.add(var.set_data(cg.StructInitializer( - Samsung36Data, - ('address', config[CONF_ADDRESS]), - ('command', config[CONF_COMMAND]), - ))) + cg.add( + var.set_data( + cg.StructInitializer( + Samsung36Data, + ("address", config[CONF_ADDRESS]), + ("command", config[CONF_COMMAND]), + ) + ) + ) -@register_trigger('samsung36', Samsung36Trigger, Samsung36Data) +@register_trigger("samsung36", Samsung36Trigger, Samsung36Data) def samsung36_trigger(var, config): pass -@register_dumper('samsung36', Samsung36Dumper) +@register_dumper("samsung36", Samsung36Dumper) def samsung36_dumper(var, config): pass -@register_action('samsung36', Samsung36Action, SAMSUNG36_SCHEMA) +@register_action("samsung36", Samsung36Action, SAMSUNG36_SCHEMA) def samsung36_action(var, config, args): template_ = yield cg.templatable(config[CONF_ADDRESS], args, cg.uint16) cg.add(var.set_address(template_)) @@ -723,34 +946,45 @@ def samsung36_action(var, config, args): # Panasonic -(PanasonicData, PanasonicBinarySensor, PanasonicTrigger, PanasonicAction, - PanasonicDumper) = declare_protocol('Panasonic') -PANASONIC_SCHEMA = cv.Schema({ - cv.Required(CONF_ADDRESS): cv.hex_uint16_t, - cv.Required(CONF_COMMAND): cv.hex_uint32_t, -}) +( + PanasonicData, + PanasonicBinarySensor, + PanasonicTrigger, + PanasonicAction, + PanasonicDumper, +) = declare_protocol("Panasonic") +PANASONIC_SCHEMA = cv.Schema( + { + cv.Required(CONF_ADDRESS): cv.hex_uint16_t, + cv.Required(CONF_COMMAND): cv.hex_uint32_t, + } +) -@register_binary_sensor('panasonic', PanasonicBinarySensor, PANASONIC_SCHEMA) +@register_binary_sensor("panasonic", PanasonicBinarySensor, PANASONIC_SCHEMA) def panasonic_binary_sensor(var, config): - cg.add(var.set_data(cg.StructInitializer( - PanasonicData, - ('address', config[CONF_ADDRESS]), - ('command', config[CONF_COMMAND]), - ))) + cg.add( + var.set_data( + cg.StructInitializer( + PanasonicData, + ("address", config[CONF_ADDRESS]), + ("command", config[CONF_COMMAND]), + ) + ) + ) -@register_trigger('panasonic', PanasonicTrigger, PanasonicData) +@register_trigger("panasonic", PanasonicTrigger, PanasonicData) def panasonic_trigger(var, config): pass -@register_dumper('panasonic', PanasonicDumper) +@register_dumper("panasonic", PanasonicDumper) def panasonic_dumper(var, config): pass -@register_action('panasonic', PanasonicAction, PANASONIC_SCHEMA) +@register_action("panasonic", PanasonicAction, PANASONIC_SCHEMA) def panasonic_action(var, config, args): template_ = yield cg.templatable(config[CONF_ADDRESS], args, cg.uint16) cg.add(var.set_address(template_)) diff --git a/esphome/components/remote_receiver/__init__.py b/esphome/components/remote_receiver/__init__.py index 28570a7c6..f29c59b3f 100644 --- a/esphome/components/remote_receiver/__init__.py +++ b/esphome/components/remote_receiver/__init__.py @@ -2,28 +2,49 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.components import remote_base -from esphome.const import CONF_BUFFER_SIZE, CONF_DUMP, CONF_FILTER, CONF_ID, CONF_IDLE, \ - CONF_PIN, CONF_TOLERANCE, CONF_MEMORY_BLOCKS +from esphome.const import ( + CONF_BUFFER_SIZE, + CONF_DUMP, + CONF_FILTER, + CONF_ID, + CONF_IDLE, + CONF_PIN, + CONF_TOLERANCE, + CONF_MEMORY_BLOCKS, +) from esphome.core import CORE -AUTO_LOAD = ['remote_base'] -remote_receiver_ns = cg.esphome_ns.namespace('remote_receiver') -RemoteReceiverComponent = remote_receiver_ns.class_('RemoteReceiverComponent', - remote_base.RemoteReceiverBase, - cg.Component) +AUTO_LOAD = ["remote_base"] +remote_receiver_ns = cg.esphome_ns.namespace("remote_receiver") +RemoteReceiverComponent = remote_receiver_ns.class_( + "RemoteReceiverComponent", remote_base.RemoteReceiverBase, cg.Component +) MULTI_CONF = True -CONFIG_SCHEMA = remote_base.validate_triggers(cv.Schema({ - cv.GenerateID(): cv.declare_id(RemoteReceiverComponent), - cv.Required(CONF_PIN): cv.All(pins.internal_gpio_input_pin_schema, - pins.validate_has_interrupt), - cv.Optional(CONF_DUMP, default=[]): remote_base.validate_dumpers, - cv.Optional(CONF_TOLERANCE, default=25): cv.All(cv.percentage_int, cv.Range(min=0)), - cv.SplitDefault(CONF_BUFFER_SIZE, esp32='10000b', esp8266='1000b'): cv.validate_bytes, - cv.Optional(CONF_FILTER, default='50us'): cv.positive_time_period_microseconds, - cv.Optional(CONF_IDLE, default='10ms'): cv.positive_time_period_microseconds, - cv.Optional(CONF_MEMORY_BLOCKS, default=3): cv.Range(min=1, max=8), -}).extend(cv.COMPONENT_SCHEMA)) +CONFIG_SCHEMA = remote_base.validate_triggers( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(RemoteReceiverComponent), + cv.Required(CONF_PIN): cv.All( + pins.internal_gpio_input_pin_schema, pins.validate_has_interrupt + ), + cv.Optional(CONF_DUMP, default=[]): remote_base.validate_dumpers, + cv.Optional(CONF_TOLERANCE, default=25): cv.All( + cv.percentage_int, cv.Range(min=0) + ), + cv.SplitDefault( + CONF_BUFFER_SIZE, esp32="10000b", esp8266="1000b" + ): cv.validate_bytes, + cv.Optional( + CONF_FILTER, default="50us" + ): cv.positive_time_period_microseconds, + cv.Optional( + CONF_IDLE, default="10ms" + ): cv.positive_time_period_microseconds, + cv.Optional(CONF_MEMORY_BLOCKS, default=3): cv.Range(min=1, max=8), + } + ).extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/remote_receiver/binary_sensor.py b/esphome/components/remote_receiver/binary_sensor.py index 7be64e5a5..522333584 100644 --- a/esphome/components/remote_receiver/binary_sensor.py +++ b/esphome/components/remote_receiver/binary_sensor.py @@ -2,7 +2,7 @@ import esphome.codegen as cg from esphome.components import binary_sensor, remote_base from esphome.const import CONF_NAME -DEPENDENCIES = ['remote_receiver'] +DEPENDENCIES = ["remote_receiver"] CONFIG_SCHEMA = remote_base.validate_binary_sensor diff --git a/esphome/components/remote_transmitter/__init__.py b/esphome/components/remote_transmitter/__init__.py index 5e217de60..123af7db9 100644 --- a/esphome/components/remote_transmitter/__init__.py +++ b/esphome/components/remote_transmitter/__init__.py @@ -4,18 +4,22 @@ from esphome import pins from esphome.components import remote_base from esphome.const import CONF_CARRIER_DUTY_PERCENT, CONF_ID, CONF_PIN -AUTO_LOAD = ['remote_base'] -remote_transmitter_ns = cg.esphome_ns.namespace('remote_transmitter') -RemoteTransmitterComponent = remote_transmitter_ns.class_('RemoteTransmitterComponent', - remote_base.RemoteTransmitterBase, - cg.Component) +AUTO_LOAD = ["remote_base"] +remote_transmitter_ns = cg.esphome_ns.namespace("remote_transmitter") +RemoteTransmitterComponent = remote_transmitter_ns.class_( + "RemoteTransmitterComponent", remote_base.RemoteTransmitterBase, cg.Component +) MULTI_CONF = True -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(RemoteTransmitterComponent), - cv.Required(CONF_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_CARRIER_DUTY_PERCENT): cv.All(cv.percentage_int, cv.Range(min=1, max=100)), -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(RemoteTransmitterComponent), + cv.Required(CONF_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_CARRIER_DUTY_PERCENT): cv.All( + cv.percentage_int, cv.Range(min=1, max=100) + ), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/remote_transmitter/switch.py b/esphome/components/remote_transmitter/switch.py index 5e0be04d7..3a2e43a31 100644 --- a/esphome/components/remote_transmitter/switch.py +++ b/esphome/components/remote_transmitter/switch.py @@ -5,26 +5,29 @@ from esphome.util import OrderedDict def show_new(value): from esphome import yaml_util + for key in BINARY_SENSOR_REGISTRY: if key in value: break else: - raise cv.Invalid("This platform has been removed in 1.13, please see the docs for updated " - "instructions.") + raise cv.Invalid( + "This platform has been removed in 1.13, please see the docs for updated " + "instructions." + ) val = value[key] - args = [('platform', 'template')] - if 'id' in value: - args.append(('id', value['id'])) - if 'name' in value: - args.append(('name', value['name'])) - args.append(('turn_on_action', { - f'remote_transmitter.transmit_{key}': val - })) + args = [("platform", "template")] + if "id" in value: + args.append(("id", value["id"])) + if "name" in value: + args.append(("name", value["name"])) + args.append(("turn_on_action", {f"remote_transmitter.transmit_{key}": val})) text = yaml_util.dump([OrderedDict(args)]) - raise cv.Invalid("This platform has been removed in 1.13, please change to:\n\n{}\n\n." - "".format(text)) + raise cv.Invalid( + "This platform has been removed in 1.13, please change to:\n\n{}\n\n." + "".format(text) + ) CONFIG_SCHEMA = show_new diff --git a/esphome/components/resistance/sensor.py b/esphome/components/resistance/sensor.py index 373fa3a8a..92a564f68 100644 --- a/esphome/components/resistance/sensor.py +++ b/esphome/components/resistance/sensor.py @@ -3,26 +3,32 @@ import esphome.config_validation as cv from esphome.components import sensor from esphome.const import CONF_SENSOR, DEVICE_CLASS_EMPTY, UNIT_OHM, ICON_FLASH, CONF_ID -resistance_ns = cg.esphome_ns.namespace('resistance') -ResistanceSensor = resistance_ns.class_('ResistanceSensor', cg.Component, sensor.Sensor) +resistance_ns = cg.esphome_ns.namespace("resistance") +ResistanceSensor = resistance_ns.class_("ResistanceSensor", cg.Component, sensor.Sensor) -CONF_REFERENCE_VOLTAGE = 'reference_voltage' -CONF_CONFIGURATION = 'configuration' -CONF_RESISTOR = 'resistor' +CONF_REFERENCE_VOLTAGE = "reference_voltage" +CONF_CONFIGURATION = "configuration" +CONF_RESISTOR = "resistor" -ResistanceConfiguration = resistance_ns.enum('ResistanceConfiguration') +ResistanceConfiguration = resistance_ns.enum("ResistanceConfiguration") CONFIGURATIONS = { - 'DOWNSTREAM': ResistanceConfiguration.DOWNSTREAM, - 'UPSTREAM': ResistanceConfiguration.UPSTREAM, + "DOWNSTREAM": ResistanceConfiguration.DOWNSTREAM, + "UPSTREAM": ResistanceConfiguration.UPSTREAM, } -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_OHM, ICON_FLASH, 1, DEVICE_CLASS_EMPTY).extend({ - cv.GenerateID(): cv.declare_id(ResistanceSensor), - cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor), - cv.Required(CONF_CONFIGURATION): cv.enum(CONFIGURATIONS, upper=True), - cv.Required(CONF_RESISTOR): cv.resistance, - cv.Optional(CONF_REFERENCE_VOLTAGE, default='3.3V'): cv.voltage, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_OHM, ICON_FLASH, 1, DEVICE_CLASS_EMPTY) + .extend( + { + cv.GenerateID(): cv.declare_id(ResistanceSensor), + cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor), + cv.Required(CONF_CONFIGURATION): cv.enum(CONFIGURATIONS, upper=True), + cv.Required(CONF_RESISTOR): cv.resistance, + cv.Optional(CONF_REFERENCE_VOLTAGE, default="3.3V"): cv.voltage, + } + ) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/restart/__init__.py b/esphome/components/restart/__init__.py index 63db7aee2..f70ffa952 100644 --- a/esphome/components/restart/__init__.py +++ b/esphome/components/restart/__init__.py @@ -1 +1 @@ -CODEOWNERS = ['@esphome/core'] +CODEOWNERS = ["@esphome/core"] diff --git a/esphome/components/restart/switch.py b/esphome/components/restart/switch.py index 9517302d3..fe170aee6 100644 --- a/esphome/components/restart/switch.py +++ b/esphome/components/restart/switch.py @@ -3,15 +3,18 @@ import esphome.config_validation as cv from esphome.components import switch from esphome.const import CONF_ID, CONF_INVERTED, CONF_ICON, ICON_RESTART -restart_ns = cg.esphome_ns.namespace('restart') -RestartSwitch = restart_ns.class_('RestartSwitch', switch.Switch, cg.Component) +restart_ns = cg.esphome_ns.namespace("restart") +RestartSwitch = restart_ns.class_("RestartSwitch", switch.Switch, cg.Component) -CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(RestartSwitch), - cv.Optional(CONF_INVERTED): cv.invalid("Restart switches do not support inverted mode!"), - - cv.Optional(CONF_ICON, default=ICON_RESTART): switch.icon, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(RestartSwitch), + cv.Optional(CONF_INVERTED): cv.invalid( + "Restart switches do not support inverted mode!" + ), + cv.Optional(CONF_ICON, default=ICON_RESTART): switch.icon, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/rf_bridge/__init__.py b/esphome/components/rf_bridge/__init__.py index a0a910118..b24e19b4b 100644 --- a/esphome/components/rf_bridge/__init__.py +++ b/esphome/components/rf_bridge/__init__.py @@ -14,47 +14,69 @@ from esphome.const import ( CONF_TRIGGER_ID, ) -DEPENDENCIES = ['uart'] -CODEOWNERS = ['@jesserockz'] +DEPENDENCIES = ["uart"] +CODEOWNERS = ["@jesserockz"] -rf_bridge_ns = cg.esphome_ns.namespace('rf_bridge') -RFBridgeComponent = rf_bridge_ns.class_('RFBridgeComponent', cg.Component, uart.UARTDevice) +rf_bridge_ns = cg.esphome_ns.namespace("rf_bridge") +RFBridgeComponent = rf_bridge_ns.class_( + "RFBridgeComponent", cg.Component, uart.UARTDevice +) -RFBridgeData = rf_bridge_ns.struct('RFBridgeData') -RFBridgeAdvancedData = rf_bridge_ns.struct('RFBridgeAdvancedData') +RFBridgeData = rf_bridge_ns.struct("RFBridgeData") +RFBridgeAdvancedData = rf_bridge_ns.struct("RFBridgeAdvancedData") -RFBridgeReceivedCodeTrigger = rf_bridge_ns.class_('RFBridgeReceivedCodeTrigger', - automation.Trigger.template(RFBridgeData)) +RFBridgeReceivedCodeTrigger = rf_bridge_ns.class_( + "RFBridgeReceivedCodeTrigger", automation.Trigger.template(RFBridgeData) +) RFBridgeReceivedAdvancedCodeTrigger = rf_bridge_ns.class_( - 'RFBridgeReceivedAdvancedCodeTrigger', + "RFBridgeReceivedAdvancedCodeTrigger", automation.Trigger.template(RFBridgeAdvancedData), ) -RFBridgeSendCodeAction = rf_bridge_ns.class_('RFBridgeSendCodeAction', automation.Action) +RFBridgeSendCodeAction = rf_bridge_ns.class_( + "RFBridgeSendCodeAction", automation.Action +) RFBridgeSendAdvancedCodeAction = rf_bridge_ns.class_( - 'RFBridgeSendAdvancedCodeAction', automation.Action) + "RFBridgeSendAdvancedCodeAction", automation.Action +) -RFBridgeLearnAction = rf_bridge_ns.class_('RFBridgeLearnAction', automation.Action) +RFBridgeLearnAction = rf_bridge_ns.class_("RFBridgeLearnAction", automation.Action) RFBridgeStartAdvancedSniffingAction = rf_bridge_ns.class_( - 'RFBridgeStartAdvancedSniffingAction', automation.Action) + "RFBridgeStartAdvancedSniffingAction", automation.Action +) RFBridgeStopAdvancedSniffingAction = rf_bridge_ns.class_( - 'RFBridgeStopAdvancedSniffingAction', automation.Action) + "RFBridgeStopAdvancedSniffingAction", automation.Action +) -RFBridgeSendRawAction = rf_bridge_ns.class_('RFBridgeSendRawAction', automation.Action) +RFBridgeSendRawAction = rf_bridge_ns.class_("RFBridgeSendRawAction", automation.Action) -CONF_ON_CODE_RECEIVED = 'on_code_received' -CONF_ON_ADVANCED_CODE_RECEIVED = 'on_advanced_code_received' +CONF_ON_CODE_RECEIVED = "on_code_received" +CONF_ON_ADVANCED_CODE_RECEIVED = "on_advanced_code_received" -CONFIG_SCHEMA = cv.All(cv.Schema({ - cv.GenerateID(): cv.declare_id(RFBridgeComponent), - cv.Optional(CONF_ON_CODE_RECEIVED): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(RFBridgeReceivedCodeTrigger), - }), - cv.Optional(CONF_ON_ADVANCED_CODE_RECEIVED): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(RFBridgeReceivedAdvancedCodeTrigger), - }), -}).extend(uart.UART_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA)) +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(RFBridgeComponent), + cv.Optional(CONF_ON_CODE_RECEIVED): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + RFBridgeReceivedCodeTrigger + ), + } + ), + cv.Optional(CONF_ON_ADVANCED_CODE_RECEIVED): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + RFBridgeReceivedAdvancedCodeTrigger + ), + } + ), + } + ) + .extend(uart.UART_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): @@ -64,26 +86,29 @@ def to_code(config): for conf in config.get(CONF_ON_CODE_RECEIVED, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - yield automation.build_automation(trigger, [(RFBridgeData, 'data')], conf) + yield automation.build_automation(trigger, [(RFBridgeData, "data")], conf) for conf in config.get(CONF_ON_ADVANCED_CODE_RECEIVED, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) yield automation.build_automation( - trigger, [(RFBridgeAdvancedData, 'data')], conf + trigger, [(RFBridgeAdvancedData, "data")], conf ) -RFBRIDGE_SEND_CODE_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.use_id(RFBridgeComponent), - cv.Required(CONF_SYNC): cv.templatable(cv.hex_uint16_t), - cv.Required(CONF_LOW): cv.templatable(cv.hex_uint16_t), - cv.Required(CONF_HIGH): cv.templatable(cv.hex_uint16_t), - cv.Required(CONF_CODE): cv.templatable(cv.hex_uint32_t) -}) +RFBRIDGE_SEND_CODE_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.use_id(RFBridgeComponent), + cv.Required(CONF_SYNC): cv.templatable(cv.hex_uint16_t), + cv.Required(CONF_LOW): cv.templatable(cv.hex_uint16_t), + cv.Required(CONF_HIGH): cv.templatable(cv.hex_uint16_t), + cv.Required(CONF_CODE): cv.templatable(cv.hex_uint32_t), + } +) -@automation.register_action('rf_bridge.send_code', RFBridgeSendCodeAction, - RFBRIDGE_SEND_CODE_SCHEMA) +@automation.register_action( + "rf_bridge.send_code", RFBridgeSendCodeAction, RFBRIDGE_SEND_CODE_SCHEMA +) def rf_bridge_send_code_to_code(config, action_id, template_args, args): paren = yield cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(action_id, template_args, paren) @@ -98,12 +123,10 @@ def rf_bridge_send_code_to_code(config, action_id, template_args, args): yield var -RFBRIDGE_ID_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.use_id(RFBridgeComponent) -}) +RFBRIDGE_ID_SCHEMA = cv.Schema({cv.GenerateID(): cv.use_id(RFBridgeComponent)}) -@automation.register_action('rf_bridge.learn', RFBridgeLearnAction, RFBRIDGE_ID_SCHEMA) +@automation.register_action("rf_bridge.learn", RFBridgeLearnAction, RFBRIDGE_ID_SCHEMA) def rf_bridge_learnx_to_code(config, action_id, template_args, args): paren = yield cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(action_id, template_args, paren) @@ -111,7 +134,7 @@ def rf_bridge_learnx_to_code(config, action_id, template_args, args): @automation.register_action( - 'rf_bridge.start_advanced_sniffing', + "rf_bridge.start_advanced_sniffing", RFBridgeStartAdvancedSniffingAction, RFBRIDGE_ID_SCHEMA, ) @@ -122,7 +145,7 @@ def rf_bridge_start_advanced_sniffing_to_code(config, action_id, template_args, @automation.register_action( - 'rf_bridge.stop_advanced_sniffing', + "rf_bridge.stop_advanced_sniffing", RFBridgeStopAdvancedSniffingAction, RFBRIDGE_ID_SCHEMA, ) @@ -132,18 +155,20 @@ def rf_bridge_stop_advanced_sniffing_to_code(config, action_id, template_args, a yield var -RFBRIDGE_SEND_ADVANCED_CODE_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.use_id(RFBridgeComponent), - cv.Required(CONF_LENGTH): cv.templatable(cv.hex_uint8_t), - cv.Required(CONF_PROTOCOL): cv.templatable(cv.hex_uint8_t), - cv.Required(CONF_CODE): cv.templatable(cv.string), -}) +RFBRIDGE_SEND_ADVANCED_CODE_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.use_id(RFBridgeComponent), + cv.Required(CONF_LENGTH): cv.templatable(cv.hex_uint8_t), + cv.Required(CONF_PROTOCOL): cv.templatable(cv.hex_uint8_t), + cv.Required(CONF_CODE): cv.templatable(cv.string), + } +) @automation.register_action( - 'rf_bridge.send_advanced_code', + "rf_bridge.send_advanced_code", RFBridgeSendAdvancedCodeAction, - RFBRIDGE_SEND_ADVANCED_CODE_SCHEMA + RFBRIDGE_SEND_ADVANCED_CODE_SCHEMA, ) def rf_bridge_send_advanced_code_to_code(config, action_id, template_args, args): paren = yield cg.get_variable(config[CONF_ID]) @@ -166,9 +191,7 @@ RFBRIDGE_SEND_RAW_SCHEMA = cv.Schema( @automation.register_action( - 'rf_bridge.send_raw', - RFBridgeSendRawAction, - RFBRIDGE_SEND_RAW_SCHEMA + "rf_bridge.send_raw", RFBridgeSendRawAction, RFBRIDGE_SEND_RAW_SCHEMA ) def rf_bridge_send_raw_to_code(config, action_id, template_args, args): paren = yield cg.get_variable(config[CONF_ID]) diff --git a/esphome/components/rgb/light.py b/esphome/components/rgb/light.py index 6bece1766..33e381d59 100644 --- a/esphome/components/rgb/light.py +++ b/esphome/components/rgb/light.py @@ -3,15 +3,17 @@ import esphome.config_validation as cv from esphome.components import light, output from esphome.const import CONF_BLUE, CONF_GREEN, CONF_RED, CONF_OUTPUT_ID -rgb_ns = cg.esphome_ns.namespace('rgb') -RGBLightOutput = rgb_ns.class_('RGBLightOutput', light.LightOutput) +rgb_ns = cg.esphome_ns.namespace("rgb") +RGBLightOutput = rgb_ns.class_("RGBLightOutput", light.LightOutput) -CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend({ - cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(RGBLightOutput), - cv.Required(CONF_RED): cv.use_id(output.FloatOutput), - cv.Required(CONF_GREEN): cv.use_id(output.FloatOutput), - cv.Required(CONF_BLUE): cv.use_id(output.FloatOutput), -}) +CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend( + { + cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(RGBLightOutput), + cv.Required(CONF_RED): cv.use_id(output.FloatOutput), + cv.Required(CONF_GREEN): cv.use_id(output.FloatOutput), + cv.Required(CONF_BLUE): cv.use_id(output.FloatOutput), + } +) def to_code(config): diff --git a/esphome/components/rgbw/light.py b/esphome/components/rgbw/light.py index ca31a8229..a922a7de3 100644 --- a/esphome/components/rgbw/light.py +++ b/esphome/components/rgbw/light.py @@ -3,18 +3,20 @@ import esphome.config_validation as cv from esphome.components import light, output from esphome.const import CONF_BLUE, CONF_GREEN, CONF_RED, CONF_OUTPUT_ID, CONF_WHITE -rgbw_ns = cg.esphome_ns.namespace('rgbw') -RGBWLightOutput = rgbw_ns.class_('RGBWLightOutput', light.LightOutput) -CONF_COLOR_INTERLOCK = 'color_interlock' +rgbw_ns = cg.esphome_ns.namespace("rgbw") +RGBWLightOutput = rgbw_ns.class_("RGBWLightOutput", light.LightOutput) +CONF_COLOR_INTERLOCK = "color_interlock" -CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend({ - cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(RGBWLightOutput), - cv.Required(CONF_RED): cv.use_id(output.FloatOutput), - cv.Required(CONF_GREEN): cv.use_id(output.FloatOutput), - cv.Required(CONF_BLUE): cv.use_id(output.FloatOutput), - cv.Required(CONF_WHITE): cv.use_id(output.FloatOutput), - cv.Optional(CONF_COLOR_INTERLOCK, default=False): cv.boolean, -}) +CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend( + { + cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(RGBWLightOutput), + cv.Required(CONF_RED): cv.use_id(output.FloatOutput), + cv.Required(CONF_GREEN): cv.use_id(output.FloatOutput), + cv.Required(CONF_BLUE): cv.use_id(output.FloatOutput), + cv.Required(CONF_WHITE): cv.use_id(output.FloatOutput), + cv.Optional(CONF_COLOR_INTERLOCK, default=False): cv.boolean, + } +) def to_code(config): diff --git a/esphome/components/rgbww/light.py b/esphome/components/rgbww/light.py index 1513a684e..d7d0d7fb1 100644 --- a/esphome/components/rgbww/light.py +++ b/esphome/components/rgbww/light.py @@ -1,28 +1,37 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import light, output -from esphome.const import CONF_BLUE, CONF_GREEN, CONF_RED, CONF_OUTPUT_ID, CONF_COLD_WHITE, \ - CONF_WARM_WHITE, CONF_COLD_WHITE_COLOR_TEMPERATURE, \ - CONF_WARM_WHITE_COLOR_TEMPERATURE +from esphome.const import ( + CONF_BLUE, + CONF_GREEN, + CONF_RED, + CONF_OUTPUT_ID, + CONF_COLD_WHITE, + CONF_WARM_WHITE, + CONF_COLD_WHITE_COLOR_TEMPERATURE, + CONF_WARM_WHITE_COLOR_TEMPERATURE, +) -rgbww_ns = cg.esphome_ns.namespace('rgbww') -RGBWWLightOutput = rgbww_ns.class_('RGBWWLightOutput', light.LightOutput) +rgbww_ns = cg.esphome_ns.namespace("rgbww") +RGBWWLightOutput = rgbww_ns.class_("RGBWWLightOutput", light.LightOutput) -CONF_CONSTANT_BRIGHTNESS = 'constant_brightness' -CONF_COLOR_INTERLOCK = 'color_interlock' +CONF_CONSTANT_BRIGHTNESS = "constant_brightness" +CONF_COLOR_INTERLOCK = "color_interlock" -CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend({ - cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(RGBWWLightOutput), - cv.Required(CONF_RED): cv.use_id(output.FloatOutput), - cv.Required(CONF_GREEN): cv.use_id(output.FloatOutput), - cv.Required(CONF_BLUE): cv.use_id(output.FloatOutput), - 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, - cv.Optional(CONF_COLOR_INTERLOCK, default=False): cv.boolean, -}) +CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend( + { + cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(RGBWWLightOutput), + cv.Required(CONF_RED): cv.use_id(output.FloatOutput), + cv.Required(CONF_GREEN): cv.use_id(output.FloatOutput), + cv.Required(CONF_BLUE): cv.use_id(output.FloatOutput), + 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, + cv.Optional(CONF_COLOR_INTERLOCK, default=False): cv.boolean, + } +) def to_code(config): diff --git a/esphome/components/rotary_encoder/sensor.py b/esphome/components/rotary_encoder/sensor.py index 4064cdea8..bcc4a5c93 100644 --- a/esphome/components/rotary_encoder/sensor.py +++ b/esphome/components/rotary_encoder/sensor.py @@ -2,30 +2,45 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins, automation from esphome.components import sensor -from esphome.const import CONF_ID, CONF_RESOLUTION, CONF_MIN_VALUE, CONF_MAX_VALUE, \ - DEVICE_CLASS_EMPTY, UNIT_STEPS, ICON_ROTATE_RIGHT, CONF_VALUE, CONF_PIN_A, CONF_PIN_B, \ - CONF_TRIGGER_ID +from esphome.const import ( + CONF_ID, + CONF_RESOLUTION, + CONF_MIN_VALUE, + CONF_MAX_VALUE, + DEVICE_CLASS_EMPTY, + UNIT_STEPS, + ICON_ROTATE_RIGHT, + CONF_VALUE, + CONF_PIN_A, + CONF_PIN_B, + CONF_TRIGGER_ID, +) -rotary_encoder_ns = cg.esphome_ns.namespace('rotary_encoder') -RotaryEncoderResolution = rotary_encoder_ns.enum('RotaryEncoderResolution') +rotary_encoder_ns = cg.esphome_ns.namespace("rotary_encoder") +RotaryEncoderResolution = rotary_encoder_ns.enum("RotaryEncoderResolution") RESOLUTIONS = { 1: RotaryEncoderResolution.ROTARY_ENCODER_1_PULSE_PER_CYCLE, 2: RotaryEncoderResolution.ROTARY_ENCODER_2_PULSES_PER_CYCLE, 4: RotaryEncoderResolution.ROTARY_ENCODER_4_PULSES_PER_CYCLE, } -CONF_PIN_RESET = 'pin_reset' -CONF_ON_CLOCKWISE = 'on_clockwise' -CONF_ON_ANTICLOCKWISE = 'on_anticlockwise' +CONF_PIN_RESET = "pin_reset" +CONF_ON_CLOCKWISE = "on_clockwise" +CONF_ON_ANTICLOCKWISE = "on_anticlockwise" -RotaryEncoderSensor = rotary_encoder_ns.class_('RotaryEncoderSensor', sensor.Sensor, cg.Component) -RotaryEncoderSetValueAction = rotary_encoder_ns.class_('RotaryEncoderSetValueAction', - automation.Action) +RotaryEncoderSensor = rotary_encoder_ns.class_( + "RotaryEncoderSensor", sensor.Sensor, cg.Component +) +RotaryEncoderSetValueAction = rotary_encoder_ns.class_( + "RotaryEncoderSetValueAction", automation.Action +) -RotaryEncoderClockwiseTrigger = rotary_encoder_ns.class_('RotaryEncoderClockwiseTrigger', - automation.Trigger) -RotaryEncoderAnticlockwiseTrigger = rotary_encoder_ns.class_('RotaryEncoderAnticlockwiseTrigger', - automation.Trigger) +RotaryEncoderClockwiseTrigger = rotary_encoder_ns.class_( + "RotaryEncoderClockwiseTrigger", automation.Trigger +) +RotaryEncoderAnticlockwiseTrigger = rotary_encoder_ns.class_( + "RotaryEncoderAnticlockwiseTrigger", automation.Trigger +) def validate_min_max_value(config): @@ -33,30 +48,47 @@ def validate_min_max_value(config): min_val = config[CONF_MIN_VALUE] max_val = config[CONF_MAX_VALUE] if min_val >= max_val: - raise cv.Invalid("Max value {} must be smaller than min value {}" - "".format(max_val, min_val)) + raise cv.Invalid( + "Max value {} must be smaller than min value {}" + "".format(max_val, min_val) + ) return config -CONFIG_SCHEMA = cv.All(sensor.sensor_schema( - UNIT_STEPS, ICON_ROTATE_RIGHT, 0, DEVICE_CLASS_EMPTY -).extend({ - cv.GenerateID(): cv.declare_id(RotaryEncoderSensor), - cv.Required(CONF_PIN_A): cv.All(pins.internal_gpio_input_pin_schema, - pins.validate_has_interrupt), - cv.Required(CONF_PIN_B): cv.All(pins.internal_gpio_input_pin_schema, - pins.validate_has_interrupt), - cv.Optional(CONF_PIN_RESET): pins.internal_gpio_output_pin_schema, - cv.Optional(CONF_RESOLUTION, default=1): cv.enum(RESOLUTIONS, int=True), - cv.Optional(CONF_MIN_VALUE): cv.int_, - cv.Optional(CONF_MAX_VALUE): cv.int_, - cv.Optional(CONF_ON_CLOCKWISE): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(RotaryEncoderClockwiseTrigger), - }), - cv.Optional(CONF_ON_ANTICLOCKWISE): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(RotaryEncoderAnticlockwiseTrigger), - }), -}).extend(cv.COMPONENT_SCHEMA), validate_min_max_value) +CONFIG_SCHEMA = cv.All( + sensor.sensor_schema(UNIT_STEPS, ICON_ROTATE_RIGHT, 0, DEVICE_CLASS_EMPTY) + .extend( + { + cv.GenerateID(): cv.declare_id(RotaryEncoderSensor), + cv.Required(CONF_PIN_A): cv.All( + pins.internal_gpio_input_pin_schema, pins.validate_has_interrupt + ), + cv.Required(CONF_PIN_B): cv.All( + pins.internal_gpio_input_pin_schema, pins.validate_has_interrupt + ), + cv.Optional(CONF_PIN_RESET): pins.internal_gpio_output_pin_schema, + cv.Optional(CONF_RESOLUTION, default=1): cv.enum(RESOLUTIONS, int=True), + cv.Optional(CONF_MIN_VALUE): cv.int_, + cv.Optional(CONF_MAX_VALUE): cv.int_, + cv.Optional(CONF_ON_CLOCKWISE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + RotaryEncoderClockwiseTrigger + ), + } + ), + cv.Optional(CONF_ON_ANTICLOCKWISE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + RotaryEncoderAnticlockwiseTrigger + ), + } + ), + } + ) + .extend(cv.COMPONENT_SCHEMA), + validate_min_max_value, +) def to_code(config): @@ -85,11 +117,16 @@ def to_code(config): yield automation.build_automation(trigger, [], conf) -@automation.register_action('sensor.rotary_encoder.set_value', RotaryEncoderSetValueAction, - cv.Schema({ - cv.Required(CONF_ID): cv.use_id(sensor.Sensor), - cv.Required(CONF_VALUE): cv.templatable(cv.int_), - })) +@automation.register_action( + "sensor.rotary_encoder.set_value", + RotaryEncoderSetValueAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(sensor.Sensor), + cv.Required(CONF_VALUE): cv.templatable(cv.int_), + } + ), +) def sensor_template_publish_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) diff --git a/esphome/components/rtttl/__init__.py b/esphome/components/rtttl/__init__.py index a276f7cb8..97b7405c6 100644 --- a/esphome/components/rtttl/__init__.py +++ b/esphome/components/rtttl/__init__.py @@ -4,28 +4,33 @@ from esphome import automation from esphome.components.output import FloatOutput from esphome.const import CONF_ID, CONF_OUTPUT, CONF_TRIGGER_ID -CODEOWNERS = ['@glmnet'] -CONF_RTTTL = 'rtttl' -CONF_ON_FINISHED_PLAYBACK = 'on_finished_playback' +CODEOWNERS = ["@glmnet"] +CONF_RTTTL = "rtttl" +CONF_ON_FINISHED_PLAYBACK = "on_finished_playback" -rtttl_ns = cg.esphome_ns.namespace('rtttl') +rtttl_ns = cg.esphome_ns.namespace("rtttl") -Rtttl = rtttl_ns .class_('Rtttl', cg.Component) -PlayAction = rtttl_ns.class_('PlayAction', automation.Action) -StopAction = rtttl_ns.class_('StopAction', automation.Action) -FinishedPlaybackTrigger = rtttl_ns.class_('FinishedPlaybackTrigger', - automation.Trigger.template()) -IsPlayingCondition = rtttl_ns.class_('IsPlayingCondition', automation.Condition) +Rtttl = rtttl_ns.class_("Rtttl", cg.Component) +PlayAction = rtttl_ns.class_("PlayAction", automation.Action) +StopAction = rtttl_ns.class_("StopAction", automation.Action) +FinishedPlaybackTrigger = rtttl_ns.class_( + "FinishedPlaybackTrigger", automation.Trigger.template() +) +IsPlayingCondition = rtttl_ns.class_("IsPlayingCondition", automation.Condition) MULTI_CONF = True -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(CONF_ID): cv.declare_id(Rtttl), - cv.Required(CONF_OUTPUT): cv.use_id(FloatOutput), - cv.Optional(CONF_ON_FINISHED_PLAYBACK): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FinishedPlaybackTrigger), - }), -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_ID): cv.declare_id(Rtttl), + cv.Required(CONF_OUTPUT): cv.use_id(FloatOutput), + cv.Optional(CONF_ON_FINISHED_PLAYBACK): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FinishedPlaybackTrigger), + } + ), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): @@ -40,10 +45,17 @@ def to_code(config): yield automation.build_automation(trigger, [], conf) -@automation.register_action('rtttl.play', PlayAction, cv.maybe_simple_value({ - cv.GenerateID(CONF_ID): cv.use_id(Rtttl), - cv.Required(CONF_RTTTL): cv.templatable(cv.string) -}, key=CONF_RTTTL)) +@automation.register_action( + "rtttl.play", + PlayAction, + cv.maybe_simple_value( + { + cv.GenerateID(CONF_ID): cv.use_id(Rtttl), + cv.Required(CONF_RTTTL): cv.templatable(cv.string), + }, + key=CONF_RTTTL, + ), +) def rtttl_play_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) @@ -52,18 +64,30 @@ def rtttl_play_to_code(config, action_id, template_arg, args): yield var -@automation.register_action('rtttl.stop', StopAction, cv.Schema({ - cv.GenerateID(): cv.use_id(Rtttl), -})) +@automation.register_action( + "rtttl.stop", + StopAction, + cv.Schema( + { + cv.GenerateID(): cv.use_id(Rtttl), + } + ), +) def rtttl_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_condition('rtttl.is_playing', IsPlayingCondition, cv.Schema({ - cv.GenerateID(): cv.use_id(Rtttl), -})) +@automation.register_condition( + "rtttl.is_playing", + IsPlayingCondition, + cv.Schema( + { + cv.GenerateID(): cv.use_id(Rtttl), + } + ), +) def rtttl_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]) diff --git a/esphome/components/ruuvi_ble/__init__.py b/esphome/components/ruuvi_ble/__init__.py index 05ba008dd..74aec457b 100644 --- a/esphome/components/ruuvi_ble/__init__.py +++ b/esphome/components/ruuvi_ble/__init__.py @@ -3,14 +3,18 @@ import esphome.config_validation as cv from esphome.components import esp32_ble_tracker from esphome.const import CONF_ID -DEPENDENCIES = ['esp32_ble_tracker'] +DEPENDENCIES = ["esp32_ble_tracker"] -ruuvi_ble_ns = cg.esphome_ns.namespace('ruuvi_ble') -RuuviListener = ruuvi_ble_ns.class_('RuuviListener', esp32_ble_tracker.ESPBTDeviceListener) +ruuvi_ble_ns = cg.esphome_ns.namespace("ruuvi_ble") +RuuviListener = ruuvi_ble_ns.class_( + "RuuviListener", esp32_ble_tracker.ESPBTDeviceListener +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(RuuviListener), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(RuuviListener), + } +).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) def to_code(config): diff --git a/esphome/components/ruuvitag/sensor.py b/esphome/components/ruuvitag/sensor.py index e99265226..2bde7b485 100644 --- a/esphome/components/ruuvitag/sensor.py +++ b/esphome/components/ruuvitag/sensor.py @@ -1,48 +1,92 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, esp32_ble_tracker -from esphome.const import CONF_HUMIDITY, CONF_MAC_ADDRESS, CONF_TEMPERATURE, CONF_PRESSURE, \ - CONF_ACCELERATION, CONF_ACCELERATION_X, CONF_ACCELERATION_Y, CONF_ACCELERATION_Z, \ - CONF_BATTERY_VOLTAGE, CONF_TX_POWER, CONF_MEASUREMENT_SEQUENCE_NUMBER, CONF_MOVEMENT_COUNTER, \ - DEVICE_CLASS_EMPTY, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_PRESSURE, \ - DEVICE_CLASS_SIGNAL_STRENGTH, DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_VOLTAGE, ICON_EMPTY, \ - UNIT_CELSIUS, UNIT_PERCENT, UNIT_VOLT, UNIT_HECTOPASCAL, UNIT_G, UNIT_DECIBEL_MILLIWATT, \ - UNIT_EMPTY, ICON_GAUGE, ICON_ACCELERATION, ICON_ACCELERATION_X, ICON_ACCELERATION_Y, \ - ICON_ACCELERATION_Z, CONF_ID +from esphome.const import ( + CONF_HUMIDITY, + CONF_MAC_ADDRESS, + CONF_TEMPERATURE, + CONF_PRESSURE, + CONF_ACCELERATION, + CONF_ACCELERATION_X, + CONF_ACCELERATION_Y, + CONF_ACCELERATION_Z, + CONF_BATTERY_VOLTAGE, + CONF_TX_POWER, + CONF_MEASUREMENT_SEQUENCE_NUMBER, + CONF_MOVEMENT_COUNTER, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_PRESSURE, + DEVICE_CLASS_SIGNAL_STRENGTH, + DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_VOLTAGE, + ICON_EMPTY, + UNIT_CELSIUS, + UNIT_PERCENT, + UNIT_VOLT, + UNIT_HECTOPASCAL, + UNIT_G, + UNIT_DECIBEL_MILLIWATT, + UNIT_EMPTY, + ICON_GAUGE, + ICON_ACCELERATION, + ICON_ACCELERATION_X, + ICON_ACCELERATION_Y, + ICON_ACCELERATION_Z, + CONF_ID, +) -DEPENDENCIES = ['esp32_ble_tracker'] -AUTO_LOAD = ['ruuvi_ble'] +DEPENDENCIES = ["esp32_ble_tracker"] +AUTO_LOAD = ["ruuvi_ble"] -ruuvitag_ns = cg.esphome_ns.namespace('ruuvitag') +ruuvitag_ns = cg.esphome_ns.namespace("ruuvitag") RuuviTag = ruuvitag_ns.class_( - 'RuuviTag', esp32_ble_tracker.ESPBTDeviceListener, cg.Component) + "RuuviTag", esp32_ble_tracker.ESPBTDeviceListener, cg.Component +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(RuuviTag), - cv.Required(CONF_MAC_ADDRESS): cv.mac_address, - 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), - cv.Optional(CONF_PRESSURE): sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_EMPTY, 2, - DEVICE_CLASS_PRESSURE), - cv.Optional(CONF_ACCELERATION): sensor.sensor_schema(UNIT_G, ICON_ACCELERATION, 3, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_ACCELERATION_X): sensor.sensor_schema(UNIT_G, ICON_ACCELERATION_X, 3, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_ACCELERATION_Y): sensor.sensor_schema(UNIT_G, ICON_ACCELERATION_Y, 3, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_ACCELERATION_Z): sensor.sensor_schema(UNIT_G, ICON_ACCELERATION_Z, 3, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_BATTERY_VOLTAGE): sensor.sensor_schema(UNIT_VOLT, ICON_EMPTY, 3, - DEVICE_CLASS_VOLTAGE), - cv.Optional(CONF_TX_POWER): sensor.sensor_schema(UNIT_DECIBEL_MILLIWATT, ICON_EMPTY, 0, - DEVICE_CLASS_SIGNAL_STRENGTH), - cv.Optional(CONF_MOVEMENT_COUNTER): sensor.sensor_schema(UNIT_EMPTY, ICON_GAUGE, 0, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_MEASUREMENT_SEQUENCE_NUMBER): sensor.sensor_schema(UNIT_EMPTY, ICON_GAUGE, 0, - DEVICE_CLASS_EMPTY), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(RuuviTag), + cv.Required(CONF_MAC_ADDRESS): cv.mac_address, + 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 + ), + cv.Optional(CONF_PRESSURE): sensor.sensor_schema( + UNIT_HECTOPASCAL, ICON_EMPTY, 2, DEVICE_CLASS_PRESSURE + ), + cv.Optional(CONF_ACCELERATION): sensor.sensor_schema( + UNIT_G, ICON_ACCELERATION, 3, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_ACCELERATION_X): sensor.sensor_schema( + UNIT_G, ICON_ACCELERATION_X, 3, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_ACCELERATION_Y): sensor.sensor_schema( + UNIT_G, ICON_ACCELERATION_Y, 3, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_ACCELERATION_Z): sensor.sensor_schema( + UNIT_G, ICON_ACCELERATION_Z, 3, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_BATTERY_VOLTAGE): sensor.sensor_schema( + UNIT_VOLT, ICON_EMPTY, 3, DEVICE_CLASS_VOLTAGE + ), + cv.Optional(CONF_TX_POWER): sensor.sensor_schema( + UNIT_DECIBEL_MILLIWATT, ICON_EMPTY, 0, DEVICE_CLASS_SIGNAL_STRENGTH + ), + cv.Optional(CONF_MOVEMENT_COUNTER): sensor.sensor_schema( + UNIT_EMPTY, ICON_GAUGE, 0, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_MEASUREMENT_SEQUENCE_NUMBER): sensor.sensor_schema( + UNIT_EMPTY, ICON_GAUGE, 0, DEVICE_CLASS_EMPTY + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/scd30/sensor.py b/esphome/components/scd30/sensor.py index 5cbc55fbd..aa3e5b65b 100644 --- a/esphome/components/scd30/sensor.py +++ b/esphome/components/scd30/sensor.py @@ -2,40 +2,61 @@ import re 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, CONF_HUMIDITY, CONF_TEMPERATURE, CONF_CO2, \ - DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, UNIT_PARTS_PER_MILLION, \ - ICON_MOLECULE_CO2, UNIT_CELSIUS, UNIT_PERCENT +from esphome.const import ( + CONF_ID, + DEVICE_CLASS_EMPTY, + CONF_HUMIDITY, + CONF_TEMPERATURE, + CONF_CO2, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_TEMPERATURE, + ICON_EMPTY, + UNIT_PARTS_PER_MILLION, + ICON_MOLECULE_CO2, + UNIT_CELSIUS, + UNIT_PERCENT, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -scd30_ns = cg.esphome_ns.namespace('scd30') -SCD30Component = scd30_ns.class_('SCD30Component', cg.PollingComponent, i2c.I2CDevice) +scd30_ns = cg.esphome_ns.namespace("scd30") +SCD30Component = scd30_ns.class_("SCD30Component", cg.PollingComponent, i2c.I2CDevice) -CONF_AUTOMATIC_SELF_CALIBRATION = 'automatic_self_calibration' -CONF_ALTITUDE_COMPENSATION = 'altitude_compensation' -CONF_AMBIENT_PRESSURE_COMPENSATION = 'ambient_pressure_compensation' -CONF_TEMPERATURE_OFFSET = 'temperature_offset' +CONF_AUTOMATIC_SELF_CALIBRATION = "automatic_self_calibration" +CONF_ALTITUDE_COMPENSATION = "altitude_compensation" +CONF_AMBIENT_PRESSURE_COMPENSATION = "ambient_pressure_compensation" +CONF_TEMPERATURE_OFFSET = "temperature_offset" def remove_altitude_suffix(value): - return re.sub(r"\s*(?:m(?:\s+a\.s\.l)?)|(?:MAM?SL)$", '', value) + return re.sub(r"\s*(?:m(?:\s+a\.s\.l)?)|(?:MAM?SL)$", "", value) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(SCD30Component), - cv.Optional(CONF_CO2): sensor.sensor_schema(UNIT_PARTS_PER_MILLION, - ICON_MOLECULE_CO2, 0, DEVICE_CLASS_EMPTY), - 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), - cv.Optional(CONF_AUTOMATIC_SELF_CALIBRATION, default=True): cv.boolean, - cv.Optional(CONF_ALTITUDE_COMPENSATION): cv.All(remove_altitude_suffix, - cv.int_range(min=0, max=0xFFFF, - max_included=False)), - cv.Optional(CONF_AMBIENT_PRESSURE_COMPENSATION, default=0): cv.pressure, - cv.Optional(CONF_TEMPERATURE_OFFSET): cv.temperature, -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x61)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(SCD30Component), + cv.Optional(CONF_CO2): sensor.sensor_schema( + UNIT_PARTS_PER_MILLION, ICON_MOLECULE_CO2, 0, DEVICE_CLASS_EMPTY + ), + 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 + ), + cv.Optional(CONF_AUTOMATIC_SELF_CALIBRATION, default=True): cv.boolean, + cv.Optional(CONF_ALTITUDE_COMPENSATION): cv.All( + remove_altitude_suffix, + cv.int_range(min=0, max=0xFFFF, max_included=False), + ), + cv.Optional(CONF_AMBIENT_PRESSURE_COMPENSATION, default=0): cv.pressure, + cv.Optional(CONF_TEMPERATURE_OFFSET): cv.temperature, + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x61)) +) def to_code(config): @@ -48,7 +69,11 @@ def to_code(config): cg.add(var.set_altitude_compensation(config[CONF_ALTITUDE_COMPENSATION])) if CONF_AMBIENT_PRESSURE_COMPENSATION in config: - cg.add(var.set_ambient_pressure_compensation(config[CONF_AMBIENT_PRESSURE_COMPENSATION])) + cg.add( + var.set_ambient_pressure_compensation( + config[CONF_AMBIENT_PRESSURE_COMPENSATION] + ) + ) if CONF_TEMPERATURE_OFFSET in config: cg.add(var.set_temperature_offset(config[CONF_TEMPERATURE_OFFSET])) diff --git a/esphome/components/script/__init__.py b/esphome/components/script/__init__.py index cdb334446..45b01778d 100644 --- a/esphome/components/script/__init__.py +++ b/esphome/components/script/__init__.py @@ -4,23 +4,23 @@ from esphome import automation from esphome.automation import maybe_simple_id from esphome.const import CONF_ID, CONF_MODE -CODEOWNERS = ['@esphome/core'] -script_ns = cg.esphome_ns.namespace('script') -Script = script_ns.class_('Script', automation.Trigger.template()) -ScriptExecuteAction = script_ns.class_('ScriptExecuteAction', automation.Action) -ScriptStopAction = script_ns.class_('ScriptStopAction', automation.Action) -ScriptWaitAction = script_ns.class_('ScriptWaitAction', automation.Action, cg.Component) -IsRunningCondition = script_ns.class_('IsRunningCondition', automation.Condition) -SingleScript = script_ns.class_('SingleScript', Script) -RestartScript = script_ns.class_('RestartScript', Script) -QueueingScript = script_ns.class_('QueueingScript', Script, cg.Component) -ParallelScript = script_ns.class_('ParallelScript', Script) +CODEOWNERS = ["@esphome/core"] +script_ns = cg.esphome_ns.namespace("script") +Script = script_ns.class_("Script", automation.Trigger.template()) +ScriptExecuteAction = script_ns.class_("ScriptExecuteAction", automation.Action) +ScriptStopAction = script_ns.class_("ScriptStopAction", automation.Action) +ScriptWaitAction = script_ns.class_("ScriptWaitAction", automation.Action, cg.Component) +IsRunningCondition = script_ns.class_("IsRunningCondition", automation.Condition) +SingleScript = script_ns.class_("SingleScript", Script) +RestartScript = script_ns.class_("RestartScript", Script) +QueueingScript = script_ns.class_("QueueingScript", Script, cg.Component) +ParallelScript = script_ns.class_("ParallelScript", Script) -CONF_SINGLE = 'single' -CONF_RESTART = 'restart' -CONF_QUEUED = 'queued' -CONF_PARALLEL = 'parallel' -CONF_MAX_RUNS = 'max_runs' +CONF_SINGLE = "single" +CONF_RESTART = "restart" +CONF_QUEUED = "queued" +CONF_PARALLEL = "parallel" +CONF_MAX_RUNS = "max_runs" SCRIPT_MODES = { CONF_SINGLE: SingleScript, @@ -34,8 +34,10 @@ def check_max_runs(value): if CONF_MAX_RUNS not in value: return value if value[CONF_MODE] not in [CONF_QUEUED, CONF_PARALLEL]: - raise cv.Invalid("The option 'max_runs' is only valid in 'queue' and 'parallel' mode.", - path=[CONF_MAX_RUNS]) + raise cv.Invalid( + "The option 'max_runs' is only valid in 'queue' and 'parallel' mode.", + path=[CONF_MAX_RUNS], + ) return value @@ -45,13 +47,18 @@ def assign_declare_id(value): return value -CONFIG_SCHEMA = automation.validate_automation({ - # Don't declare id as cv.declare_id yet, because the ID type - # dpeends on the mode. Will be checked later with assign_declare_id - cv.Required(CONF_ID): cv.string_strict, - cv.Optional(CONF_MODE, default=CONF_SINGLE): cv.one_of(*SCRIPT_MODES, lower=True), - cv.Optional(CONF_MAX_RUNS): cv.positive_int, -}, extra_validators=cv.All(check_max_runs, assign_declare_id)) +CONFIG_SCHEMA = automation.validate_automation( + { + # Don't declare id as cv.declare_id yet, because the ID type + # dpeends on the mode. Will be checked later with assign_declare_id + cv.Required(CONF_ID): cv.string_strict, + cv.Optional(CONF_MODE, default=CONF_SINGLE): cv.one_of( + *SCRIPT_MODES, lower=True + ), + cv.Optional(CONF_MAX_RUNS): cv.positive_int, + }, + extra_validators=cv.All(check_max_runs, assign_declare_id), +) def to_code(config): @@ -74,25 +81,35 @@ def to_code(config): yield automation.build_automation(trigger, [], conf) -@automation.register_action('script.execute', ScriptExecuteAction, maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(Script), -})) +@automation.register_action( + "script.execute", + ScriptExecuteAction, + maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(Script), + } + ), +) def script_execute_action_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('script.stop', ScriptStopAction, maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(Script) -})) +@automation.register_action( + "script.stop", + ScriptStopAction, + maybe_simple_id({cv.Required(CONF_ID): cv.use_id(Script)}), +) def script_stop_action_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('script.wait', ScriptWaitAction, maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(Script) -})) +@automation.register_action( + "script.wait", + ScriptWaitAction, + maybe_simple_id({cv.Required(CONF_ID): cv.use_id(Script)}), +) def script_wait_action_to_code(config, action_id, template_arg, args): paren = yield cg.get_variable(config[CONF_ID]) var = yield cg.new_Pvariable(action_id, template_arg, paren) @@ -100,9 +117,11 @@ def script_wait_action_to_code(config, action_id, template_arg, args): yield var -@automation.register_condition('script.is_running', IsRunningCondition, automation.maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(Script) -})) +@automation.register_condition( + "script.is_running", + IsRunningCondition, + automation.maybe_simple_id({cv.Required(CONF_ID): cv.use_id(Script)}), +) def script_is_running_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) diff --git a/esphome/components/sds011/sensor.py b/esphome/components/sds011/sensor.py index 7b16f0412..fcee6fe7d 100644 --- a/esphome/components/sds011/sensor.py +++ b/esphome/components/sds011/sensor.py @@ -1,13 +1,21 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, uart -from esphome.const import CONF_ID, CONF_PM_10_0, CONF_PM_2_5, CONF_RX_ONLY, CONF_UPDATE_INTERVAL, \ - DEVICE_CLASS_EMPTY, UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_CHEMICAL_WEAPON +from esphome.const import ( + CONF_ID, + CONF_PM_10_0, + CONF_PM_2_5, + CONF_RX_ONLY, + CONF_UPDATE_INTERVAL, + DEVICE_CLASS_EMPTY, + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, +) -DEPENDENCIES = ['uart'] +DEPENDENCIES = ["uart"] -sds011_ns = cg.esphome_ns.namespace('sds011') -SDS011Component = sds011_ns.class_('SDS011Component', uart.UARTDevice, cg.Component) +sds011_ns = cg.esphome_ns.namespace("sds011") +SDS011Component = sds011_ns.class_("SDS011Component", uart.UARTDevice, cg.Component) def validate_sds011_rx_mode(value): @@ -18,24 +26,37 @@ def validate_sds011_rx_mode(value): elif value.get(CONF_RX_ONLY) and CONF_UPDATE_INTERVAL in value: # update_interval does not affect anything in rx-only mode, let's warn user about # that - raise cv.Invalid("update_interval has no effect in rx_only mode. Please remove it.", - path=['update_interval']) + raise cv.Invalid( + "update_interval has no effect in rx_only mode. Please remove it.", + path=["update_interval"], + ) return value -CONFIG_SCHEMA = cv.All(cv.Schema({ - cv.GenerateID(): cv.declare_id(SDS011Component), - - cv.Optional(CONF_PM_2_5): - sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_CHEMICAL_WEAPON, 1, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_PM_10_0): - sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_CHEMICAL_WEAPON, 1, - DEVICE_CLASS_EMPTY), - - cv.Optional(CONF_RX_ONLY, default=False): cv.boolean, - cv.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_minutes, -}).extend(cv.COMPONENT_SCHEMA).extend(uart.UART_DEVICE_SCHEMA), validate_sds011_rx_mode) +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(SDS011Component), + cv.Optional(CONF_PM_2_5): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, + 1, + DEVICE_CLASS_EMPTY, + ), + cv.Optional(CONF_PM_10_0): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, + 1, + DEVICE_CLASS_EMPTY, + ), + cv.Optional(CONF_RX_ONLY, default=False): cv.boolean, + cv.Optional(CONF_UPDATE_INTERVAL): cv.positive_time_period_minutes, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(uart.UART_DEVICE_SCHEMA), + validate_sds011_rx_mode, +) def to_code(config): diff --git a/esphome/components/senseair/sensor.py b/esphome/components/senseair/sensor.py index 8ce06686b..8f5c7caa6 100644 --- a/esphome/components/senseair/sensor.py +++ b/esphome/components/senseair/sensor.py @@ -1,19 +1,33 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, uart -from esphome.const import CONF_CO2, CONF_ID, DEVICE_CLASS_EMPTY, ICON_MOLECULE_CO2, \ - UNIT_PARTS_PER_MILLION +from esphome.const import ( + CONF_CO2, + CONF_ID, + DEVICE_CLASS_EMPTY, + ICON_MOLECULE_CO2, + UNIT_PARTS_PER_MILLION, +) -DEPENDENCIES = ['uart'] +DEPENDENCIES = ["uart"] -senseair_ns = cg.esphome_ns.namespace('senseair') -SenseAirComponent = senseair_ns.class_('SenseAirComponent', cg.PollingComponent, uart.UARTDevice) +senseair_ns = cg.esphome_ns.namespace("senseair") +SenseAirComponent = senseair_ns.class_( + "SenseAirComponent", cg.PollingComponent, uart.UARTDevice +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(SenseAirComponent), - cv.Required(CONF_CO2): sensor.sensor_schema(UNIT_PARTS_PER_MILLION, ICON_MOLECULE_CO2, 0, - DEVICE_CLASS_EMPTY), -}).extend(cv.polling_component_schema('60s')).extend(uart.UART_DEVICE_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(SenseAirComponent), + cv.Required(CONF_CO2): sensor.sensor_schema( + UNIT_PARTS_PER_MILLION, ICON_MOLECULE_CO2, 0, DEVICE_CLASS_EMPTY + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(uart.UART_DEVICE_SCHEMA) +) def to_code(config): diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index a1de877d7..a10c5d732 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -4,23 +4,64 @@ 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_DEVICE_CLASS, CONF_ABOVE, CONF_ACCURACY_DECIMALS, CONF_ALPHA, \ - CONF_BELOW, CONF_EXPIRE_AFTER, CONF_FILTERS, CONF_FROM, CONF_ICON, CONF_ID, CONF_INTERNAL, \ - CONF_ON_RAW_VALUE, CONF_ON_VALUE, CONF_ON_VALUE_RANGE, CONF_SEND_EVERY, CONF_SEND_FIRST_AT, \ - CONF_TO, CONF_TRIGGER_ID, CONF_UNIT_OF_MEASUREMENT, CONF_WINDOW_SIZE, CONF_NAME, CONF_MQTT_ID, \ - CONF_FORCE_UPDATE, UNIT_EMPTY, ICON_EMPTY, DEVICE_CLASS_EMPTY, DEVICE_CLASS_BATTERY, \ - DEVICE_CLASS_CURRENT, DEVICE_CLASS_ENERGY, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_ILLUMINANCE, \ - DEVICE_CLASS_SIGNAL_STRENGTH, DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_POWER, \ - DEVICE_CLASS_POWER_FACTOR, DEVICE_CLASS_PRESSURE, DEVICE_CLASS_TIMESTAMP, DEVICE_CLASS_VOLTAGE +from esphome.const import ( + CONF_DEVICE_CLASS, + CONF_ABOVE, + CONF_ACCURACY_DECIMALS, + CONF_ALPHA, + CONF_BELOW, + CONF_EXPIRE_AFTER, + CONF_FILTERS, + CONF_FROM, + CONF_ICON, + CONF_ID, + CONF_INTERNAL, + CONF_ON_RAW_VALUE, + CONF_ON_VALUE, + CONF_ON_VALUE_RANGE, + CONF_SEND_EVERY, + CONF_SEND_FIRST_AT, + CONF_TO, + CONF_TRIGGER_ID, + CONF_UNIT_OF_MEASUREMENT, + CONF_WINDOW_SIZE, + CONF_NAME, + CONF_MQTT_ID, + CONF_FORCE_UPDATE, + UNIT_EMPTY, + ICON_EMPTY, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_BATTERY, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_ENERGY, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_ILLUMINANCE, + DEVICE_CLASS_SIGNAL_STRENGTH, + DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_POWER, + DEVICE_CLASS_POWER_FACTOR, + DEVICE_CLASS_PRESSURE, + DEVICE_CLASS_TIMESTAMP, + DEVICE_CLASS_VOLTAGE, +) 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_CURRENT, DEVICE_CLASS_ENERGY, - DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_ILLUMINANCE, DEVICE_CLASS_SIGNAL_STRENGTH, - DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_POWER, DEVICE_CLASS_POWER_FACTOR, DEVICE_CLASS_PRESSURE, - DEVICE_CLASS_TIMESTAMP, DEVICE_CLASS_VOLTAGE + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_BATTERY, + DEVICE_CLASS_CURRENT, + DEVICE_CLASS_ENERGY, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_ILLUMINANCE, + DEVICE_CLASS_SIGNAL_STRENGTH, + DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_POWER, + DEVICE_CLASS_POWER_FACTOR, + DEVICE_CLASS_PRESSURE, + DEVICE_CLASS_TIMESTAMP, + DEVICE_CLASS_VOLTAGE, ] IS_PLATFORM_COMPONENT = True @@ -30,222 +71,302 @@ def validate_send_first_at(value): send_first_at = value.get(CONF_SEND_FIRST_AT) send_every = value[CONF_SEND_EVERY] if send_first_at is not None and send_first_at > send_every: - raise cv.Invalid("send_first_at must be smaller than or equal to send_every! {} <= {}" - "".format(send_first_at, send_every)) + raise cv.Invalid( + "send_first_at must be smaller than or equal to send_every! {} <= {}" + "".format(send_first_at, send_every) + ) return value FILTER_REGISTRY = Registry() -validate_filters = cv.validate_registry('filter', FILTER_REGISTRY) +validate_filters = cv.validate_registry("filter", FILTER_REGISTRY) def validate_datapoint(value): if isinstance(value, dict): - return cv.Schema({ - cv.Required(CONF_FROM): cv.float_, - cv.Required(CONF_TO): cv.float_, - })(value) + return cv.Schema( + { + cv.Required(CONF_FROM): cv.float_, + cv.Required(CONF_TO): cv.float_, + } + )(value) value = cv.string(value) - if '->' not in value: + if "->" not in value: raise cv.Invalid("Datapoint mapping must contain '->'") - a, b = value.split('->', 1) + a, b = value.split("->", 1) a, b = a.strip(), b.strip() - return validate_datapoint({ - CONF_FROM: cv.float_(a), - CONF_TO: cv.float_(b) - }) + return validate_datapoint({CONF_FROM: cv.float_(a), CONF_TO: cv.float_(b)}) # Base -sensor_ns = cg.esphome_ns.namespace('sensor') -Sensor = sensor_ns.class_('Sensor', cg.Nameable) -SensorPtr = Sensor.operator('ptr') +sensor_ns = cg.esphome_ns.namespace("sensor") +Sensor = sensor_ns.class_("Sensor", cg.Nameable) +SensorPtr = Sensor.operator("ptr") # Triggers -SensorStateTrigger = sensor_ns.class_('SensorStateTrigger', automation.Trigger.template(cg.float_)) -SensorRawStateTrigger = sensor_ns.class_('SensorRawStateTrigger', - automation.Trigger.template(cg.float_)) -ValueRangeTrigger = sensor_ns.class_('ValueRangeTrigger', automation.Trigger.template(cg.float_), - cg.Component) -SensorPublishAction = sensor_ns.class_('SensorPublishAction', automation.Action) +SensorStateTrigger = sensor_ns.class_( + "SensorStateTrigger", automation.Trigger.template(cg.float_) +) +SensorRawStateTrigger = sensor_ns.class_( + "SensorRawStateTrigger", automation.Trigger.template(cg.float_) +) +ValueRangeTrigger = sensor_ns.class_( + "ValueRangeTrigger", automation.Trigger.template(cg.float_), cg.Component +) +SensorPublishAction = sensor_ns.class_("SensorPublishAction", automation.Action) # Filters -Filter = sensor_ns.class_('Filter') -MedianFilter = sensor_ns.class_('MedianFilter', Filter) -MinFilter = sensor_ns.class_('MinFilter', Filter) -MaxFilter = sensor_ns.class_('MaxFilter', Filter) -SlidingWindowMovingAverageFilter = sensor_ns.class_('SlidingWindowMovingAverageFilter', Filter) -ExponentialMovingAverageFilter = sensor_ns.class_('ExponentialMovingAverageFilter', Filter) -LambdaFilter = sensor_ns.class_('LambdaFilter', Filter) -OffsetFilter = sensor_ns.class_('OffsetFilter', Filter) -MultiplyFilter = sensor_ns.class_('MultiplyFilter', Filter) -FilterOutValueFilter = sensor_ns.class_('FilterOutValueFilter', Filter) -ThrottleFilter = sensor_ns.class_('ThrottleFilter', Filter) -DebounceFilter = sensor_ns.class_('DebounceFilter', Filter, cg.Component) -HeartbeatFilter = sensor_ns.class_('HeartbeatFilter', Filter, cg.Component) -DeltaFilter = sensor_ns.class_('DeltaFilter', Filter) -OrFilter = sensor_ns.class_('OrFilter', Filter) -CalibrateLinearFilter = sensor_ns.class_('CalibrateLinearFilter', Filter) -CalibratePolynomialFilter = sensor_ns.class_('CalibratePolynomialFilter', Filter) -SensorInRangeCondition = sensor_ns.class_('SensorInRangeCondition', Filter) +Filter = sensor_ns.class_("Filter") +MedianFilter = sensor_ns.class_("MedianFilter", Filter) +MinFilter = sensor_ns.class_("MinFilter", Filter) +MaxFilter = sensor_ns.class_("MaxFilter", Filter) +SlidingWindowMovingAverageFilter = sensor_ns.class_( + "SlidingWindowMovingAverageFilter", Filter +) +ExponentialMovingAverageFilter = sensor_ns.class_( + "ExponentialMovingAverageFilter", Filter +) +LambdaFilter = sensor_ns.class_("LambdaFilter", Filter) +OffsetFilter = sensor_ns.class_("OffsetFilter", Filter) +MultiplyFilter = sensor_ns.class_("MultiplyFilter", Filter) +FilterOutValueFilter = sensor_ns.class_("FilterOutValueFilter", Filter) +ThrottleFilter = sensor_ns.class_("ThrottleFilter", Filter) +DebounceFilter = sensor_ns.class_("DebounceFilter", Filter, cg.Component) +HeartbeatFilter = sensor_ns.class_("HeartbeatFilter", Filter, cg.Component) +DeltaFilter = sensor_ns.class_("DeltaFilter", Filter) +OrFilter = sensor_ns.class_("OrFilter", Filter) +CalibrateLinearFilter = sensor_ns.class_("CalibrateLinearFilter", Filter) +CalibratePolynomialFilter = sensor_ns.class_("CalibratePolynomialFilter", Filter) +SensorInRangeCondition = sensor_ns.class_("SensorInRangeCondition", Filter) unit_of_measurement = cv.string_strict accuracy_decimals = cv.int_ icon = cv.icon -device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space='_') +device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space="_") -SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({ - cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTSensorComponent), - cv.GenerateID(): cv.declare_id(Sensor), - cv.Optional(CONF_UNIT_OF_MEASUREMENT): unit_of_measurement, - cv.Optional(CONF_ICON): icon, - cv.Optional(CONF_ACCURACY_DECIMALS): accuracy_decimals, - cv.Optional(CONF_DEVICE_CLASS): device_class, - cv.Optional(CONF_FORCE_UPDATE, default=False): cv.boolean, - cv.Optional(CONF_EXPIRE_AFTER): cv.All(cv.requires_component('mqtt'), - cv.Any(None, cv.positive_time_period_milliseconds)), - cv.Optional(CONF_FILTERS): validate_filters, - cv.Optional(CONF_ON_VALUE): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SensorStateTrigger), - }), - cv.Optional(CONF_ON_RAW_VALUE): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SensorRawStateTrigger), - }), - cv.Optional(CONF_ON_VALUE_RANGE): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ValueRangeTrigger), - cv.Optional(CONF_ABOVE): cv.float_, - cv.Optional(CONF_BELOW): cv.float_, - }, cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW)), -}) +SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend( + { + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTSensorComponent), + cv.GenerateID(): cv.declare_id(Sensor), + cv.Optional(CONF_UNIT_OF_MEASUREMENT): unit_of_measurement, + cv.Optional(CONF_ICON): icon, + cv.Optional(CONF_ACCURACY_DECIMALS): accuracy_decimals, + cv.Optional(CONF_DEVICE_CLASS): device_class, + cv.Optional(CONF_FORCE_UPDATE, default=False): cv.boolean, + cv.Optional(CONF_EXPIRE_AFTER): cv.All( + cv.requires_component("mqtt"), + cv.Any(None, cv.positive_time_period_milliseconds), + ), + cv.Optional(CONF_FILTERS): validate_filters, + cv.Optional(CONF_ON_VALUE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SensorStateTrigger), + } + ), + cv.Optional(CONF_ON_RAW_VALUE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SensorRawStateTrigger), + } + ), + cv.Optional(CONF_ON_VALUE_RANGE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ValueRangeTrigger), + cv.Optional(CONF_ABOVE): cv.float_, + cv.Optional(CONF_BELOW): cv.float_, + }, + cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW), + ), + } +) def sensor_schema(unit_of_measurement_, icon_, accuracy_decimals_, device_class_): # type: (str, str, int, str) -> cv.Schema schema = SENSOR_SCHEMA if unit_of_measurement_ != UNIT_EMPTY: - schema = schema.extend({ - cv.Optional(CONF_UNIT_OF_MEASUREMENT, default=unit_of_measurement_): unit_of_measurement - }) + schema = schema.extend( + { + cv.Optional( + CONF_UNIT_OF_MEASUREMENT, default=unit_of_measurement_ + ): unit_of_measurement + } + ) if icon_ != ICON_EMPTY: schema = schema.extend({cv.Optional(CONF_ICON, default=icon_): icon}) if accuracy_decimals_ != 0: - schema = schema.extend({ - cv.Optional(CONF_ACCURACY_DECIMALS, default=accuracy_decimals_): accuracy_decimals, - }) + schema = schema.extend( + { + cv.Optional( + CONF_ACCURACY_DECIMALS, default=accuracy_decimals_ + ): accuracy_decimals, + } + ) if device_class_ != DEVICE_CLASS_EMPTY: - schema = schema.extend({ - cv.Optional(CONF_DEVICE_CLASS, default=device_class_): device_class - }) + schema = schema.extend( + {cv.Optional(CONF_DEVICE_CLASS, default=device_class_): device_class} + ) return schema -@FILTER_REGISTRY.register('offset', OffsetFilter, cv.float_) +@FILTER_REGISTRY.register("offset", OffsetFilter, cv.float_) def offset_filter_to_code(config, filter_id): yield cg.new_Pvariable(filter_id, config) -@FILTER_REGISTRY.register('multiply', MultiplyFilter, cv.float_) +@FILTER_REGISTRY.register("multiply", MultiplyFilter, cv.float_) def multiply_filter_to_code(config, filter_id): yield cg.new_Pvariable(filter_id, config) -@FILTER_REGISTRY.register('filter_out', FilterOutValueFilter, cv.float_) +@FILTER_REGISTRY.register("filter_out", FilterOutValueFilter, cv.float_) def filter_out_filter_to_code(config, filter_id): yield cg.new_Pvariable(filter_id, config) -MEDIAN_SCHEMA = cv.All(cv.Schema({ - cv.Optional(CONF_WINDOW_SIZE, default=5): cv.positive_not_null_int, - cv.Optional(CONF_SEND_EVERY, default=5): cv.positive_not_null_int, - cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.positive_not_null_int, -}), validate_send_first_at) +MEDIAN_SCHEMA = cv.All( + cv.Schema( + { + cv.Optional(CONF_WINDOW_SIZE, default=5): cv.positive_not_null_int, + cv.Optional(CONF_SEND_EVERY, default=5): cv.positive_not_null_int, + cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.positive_not_null_int, + } + ), + validate_send_first_at, +) -@FILTER_REGISTRY.register('median', MedianFilter, MEDIAN_SCHEMA) +@FILTER_REGISTRY.register("median", MedianFilter, MEDIAN_SCHEMA) def median_filter_to_code(config, filter_id): - yield cg.new_Pvariable(filter_id, config[CONF_WINDOW_SIZE], config[CONF_SEND_EVERY], - config[CONF_SEND_FIRST_AT]) + yield cg.new_Pvariable( + filter_id, + config[CONF_WINDOW_SIZE], + config[CONF_SEND_EVERY], + config[CONF_SEND_FIRST_AT], + ) -MIN_SCHEMA = cv.All(cv.Schema({ - cv.Optional(CONF_WINDOW_SIZE, default=5): cv.positive_not_null_int, - cv.Optional(CONF_SEND_EVERY, default=5): cv.positive_not_null_int, - cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.positive_not_null_int, -}), validate_send_first_at) +MIN_SCHEMA = cv.All( + cv.Schema( + { + cv.Optional(CONF_WINDOW_SIZE, default=5): cv.positive_not_null_int, + cv.Optional(CONF_SEND_EVERY, default=5): cv.positive_not_null_int, + cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.positive_not_null_int, + } + ), + validate_send_first_at, +) -@FILTER_REGISTRY.register('min', MinFilter, MIN_SCHEMA) +@FILTER_REGISTRY.register("min", MinFilter, MIN_SCHEMA) def min_filter_to_code(config, filter_id): - yield cg.new_Pvariable(filter_id, config[CONF_WINDOW_SIZE], config[CONF_SEND_EVERY], - config[CONF_SEND_FIRST_AT]) + yield cg.new_Pvariable( + filter_id, + config[CONF_WINDOW_SIZE], + config[CONF_SEND_EVERY], + config[CONF_SEND_FIRST_AT], + ) -MAX_SCHEMA = cv.All(cv.Schema({ - cv.Optional(CONF_WINDOW_SIZE, default=5): cv.positive_not_null_int, - cv.Optional(CONF_SEND_EVERY, default=5): cv.positive_not_null_int, - cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.positive_not_null_int, -}), validate_send_first_at) +MAX_SCHEMA = cv.All( + cv.Schema( + { + cv.Optional(CONF_WINDOW_SIZE, default=5): cv.positive_not_null_int, + cv.Optional(CONF_SEND_EVERY, default=5): cv.positive_not_null_int, + cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.positive_not_null_int, + } + ), + validate_send_first_at, +) -@FILTER_REGISTRY.register('max', MaxFilter, MAX_SCHEMA) +@FILTER_REGISTRY.register("max", MaxFilter, MAX_SCHEMA) def max_filter_to_code(config, filter_id): - yield cg.new_Pvariable(filter_id, config[CONF_WINDOW_SIZE], config[CONF_SEND_EVERY], - config[CONF_SEND_FIRST_AT]) + yield cg.new_Pvariable( + filter_id, + config[CONF_WINDOW_SIZE], + config[CONF_SEND_EVERY], + config[CONF_SEND_FIRST_AT], + ) -SLIDING_AVERAGE_SCHEMA = cv.All(cv.Schema({ - cv.Optional(CONF_WINDOW_SIZE, default=15): cv.positive_not_null_int, - cv.Optional(CONF_SEND_EVERY, default=15): cv.positive_not_null_int, - cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.positive_not_null_int, -}), validate_send_first_at) +SLIDING_AVERAGE_SCHEMA = cv.All( + cv.Schema( + { + cv.Optional(CONF_WINDOW_SIZE, default=15): cv.positive_not_null_int, + cv.Optional(CONF_SEND_EVERY, default=15): cv.positive_not_null_int, + cv.Optional(CONF_SEND_FIRST_AT, default=1): cv.positive_not_null_int, + } + ), + validate_send_first_at, +) -@FILTER_REGISTRY.register('sliding_window_moving_average', SlidingWindowMovingAverageFilter, - SLIDING_AVERAGE_SCHEMA) +@FILTER_REGISTRY.register( + "sliding_window_moving_average", + SlidingWindowMovingAverageFilter, + SLIDING_AVERAGE_SCHEMA, +) def sliding_window_moving_average_filter_to_code(config, filter_id): - yield cg.new_Pvariable(filter_id, config[CONF_WINDOW_SIZE], config[CONF_SEND_EVERY], - config[CONF_SEND_FIRST_AT]) + yield cg.new_Pvariable( + filter_id, + config[CONF_WINDOW_SIZE], + config[CONF_SEND_EVERY], + config[CONF_SEND_FIRST_AT], + ) -@FILTER_REGISTRY.register('exponential_moving_average', ExponentialMovingAverageFilter, cv.Schema({ - cv.Optional(CONF_ALPHA, default=0.1): cv.positive_float, - cv.Optional(CONF_SEND_EVERY, default=15): cv.positive_not_null_int, -})) +@FILTER_REGISTRY.register( + "exponential_moving_average", + ExponentialMovingAverageFilter, + cv.Schema( + { + cv.Optional(CONF_ALPHA, default=0.1): cv.positive_float, + cv.Optional(CONF_SEND_EVERY, default=15): cv.positive_not_null_int, + } + ), +) def exponential_moving_average_filter_to_code(config, filter_id): yield cg.new_Pvariable(filter_id, config[CONF_ALPHA], config[CONF_SEND_EVERY]) -@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, [(float, 'x')], - return_type=cg.optional.template(float)) + lambda_ = yield cg.process_lambda( + config, [(float, "x")], return_type=cg.optional.template(float) + ) yield cg.new_Pvariable(filter_id, lambda_) -@FILTER_REGISTRY.register('delta', DeltaFilter, cv.float_) +@FILTER_REGISTRY.register("delta", DeltaFilter, cv.float_) def delta_filter_to_code(config, filter_id): yield cg.new_Pvariable(filter_id, config) -@FILTER_REGISTRY.register('or', OrFilter, validate_filters) +@FILTER_REGISTRY.register("or", OrFilter, validate_filters) def or_filter_to_code(config, filter_id): filters = yield build_filters(config) yield cg.new_Pvariable(filter_id, filters) -@FILTER_REGISTRY.register('throttle', ThrottleFilter, cv.positive_time_period_milliseconds) +@FILTER_REGISTRY.register( + "throttle", ThrottleFilter, cv.positive_time_period_milliseconds +) def throttle_filter_to_code(config, filter_id): yield cg.new_Pvariable(filter_id, config) -@FILTER_REGISTRY.register('heartbeat', HeartbeatFilter, cv.positive_time_period_milliseconds) +@FILTER_REGISTRY.register( + "heartbeat", HeartbeatFilter, cv.positive_time_period_milliseconds +) def heartbeat_filter_to_code(config, filter_id): var = cg.new_Pvariable(filter_id, config) yield cg.register_component(var, {}) yield var -@FILTER_REGISTRY.register('debounce', DebounceFilter, cv.positive_time_period_milliseconds) +@FILTER_REGISTRY.register( + "debounce", DebounceFilter, cv.positive_time_period_milliseconds +) def debounce_filter_to_code(config, filter_id): var = cg.new_Pvariable(filter_id, config) yield cg.register_component(var, {}) @@ -254,13 +375,20 @@ def debounce_filter_to_code(config, filter_id): def validate_not_all_from_same(config): if all(conf[CONF_FROM] == config[0][CONF_FROM] for conf in config): - raise cv.Invalid("The 'from' values of the calibrate_linear filter cannot all point " - "to the same value! Please add more values to the filter.") + raise cv.Invalid( + "The 'from' values of the calibrate_linear filter cannot all point " + "to the same value! Please add more values to the filter." + ) return config -@FILTER_REGISTRY.register('calibrate_linear', CalibrateLinearFilter, cv.All( - cv.ensure_list(validate_datapoint), cv.Length(min=2), validate_not_all_from_same)) +@FILTER_REGISTRY.register( + "calibrate_linear", + CalibrateLinearFilter, + cv.All( + cv.ensure_list(validate_datapoint), cv.Length(min=2), validate_not_all_from_same + ), +) def calibrate_linear_filter_to_code(config, filter_id): x = [conf[CONF_FROM] for conf in config] y = [conf[CONF_TO] for conf in config] @@ -268,26 +396,40 @@ def calibrate_linear_filter_to_code(config, filter_id): yield cg.new_Pvariable(filter_id, k, b) -CONF_DATAPOINTS = 'datapoints' -CONF_DEGREE = 'degree' +CONF_DATAPOINTS = "datapoints" +CONF_DEGREE = "degree" def validate_calibrate_polynomial(config): if config[CONF_DEGREE] >= len(config[CONF_DATAPOINTS]): - raise cv.Invalid("Degree is too high! Maximum possible degree with given datapoints is " - "{}".format(len(config[CONF_DATAPOINTS]) - 1), [CONF_DEGREE]) + raise cv.Invalid( + "Degree is too high! Maximum possible degree with given datapoints is " + "{}".format(len(config[CONF_DATAPOINTS]) - 1), + [CONF_DEGREE], + ) return config -@FILTER_REGISTRY.register('calibrate_polynomial', CalibratePolynomialFilter, cv.All(cv.Schema({ - cv.Required(CONF_DATAPOINTS): cv.All(cv.ensure_list(validate_datapoint), cv.Length(min=1)), - cv.Required(CONF_DEGREE): cv.positive_int, -}), validate_calibrate_polynomial)) +@FILTER_REGISTRY.register( + "calibrate_polynomial", + CalibratePolynomialFilter, + cv.All( + cv.Schema( + { + cv.Required(CONF_DATAPOINTS): cv.All( + cv.ensure_list(validate_datapoint), cv.Length(min=1) + ), + cv.Required(CONF_DEGREE): cv.positive_int, + } + ), + validate_calibrate_polynomial, + ), +) def calibrate_polynomial_filter_to_code(config, filter_id): x = [conf[CONF_FROM] for conf in config[CONF_DATAPOINTS]] y = [conf[CONF_TO] for conf in config[CONF_DATAPOINTS]] degree = config[CONF_DEGREE] - a = [[1] + [x_**(i+1) for i in range(degree)] for x_ in x] + a = [[1] + [x_ ** (i + 1) for i in range(degree)] for x_ in x] # Column vector b = [[v] for v in y] res = [v[0] for v in _lstsq(a, b)] @@ -319,20 +461,20 @@ def setup_sensor_core_(var, config): for conf in config.get(CONF_ON_VALUE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - yield automation.build_automation(trigger, [(float, 'x')], conf) + yield automation.build_automation(trigger, [(float, "x")], conf) for conf in config.get(CONF_ON_RAW_VALUE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - yield automation.build_automation(trigger, [(float, 'x')], conf) + yield automation.build_automation(trigger, [(float, "x")], conf) for conf in config.get(CONF_ON_VALUE_RANGE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) yield cg.register_component(trigger, conf) if CONF_ABOVE in conf: - template_ = yield cg.templatable(conf[CONF_ABOVE], [(float, 'x')], float) + template_ = yield cg.templatable(conf[CONF_ABOVE], [(float, "x")], float) cg.add(trigger.set_min(template_)) if CONF_BELOW in conf: - template_ = yield cg.templatable(conf[CONF_BELOW], [(float, 'x')], float) + template_ = yield cg.templatable(conf[CONF_BELOW], [(float, "x")], float) cg.add(trigger.set_max(template_)) - yield automation.build_automation(trigger, [(float, 'x')], conf) + yield automation.build_automation(trigger, [(float, "x")], conf) if CONF_MQTT_ID in config: mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var) @@ -360,15 +502,19 @@ def new_sensor(config): yield var -SENSOR_IN_RANGE_CONDITION_SCHEMA = cv.All({ - cv.Required(CONF_ID): cv.use_id(Sensor), - cv.Optional(CONF_ABOVE): cv.float_, - cv.Optional(CONF_BELOW): cv.float_, -}, cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW)) +SENSOR_IN_RANGE_CONDITION_SCHEMA = cv.All( + { + cv.Required(CONF_ID): cv.use_id(Sensor), + cv.Optional(CONF_ABOVE): cv.float_, + cv.Optional(CONF_BELOW): cv.float_, + }, + cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW), +) -@automation.register_condition('sensor.in_range', SensorInRangeCondition, - SENSOR_IN_RANGE_CONDITION_SCHEMA) +@automation.register_condition( + "sensor.in_range", SensorInRangeCondition, SENSOR_IN_RANGE_CONDITION_SCHEMA +) def sensor_in_range_to_code(config, condition_id, template_arg, args): paren = yield cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(condition_id, template_arg, paren) @@ -420,7 +566,7 @@ def _mat_identity(n): def _mat_dot(a, b): b_t = _mat_transpose(b) - return [[sum(x*y for x, y in zip(row_a, col_b)) for col_b in b_t] for row_a in a] + return [[sum(x * y for x, y in zip(row_a, col_b)) for col_b in b_t] for row_a in a] def _mat_inverse(m): @@ -431,7 +577,7 @@ def _mat_inverse(m): for diag in range(n): # If diag element is 0, swap rows if m[diag][diag] == 0: - for i in range(diag+1, n): + for i in range(diag + 1, n): if m[i][diag] != 0: break else: @@ -468,5 +614,5 @@ def _lstsq(a, b): @coroutine_with_priority(40.0) def to_code(config): - cg.add_define('USE_SENSOR') + cg.add_define("USE_SENSOR") cg.add_global(sensor_ns.using) diff --git a/esphome/components/servo/__init__.py b/esphome/components/servo/__init__.py index 76690dbcf..489c29525 100644 --- a/esphome/components/servo/__init__.py +++ b/esphome/components/servo/__init__.py @@ -3,26 +3,40 @@ import esphome.config_validation as cv from esphome import automation from esphome.automation import maybe_simple_id from esphome.components.output import FloatOutput -from esphome.const import CONF_ID, CONF_IDLE_LEVEL, CONF_MAX_LEVEL, CONF_MIN_LEVEL, CONF_OUTPUT, \ - CONF_LEVEL, CONF_RESTORE, CONF_TRANSITION_LENGTH +from esphome.const import ( + CONF_ID, + CONF_IDLE_LEVEL, + CONF_MAX_LEVEL, + CONF_MIN_LEVEL, + CONF_OUTPUT, + CONF_LEVEL, + CONF_RESTORE, + CONF_TRANSITION_LENGTH, +) -servo_ns = cg.esphome_ns.namespace('servo') -Servo = servo_ns.class_('Servo', cg.Component) -ServoWriteAction = servo_ns.class_('ServoWriteAction', automation.Action) -ServoDetachAction = servo_ns.class_('ServoDetachAction', automation.Action) +servo_ns = cg.esphome_ns.namespace("servo") +Servo = servo_ns.class_("Servo", cg.Component) +ServoWriteAction = servo_ns.class_("ServoWriteAction", automation.Action) +ServoDetachAction = servo_ns.class_("ServoDetachAction", automation.Action) -CONF_AUTO_DETACH_TIME = 'auto_detach_time' +CONF_AUTO_DETACH_TIME = "auto_detach_time" MULTI_CONF = True -CONFIG_SCHEMA = cv.Schema({ - cv.Required(CONF_ID): cv.declare_id(Servo), - cv.Required(CONF_OUTPUT): cv.use_id(FloatOutput), - cv.Optional(CONF_MIN_LEVEL, default='3%'): cv.percentage, - cv.Optional(CONF_IDLE_LEVEL, default='7.5%'): cv.percentage, - cv.Optional(CONF_MAX_LEVEL, default='12%'): cv.percentage, - cv.Optional(CONF_RESTORE, default=False): cv.boolean, - cv.Optional(CONF_AUTO_DETACH_TIME, default='0s'): cv.positive_time_period_milliseconds, - cv.Optional(CONF_TRANSITION_LENGTH, default='0s'): cv.positive_time_period_milliseconds -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(Servo), + cv.Required(CONF_OUTPUT): cv.use_id(FloatOutput), + cv.Optional(CONF_MIN_LEVEL, default="3%"): cv.percentage, + cv.Optional(CONF_IDLE_LEVEL, default="7.5%"): cv.percentage, + cv.Optional(CONF_MAX_LEVEL, default="12%"): cv.percentage, + cv.Optional(CONF_RESTORE, default=False): cv.boolean, + cv.Optional( + CONF_AUTO_DETACH_TIME, default="0s" + ): cv.positive_time_period_milliseconds, + cv.Optional( + CONF_TRANSITION_LENGTH, default="0s" + ): cv.positive_time_period_milliseconds, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): @@ -39,10 +53,16 @@ def to_code(config): cg.add(var.set_transition_length(config[CONF_TRANSITION_LENGTH])) -@automation.register_action('servo.write', ServoWriteAction, cv.Schema({ - cv.Required(CONF_ID): cv.use_id(Servo), - cv.Required(CONF_LEVEL): cv.templatable(cv.possibly_negative_percentage), -})) +@automation.register_action( + "servo.write", + ServoWriteAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(Servo), + cv.Required(CONF_LEVEL): cv.templatable(cv.possibly_negative_percentage), + } + ), +) def servo_write_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) @@ -51,9 +71,15 @@ def servo_write_to_code(config, action_id, template_arg, args): yield var -@automation.register_action('servo.detach', ServoDetachAction, maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(Servo), -})) +@automation.register_action( + "servo.detach", + ServoDetachAction, + maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(Servo), + } + ), +) def servo_detach_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) diff --git a/esphome/components/sgp30/sensor.py b/esphome/components/sgp30/sensor.py index a3ce1013e..31b40840e 100644 --- a/esphome/components/sgp30/sensor.py +++ b/esphome/components/sgp30/sensor.py @@ -1,38 +1,57 @@ 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, ICON_MOLECULE_CO2, CONF_TVOC +from esphome.const import ( + CONF_ID, + DEVICE_CLASS_EMPTY, + ICON_RADIATOR, + UNIT_PARTS_PER_MILLION, + UNIT_PARTS_PER_BILLION, + ICON_MOLECULE_CO2, + CONF_TVOC, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -sgp30_ns = cg.esphome_ns.namespace('sgp30') -SGP30Component = sgp30_ns.class_('SGP30Component', cg.PollingComponent, i2c.I2CDevice) +sgp30_ns = cg.esphome_ns.namespace("sgp30") +SGP30Component = sgp30_ns.class_("SGP30Component", cg.PollingComponent, i2c.I2CDevice) -CONF_ECO2 = 'eco2' -CONF_BASELINE = 'baseline' -CONF_ECO2_BASELINE = 'eco2_baseline' -CONF_TVOC_BASELINE = 'tvoc_baseline' -CONF_UPTIME = 'uptime' -CONF_COMPENSATION = 'compensation' -CONF_HUMIDITY_SOURCE = 'humidity_source' -CONF_TEMPERATURE_SOURCE = 'temperature_source' +CONF_ECO2 = "eco2" +CONF_BASELINE = "baseline" +CONF_ECO2_BASELINE = "eco2_baseline" +CONF_TVOC_BASELINE = "tvoc_baseline" +CONF_UPTIME = "uptime" +CONF_COMPENSATION = "compensation" +CONF_HUMIDITY_SOURCE = "humidity_source" +CONF_TEMPERATURE_SOURCE = "temperature_source" -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(SGP30Component), - 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.Schema({ - cv.Required(CONF_ECO2_BASELINE): cv.hex_uint16_t, - cv.Required(CONF_TVOC_BASELINE): cv.hex_uint16_t, - }), - cv.Optional(CONF_COMPENSATION): cv.Schema({ - cv.Required(CONF_HUMIDITY_SOURCE): cv.use_id(sensor.Sensor), - cv.Required(CONF_TEMPERATURE_SOURCE): cv.use_id(sensor.Sensor) - }), -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x58)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(SGP30Component), + 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.Schema( + { + cv.Required(CONF_ECO2_BASELINE): cv.hex_uint16_t, + cv.Required(CONF_TVOC_BASELINE): cv.hex_uint16_t, + } + ), + cv.Optional(CONF_COMPENSATION): cv.Schema( + { + cv.Required(CONF_HUMIDITY_SOURCE): cv.use_id(sensor.Sensor), + cv.Required(CONF_TEMPERATURE_SOURCE): cv.use_id(sensor.Sensor), + } + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x58)) +) def to_code(config): diff --git a/esphome/components/sht3xd/sensor.py b/esphome/components/sht3xd/sensor.py index 45ede0b10..0b30d6780 100644 --- a/esphome/components/sht3xd/sensor.py +++ b/esphome/components/sht3xd/sensor.py @@ -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, 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"] -sht3xd_ns = cg.esphome_ns.namespace('sht3xd') -SHT3XDComponent = sht3xd_ns.class_('SHT3XDComponent', cg.PollingComponent, i2c.I2CDevice) +sht3xd_ns = cg.esphome_ns.namespace("sht3xd") +SHT3XDComponent = sht3xd_ns.class_( + "SHT3XDComponent", cg.PollingComponent, i2c.I2CDevice +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(SHT3XDComponent), - cv.Required(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, - DEVICE_CLASS_TEMPERATURE), - cv.Required(CONF_HUMIDITY): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 1, - DEVICE_CLASS_HUMIDITY), -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x44)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(SHT3XDComponent), + cv.Required(CONF_TEMPERATURE): sensor.sensor_schema( + UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE + ), + cv.Required(CONF_HUMIDITY): sensor.sensor_schema( + UNIT_PERCENT, ICON_EMPTY, 1, DEVICE_CLASS_HUMIDITY + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x44)) +) def to_code(config): diff --git a/esphome/components/shtcx/sensor.py b/esphome/components/shtcx/sensor.py index 788dd0021..4b1c6c7af 100644 --- a/esphome/components/shtcx/sensor.py +++ b/esphome/components/shtcx/sensor.py @@ -1,23 +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, 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"] -shtcx_ns = cg.esphome_ns.namespace('shtcx') -SHTCXComponent = shtcx_ns.class_('SHTCXComponent', cg.PollingComponent, i2c.I2CDevice) +shtcx_ns = cg.esphome_ns.namespace("shtcx") +SHTCXComponent = shtcx_ns.class_("SHTCXComponent", cg.PollingComponent, i2c.I2CDevice) -SHTCXType = shtcx_ns.enum('SHTCXType') +SHTCXType = shtcx_ns.enum("SHTCXType") -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(SHTCXComponent), - cv.Required(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, - DEVICE_CLASS_TEMPERATURE), - cv.Required(CONF_HUMIDITY): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 1, - DEVICE_CLASS_HUMIDITY), -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x70)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(SHTCXComponent), + cv.Required(CONF_TEMPERATURE): sensor.sensor_schema( + UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE + ), + cv.Required(CONF_HUMIDITY): sensor.sensor_schema( + UNIT_PERCENT, ICON_EMPTY, 1, DEVICE_CLASS_HUMIDITY + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x70)) +) def to_code(config): diff --git a/esphome/components/shutdown/__init__.py b/esphome/components/shutdown/__init__.py index 63db7aee2..f70ffa952 100644 --- a/esphome/components/shutdown/__init__.py +++ b/esphome/components/shutdown/__init__.py @@ -1 +1 @@ -CODEOWNERS = ['@esphome/core'] +CODEOWNERS = ["@esphome/core"] diff --git a/esphome/components/shutdown/switch.py b/esphome/components/shutdown/switch.py index 9826f9bbe..e35029afd 100644 --- a/esphome/components/shutdown/switch.py +++ b/esphome/components/shutdown/switch.py @@ -3,16 +3,18 @@ import esphome.config_validation as cv from esphome.components import switch from esphome.const import CONF_ID, CONF_INVERTED, CONF_ICON, ICON_POWER -shutdown_ns = cg.esphome_ns.namespace('shutdown') -ShutdownSwitch = shutdown_ns.class_('ShutdownSwitch', switch.Switch, cg.Component) +shutdown_ns = cg.esphome_ns.namespace("shutdown") +ShutdownSwitch = shutdown_ns.class_("ShutdownSwitch", switch.Switch, cg.Component) -CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(ShutdownSwitch), - - cv.Optional(CONF_INVERTED): cv.invalid("Shutdown switches do not support inverted mode!"), - - cv.Optional(CONF_ICON, default=ICON_POWER): switch.icon -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(ShutdownSwitch), + cv.Optional(CONF_INVERTED): cv.invalid( + "Shutdown switches do not support inverted mode!" + ), + cv.Optional(CONF_ICON, default=ICON_POWER): switch.icon, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/sim800l/__init__.py b/esphome/components/sim800l/__init__.py index 0c4215d8e..3b06ca6d8 100644 --- a/esphome/components/sim800l/__init__.py +++ b/esphome/components/sim800l/__init__.py @@ -4,31 +4,42 @@ from esphome import automation from esphome.const import CONF_ID, CONF_TRIGGER_ID from esphome.components import uart -DEPENDENCIES = ['uart'] -CODEOWNERS = ['@glmnet'] +DEPENDENCIES = ["uart"] +CODEOWNERS = ["@glmnet"] MULTI_CONF = True -sim800l_ns = cg.esphome_ns.namespace('sim800l') -Sim800LComponent = sim800l_ns.class_('Sim800LComponent', cg.Component) +sim800l_ns = cg.esphome_ns.namespace("sim800l") +Sim800LComponent = sim800l_ns.class_("Sim800LComponent", cg.Component) -Sim800LReceivedMessageTrigger = sim800l_ns.class_('Sim800LReceivedMessageTrigger', - automation.Trigger.template(cg.std_string, - cg.std_string)) +Sim800LReceivedMessageTrigger = sim800l_ns.class_( + "Sim800LReceivedMessageTrigger", + automation.Trigger.template(cg.std_string, cg.std_string), +) # Actions -Sim800LSendSmsAction = sim800l_ns.class_('Sim800LSendSmsAction', automation.Action) -Sim800LDialAction = sim800l_ns.class_('Sim800LDialAction', automation.Action) +Sim800LSendSmsAction = sim800l_ns.class_("Sim800LSendSmsAction", automation.Action) +Sim800LDialAction = sim800l_ns.class_("Sim800LDialAction", automation.Action) -CONF_ON_SMS_RECEIVED = 'on_sms_received' -CONF_RECIPIENT = 'recipient' -CONF_MESSAGE = 'message' +CONF_ON_SMS_RECEIVED = "on_sms_received" +CONF_RECIPIENT = "recipient" +CONF_MESSAGE = "message" -CONFIG_SCHEMA = cv.All(cv.Schema({ - cv.GenerateID(): cv.declare_id(Sim800LComponent), - cv.Optional(CONF_ON_SMS_RECEIVED): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(Sim800LReceivedMessageTrigger), - }), -}).extend(cv.polling_component_schema('5s')).extend(uart.UART_DEVICE_SCHEMA)) +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(Sim800LComponent), + cv.Optional(CONF_ON_SMS_RECEIVED): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id( + Sim800LReceivedMessageTrigger + ), + } + ), + } + ) + .extend(cv.polling_component_schema("5s")) + .extend(uart.UART_DEVICE_SCHEMA) +) def to_code(config): @@ -38,18 +49,23 @@ def to_code(config): for conf in config.get(CONF_ON_SMS_RECEIVED, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - yield automation.build_automation(trigger, [(cg.std_string, 'message'), - (cg.std_string, 'sender')], conf) + yield automation.build_automation( + trigger, [(cg.std_string, "message"), (cg.std_string, "sender")], conf + ) -SIM800L_SEND_SMS_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.use_id(Sim800LComponent), - cv.Required(CONF_RECIPIENT): cv.templatable(cv.string_strict), - cv.Required(CONF_MESSAGE): cv.templatable(cv.string), -}) +SIM800L_SEND_SMS_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.use_id(Sim800LComponent), + cv.Required(CONF_RECIPIENT): cv.templatable(cv.string_strict), + cv.Required(CONF_MESSAGE): cv.templatable(cv.string), + } +) -@automation.register_action('sim800l.send_sms', Sim800LSendSmsAction, SIM800L_SEND_SMS_SCHEMA) +@automation.register_action( + "sim800l.send_sms", Sim800LSendSmsAction, SIM800L_SEND_SMS_SCHEMA +) def sim800l_send_sms_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) @@ -60,13 +76,15 @@ def sim800l_send_sms_to_code(config, action_id, template_arg, args): yield var -SIM800L_DIAL_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.use_id(Sim800LComponent), - cv.Required(CONF_RECIPIENT): cv.templatable(cv.string_strict), -}) +SIM800L_DIAL_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.use_id(Sim800LComponent), + cv.Required(CONF_RECIPIENT): cv.templatable(cv.string_strict), + } +) -@automation.register_action('sim800l.dial', Sim800LDialAction, SIM800L_DIAL_SCHEMA) +@automation.register_action("sim800l.dial", Sim800LDialAction, SIM800L_DIAL_SCHEMA) def sim800l_dial_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) diff --git a/esphome/components/sm16716/__init__.py b/esphome/components/sm16716/__init__.py index 4e342588f..8030f78f4 100644 --- a/esphome/components/sm16716/__init__.py +++ b/esphome/components/sm16716/__init__.py @@ -1,21 +1,28 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins -from esphome.const import (CONF_CLOCK_PIN, CONF_DATA_PIN, CONF_ID, - CONF_NUM_CHANNELS, CONF_NUM_CHIPS) +from esphome.const import ( + CONF_CLOCK_PIN, + CONF_DATA_PIN, + CONF_ID, + CONF_NUM_CHANNELS, + CONF_NUM_CHIPS, +) -AUTO_LOAD = ['output'] -sm16716_ns = cg.esphome_ns.namespace('sm16716') -SM16716 = sm16716_ns.class_('SM16716', cg.Component) +AUTO_LOAD = ["output"] +sm16716_ns = cg.esphome_ns.namespace("sm16716") +SM16716 = sm16716_ns.class_("SM16716", cg.Component) MULTI_CONF = True -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(SM16716), - cv.Required(CONF_DATA_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_NUM_CHANNELS, default=3): cv.int_range(min=3, max=255), - cv.Optional(CONF_NUM_CHIPS, default=1): cv.int_range(min=1, max=85), -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(SM16716), + cv.Required(CONF_DATA_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_NUM_CHANNELS, default=3): cv.int_range(min=3, max=255), + cv.Optional(CONF_NUM_CHIPS, default=1): cv.int_range(min=1, max=85), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/sm16716/output.py b/esphome/components/sm16716/output.py index 93c9ed4ce..033bd86e9 100644 --- a/esphome/components/sm16716/output.py +++ b/esphome/components/sm16716/output.py @@ -4,16 +4,18 @@ from esphome.components import output from esphome.const import CONF_CHANNEL, CONF_ID from . import SM16716 -DEPENDENCIES = ['sm16716'] +DEPENDENCIES = ["sm16716"] -Channel = SM16716.class_('Channel', output.FloatOutput) +Channel = SM16716.class_("Channel", output.FloatOutput) -CONF_SM16716_ID = 'sm16716_id' -CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend({ - cv.GenerateID(CONF_SM16716_ID): cv.use_id(SM16716), - cv.Required(CONF_ID): cv.declare_id(Channel), - cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=65535), -}).extend(cv.COMPONENT_SCHEMA) +CONF_SM16716_ID = "sm16716_id" +CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( + { + cv.GenerateID(CONF_SM16716_ID): cv.use_id(SM16716), + cv.Required(CONF_ID): cv.declare_id(Channel), + cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=65535), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/sm300d2/sensor.py b/esphome/components/sm300d2/sensor.py index 2191143ec..b1df1fb1b 100644 --- a/esphome/components/sm300d2/sensor.py +++ b/esphome/components/sm300d2/sensor.py @@ -1,36 +1,67 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, uart -from esphome.const import CONF_ID, CONF_CO2, CONF_FORMALDEHYDE, CONF_TVOC, CONF_PM_2_5, \ - CONF_PM_10_0, CONF_TEMPERATURE, CONF_HUMIDITY, DEVICE_CLASS_EMPTY, DEVICE_CLASS_TEMPERATURE, \ - DEVICE_CLASS_HUMIDITY, UNIT_PARTS_PER_MILLION, UNIT_MICROGRAMS_PER_CUBIC_METER, UNIT_CELSIUS, \ - UNIT_PERCENT, ICON_EMPTY, ICON_MOLECULE_CO2, ICON_FLASK, ICON_CHEMICAL_WEAPON, ICON_GRAIN +from esphome.const import ( + CONF_ID, + CONF_CO2, + CONF_FORMALDEHYDE, + CONF_TVOC, + CONF_PM_2_5, + CONF_PM_10_0, + CONF_TEMPERATURE, + CONF_HUMIDITY, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_HUMIDITY, + UNIT_PARTS_PER_MILLION, + UNIT_MICROGRAMS_PER_CUBIC_METER, + UNIT_CELSIUS, + UNIT_PERCENT, + ICON_EMPTY, + ICON_MOLECULE_CO2, + ICON_FLASK, + ICON_CHEMICAL_WEAPON, + ICON_GRAIN, +) -DEPENDENCIES = ['uart'] +DEPENDENCIES = ["uart"] -sm300d2_ns = cg.esphome_ns.namespace('sm300d2') -SM300D2Sensor = sm300d2_ns.class_('SM300D2Sensor', cg.PollingComponent, uart.UARTDevice) +sm300d2_ns = cg.esphome_ns.namespace("sm300d2") +SM300D2Sensor = sm300d2_ns.class_("SM300D2Sensor", cg.PollingComponent, uart.UARTDevice) -CONFIG_SCHEMA = cv.All(cv.Schema({ - cv.GenerateID(): cv.declare_id(SM300D2Sensor), - - cv.Optional(CONF_CO2): - sensor.sensor_schema(UNIT_PARTS_PER_MILLION, ICON_MOLECULE_CO2, 0, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_FORMALDEHYDE): - sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_FLASK, 0, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_TVOC): - sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_CHEMICAL_WEAPON, 0, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_PM_2_5): - sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_GRAIN, 0, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_PM_10_0): - sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_GRAIN, 0, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_TEMPERATURE): - sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 0, DEVICE_CLASS_TEMPERATURE), - cv.Optional(CONF_HUMIDITY): - sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 0, DEVICE_CLASS_HUMIDITY), - -}).extend(cv.polling_component_schema('60s')).extend(uart.UART_DEVICE_SCHEMA)) +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(SM300D2Sensor), + cv.Optional(CONF_CO2): sensor.sensor_schema( + UNIT_PARTS_PER_MILLION, ICON_MOLECULE_CO2, 0, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_FORMALDEHYDE): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_FLASK, 0, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_TVOC): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, + 0, + DEVICE_CLASS_EMPTY, + ), + cv.Optional(CONF_PM_2_5): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_GRAIN, 0, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_PM_10_0): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, ICON_GRAIN, 0, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema( + UNIT_CELSIUS, ICON_EMPTY, 0, DEVICE_CLASS_TEMPERATURE + ), + cv.Optional(CONF_HUMIDITY): sensor.sensor_schema( + UNIT_PERCENT, ICON_EMPTY, 0, DEVICE_CLASS_HUMIDITY + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(uart.UART_DEVICE_SCHEMA) +) def to_code(config): diff --git a/esphome/components/sn74hc595/__init__.py b/esphome/components/sn74hc595/__init__.py index 369fc41fa..152ac0210 100644 --- a/esphome/components/sn74hc595/__init__.py +++ b/esphome/components/sn74hc595/__init__.py @@ -1,28 +1,36 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins -from esphome.const import CONF_ID, CONF_NUMBER, CONF_INVERTED, CONF_DATA_PIN, CONF_CLOCK_PIN +from esphome.const import ( + CONF_ID, + CONF_NUMBER, + CONF_INVERTED, + CONF_DATA_PIN, + CONF_CLOCK_PIN, +) DEPENDENCIES = [] MULTI_CONF = True -sn74hc595_ns = cg.esphome_ns.namespace('sn74hc595') +sn74hc595_ns = cg.esphome_ns.namespace("sn74hc595") -SN74HC595Component = sn74hc595_ns.class_('SN74HC595Component', cg.Component) -SN74HC595GPIOPin = sn74hc595_ns.class_('SN74HC595GPIOPin', cg.GPIOPin) +SN74HC595Component = sn74hc595_ns.class_("SN74HC595Component", cg.Component) +SN74HC595GPIOPin = sn74hc595_ns.class_("SN74HC595GPIOPin", cg.GPIOPin) -CONF_SN74HC595 = 'sn74hc595' -CONF_LATCH_PIN = 'latch_pin' -CONF_OE_PIN = 'oe_pin' -CONF_SR_COUNT = 'sr_count' -CONFIG_SCHEMA = cv.Schema({ - cv.Required(CONF_ID): cv.declare_id(SN74HC595Component), - cv.Required(CONF_DATA_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_LATCH_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_OE_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_SR_COUNT, default=1): cv.int_range(1, 4) -}).extend(cv.COMPONENT_SCHEMA) +CONF_SN74HC595 = "sn74hc595" +CONF_LATCH_PIN = "latch_pin" +CONF_OE_PIN = "oe_pin" +CONF_SR_COUNT = "sr_count" +CONFIG_SCHEMA = cv.Schema( + { + cv.Required(CONF_ID): cv.declare_id(SN74HC595Component), + cv.Required(CONF_DATA_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_CLOCK_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_LATCH_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_OE_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_SR_COUNT, default=1): cv.int_range(1, 4), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): @@ -40,16 +48,19 @@ def to_code(config): cg.add(var.set_sr_count(config[CONF_SR_COUNT])) -SN74HC595_OUTPUT_PIN_SCHEMA = cv.Schema({ - cv.Required(CONF_SN74HC595): cv.use_id(SN74HC595Component), - cv.Required(CONF_NUMBER): cv.int_, - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) +SN74HC595_OUTPUT_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_SN74HC595): cv.use_id(SN74HC595Component), + cv.Required(CONF_NUMBER): cv.int_, + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) SN74HC595_INPUT_PIN_SCHEMA = cv.Schema({}) -@pins.PIN_SCHEMA_REGISTRY.register(CONF_SN74HC595, - (SN74HC595_OUTPUT_PIN_SCHEMA, SN74HC595_INPUT_PIN_SCHEMA)) +@pins.PIN_SCHEMA_REGISTRY.register( + CONF_SN74HC595, (SN74HC595_OUTPUT_PIN_SCHEMA, SN74HC595_INPUT_PIN_SCHEMA) +) def sn74hc595_pin_to_code(config): parent = yield cg.get_variable(config[CONF_SN74HC595]) yield SN74HC595GPIOPin.new(parent, config[CONF_NUMBER], config[CONF_INVERTED]) diff --git a/esphome/components/sntp/time.py b/esphome/components/sntp/time.py index f6afcced0..a142ad72d 100644 --- a/esphome/components/sntp/time.py +++ b/esphome/components/sntp/time.py @@ -5,25 +5,28 @@ from esphome.core import CORE from esphome.const import CONF_ID, CONF_SERVERS -DEPENDENCIES = ['network'] -sntp_ns = cg.esphome_ns.namespace('sntp') -SNTPComponent = sntp_ns.class_('SNTPComponent', time_.RealTimeClock) +DEPENDENCIES = ["network"] +sntp_ns = cg.esphome_ns.namespace("sntp") +SNTPComponent = sntp_ns.class_("SNTPComponent", time_.RealTimeClock) DEFAULT_SERVERS = ["0.pool.ntp.org", "1.pool.ntp.org", "2.pool.ntp.org"] -CONFIG_SCHEMA = time_.TIME_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(SNTPComponent), - cv.Optional(CONF_SERVERS, default=DEFAULT_SERVERS): - cv.All(cv.ensure_list(cv.domain), cv.Length(min=1, max=3)), -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = time_.TIME_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(SNTPComponent), + cv.Optional(CONF_SERVERS, default=DEFAULT_SERVERS): cv.All( + cv.ensure_list(cv.domain), cv.Length(min=1, max=3) + ), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) servers = config[CONF_SERVERS] - servers += [''] * (3 - len(servers)) + servers += [""] * (3 - len(servers)) cg.add(var.set_servers(*servers)) yield cg.register_component(var, config) @@ -31,4 +34,4 @@ def to_code(config): if CORE.is_esp8266 and len(servers) > 1: # We need LwIP features enabled to get 3 SNTP servers (not just one) - cg.add_build_flag('-DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY') + cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY") diff --git a/esphome/components/speed/__init__.py b/esphome/components/speed/__init__.py index 7c7d64ed1..b75374863 100644 --- a/esphome/components/speed/__init__.py +++ b/esphome/components/speed/__init__.py @@ -1,3 +1,3 @@ import esphome.codegen as cg -speed_ns = cg.esphome_ns.namespace('speed') +speed_ns = cg.esphome_ns.namespace("speed") diff --git a/esphome/components/speed/fan/__init__.py b/esphome/components/speed/fan/__init__.py index 420c957d8..a8f306d71 100644 --- a/esphome/components/speed/fan/__init__.py +++ b/esphome/components/speed/fan/__init__.py @@ -1,23 +1,35 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import fan, output -from esphome.const import CONF_OSCILLATION_OUTPUT, CONF_OUTPUT, CONF_DIRECTION_OUTPUT, \ - CONF_OUTPUT_ID, CONF_SPEED, CONF_LOW, CONF_MEDIUM, CONF_HIGH +from esphome.const import ( + CONF_OSCILLATION_OUTPUT, + CONF_OUTPUT, + CONF_DIRECTION_OUTPUT, + CONF_OUTPUT_ID, + CONF_SPEED, + CONF_LOW, + CONF_MEDIUM, + CONF_HIGH, +) from .. import speed_ns -SpeedFan = speed_ns.class_('SpeedFan', cg.Component) +SpeedFan = speed_ns.class_("SpeedFan", cg.Component) -CONFIG_SCHEMA = fan.FAN_SCHEMA.extend({ - cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(SpeedFan), - cv.Required(CONF_OUTPUT): cv.use_id(output.FloatOutput), - cv.Optional(CONF_OSCILLATION_OUTPUT): cv.use_id(output.BinaryOutput), - cv.Optional(CONF_DIRECTION_OUTPUT): cv.use_id(output.BinaryOutput), - cv.Optional(CONF_SPEED, default={}): cv.Schema({ - cv.Optional(CONF_LOW, default=0.33): cv.percentage, - cv.Optional(CONF_MEDIUM, default=0.66): cv.percentage, - cv.Optional(CONF_HIGH, default=1.0): cv.percentage, - }), -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = fan.FAN_SCHEMA.extend( + { + cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(SpeedFan), + cv.Required(CONF_OUTPUT): cv.use_id(output.FloatOutput), + cv.Optional(CONF_OSCILLATION_OUTPUT): cv.use_id(output.BinaryOutput), + cv.Optional(CONF_DIRECTION_OUTPUT): cv.use_id(output.BinaryOutput), + cv.Optional(CONF_SPEED, default={}): cv.Schema( + { + cv.Optional(CONF_LOW, default=0.33): cv.percentage, + cv.Optional(CONF_MEDIUM, default=0.66): cv.percentage, + cv.Optional(CONF_HIGH, default=1.0): cv.percentage, + } + ), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/spi/__init__.py b/esphome/components/spi/__init__.py index e7f8bc378..5a25ac254 100644 --- a/esphome/components/spi/__init__.py +++ b/esphome/components/spi/__init__.py @@ -1,22 +1,33 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins -from esphome.const import CONF_CLK_PIN, CONF_ID, CONF_MISO_PIN, CONF_MOSI_PIN, CONF_SPI_ID, \ - CONF_CS_PIN +from esphome.const import ( + CONF_CLK_PIN, + CONF_ID, + CONF_MISO_PIN, + CONF_MOSI_PIN, + CONF_SPI_ID, + CONF_CS_PIN, +) from esphome.core import coroutine, coroutine_with_priority -CODEOWNERS = ['@esphome/core'] -spi_ns = cg.esphome_ns.namespace('spi') -SPIComponent = spi_ns.class_('SPIComponent', cg.Component) -SPIDevice = spi_ns.class_('SPIDevice') +CODEOWNERS = ["@esphome/core"] +spi_ns = cg.esphome_ns.namespace("spi") +SPIComponent = spi_ns.class_("SPIComponent", cg.Component) +SPIDevice = spi_ns.class_("SPIDevice") MULTI_CONF = True -CONFIG_SCHEMA = cv.All(cv.Schema({ - cv.GenerateID(): cv.declare_id(SPIComponent), - cv.Required(CONF_CLK_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_MISO_PIN): pins.gpio_input_pin_schema, - cv.Optional(CONF_MOSI_PIN): pins.gpio_output_pin_schema, -}), cv.has_at_least_one_key(CONF_MISO_PIN, CONF_MOSI_PIN)) +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(SPIComponent), + cv.Required(CONF_CLK_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_MISO_PIN): pins.gpio_input_pin_schema, + cv.Optional(CONF_MOSI_PIN): pins.gpio_output_pin_schema, + } + ), + cv.has_at_least_one_key(CONF_MISO_PIN, CONF_MOSI_PIN), +) @coroutine_with_priority(1.0) diff --git a/esphome/components/sps30/sensor.py b/esphome/components/sps30/sensor.py index 9f139aa26..5bc586ea8 100644 --- a/esphome/components/sps30/sensor.py +++ b/esphome/components/sps30/sensor.py @@ -1,39 +1,83 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, sensor -from esphome.const import CONF_ID, CONF_PM_1_0, CONF_PM_2_5, CONF_PM_4_0, CONF_PM_10_0, \ - CONF_PMC_0_5, CONF_PMC_1_0, CONF_PMC_2_5, CONF_PMC_4_0, CONF_PMC_10_0, CONF_PM_SIZE, \ - DEVICE_CLASS_EMPTY, UNIT_MICROGRAMS_PER_CUBIC_METER, UNIT_COUNTS_PER_CUBIC_METER, \ - UNIT_MICROMETER, ICON_CHEMICAL_WEAPON, ICON_COUNTER, ICON_RULER +from esphome.const import ( + CONF_ID, + CONF_PM_1_0, + CONF_PM_2_5, + CONF_PM_4_0, + CONF_PM_10_0, + CONF_PMC_0_5, + CONF_PMC_1_0, + CONF_PMC_2_5, + CONF_PMC_4_0, + CONF_PMC_10_0, + CONF_PM_SIZE, + DEVICE_CLASS_EMPTY, + UNIT_MICROGRAMS_PER_CUBIC_METER, + UNIT_COUNTS_PER_CUBIC_METER, + UNIT_MICROMETER, + ICON_CHEMICAL_WEAPON, + ICON_COUNTER, + ICON_RULER, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -sps30_ns = cg.esphome_ns.namespace('sps30') -SPS30Component = sps30_ns.class_('SPS30Component', cg.PollingComponent, i2c.I2CDevice) +sps30_ns = cg.esphome_ns.namespace("sps30") +SPS30Component = sps30_ns.class_("SPS30Component", cg.PollingComponent, i2c.I2CDevice) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(SPS30Component), - cv.Optional(CONF_PM_1_0): sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, - ICON_CHEMICAL_WEAPON, 2, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_PM_2_5): sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, - ICON_CHEMICAL_WEAPON, 2, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_PM_4_0): sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, - ICON_CHEMICAL_WEAPON, 2, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_PM_10_0): sensor.sensor_schema(UNIT_MICROGRAMS_PER_CUBIC_METER, - ICON_CHEMICAL_WEAPON, 2, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_PMC_0_5): sensor.sensor_schema(UNIT_COUNTS_PER_CUBIC_METER, - ICON_COUNTER, 2, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_PMC_1_0): sensor.sensor_schema(UNIT_COUNTS_PER_CUBIC_METER, - ICON_COUNTER, 2, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_PMC_2_5): sensor.sensor_schema(UNIT_COUNTS_PER_CUBIC_METER, - ICON_COUNTER, 2, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_PMC_4_0): sensor.sensor_schema(UNIT_COUNTS_PER_CUBIC_METER, - ICON_COUNTER, 2, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_PMC_10_0): sensor.sensor_schema(UNIT_COUNTS_PER_CUBIC_METER, - ICON_COUNTER, 2, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_PM_SIZE): sensor.sensor_schema(UNIT_MICROMETER, - ICON_RULER, 0, DEVICE_CLASS_EMPTY), -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x69)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(SPS30Component), + cv.Optional(CONF_PM_1_0): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, + 2, + DEVICE_CLASS_EMPTY, + ), + cv.Optional(CONF_PM_2_5): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, + 2, + DEVICE_CLASS_EMPTY, + ), + cv.Optional(CONF_PM_4_0): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, + 2, + DEVICE_CLASS_EMPTY, + ), + cv.Optional(CONF_PM_10_0): sensor.sensor_schema( + UNIT_MICROGRAMS_PER_CUBIC_METER, + ICON_CHEMICAL_WEAPON, + 2, + DEVICE_CLASS_EMPTY, + ), + cv.Optional(CONF_PMC_0_5): sensor.sensor_schema( + UNIT_COUNTS_PER_CUBIC_METER, ICON_COUNTER, 2, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_PMC_1_0): sensor.sensor_schema( + UNIT_COUNTS_PER_CUBIC_METER, ICON_COUNTER, 2, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_PMC_2_5): sensor.sensor_schema( + UNIT_COUNTS_PER_CUBIC_METER, ICON_COUNTER, 2, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_PMC_4_0): sensor.sensor_schema( + UNIT_COUNTS_PER_CUBIC_METER, ICON_COUNTER, 2, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_PMC_10_0): sensor.sensor_schema( + UNIT_COUNTS_PER_CUBIC_METER, ICON_COUNTER, 2, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_PM_SIZE): sensor.sensor_schema( + UNIT_MICROMETER, ICON_RULER, 0, DEVICE_CLASS_EMPTY + ), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x69)) +) def to_code(config): diff --git a/esphome/components/ssd1306_base/__init__.py b/esphome/components/ssd1306_base/__init__.py index a8b2a2a7b..af7c1a019 100644 --- a/esphome/components/ssd1306_base/__init__.py +++ b/esphome/components/ssd1306_base/__init__.py @@ -2,33 +2,40 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.components import display -from esphome.const import CONF_EXTERNAL_VCC, CONF_LAMBDA, CONF_MODEL, CONF_RESET_PIN, \ - CONF_BRIGHTNESS +from esphome.const import ( + CONF_EXTERNAL_VCC, + CONF_LAMBDA, + CONF_MODEL, + CONF_RESET_PIN, + CONF_BRIGHTNESS, +) from esphome.core import coroutine -ssd1306_base_ns = cg.esphome_ns.namespace('ssd1306_base') -SSD1306 = ssd1306_base_ns.class_('SSD1306', cg.PollingComponent, display.DisplayBuffer) -SSD1306Model = ssd1306_base_ns.enum('SSD1306Model') +ssd1306_base_ns = cg.esphome_ns.namespace("ssd1306_base") +SSD1306 = ssd1306_base_ns.class_("SSD1306", cg.PollingComponent, display.DisplayBuffer) +SSD1306Model = ssd1306_base_ns.enum("SSD1306Model") MODELS = { - 'SSD1306_128X32': SSD1306Model.SSD1306_MODEL_128_32, - 'SSD1306_128X64': SSD1306Model.SSD1306_MODEL_128_64, - 'SSD1306_96X16': SSD1306Model.SSD1306_MODEL_96_16, - 'SSD1306_64X48': SSD1306Model.SSD1306_MODEL_64_48, - 'SH1106_128X32': SSD1306Model.SH1106_MODEL_128_32, - 'SH1106_128X64': SSD1306Model.SH1106_MODEL_128_64, - 'SH1106_96X16': SSD1306Model.SH1106_MODEL_96_16, - 'SH1106_64X48': SSD1306Model.SH1106_MODEL_64_48, + "SSD1306_128X32": SSD1306Model.SSD1306_MODEL_128_32, + "SSD1306_128X64": SSD1306Model.SSD1306_MODEL_128_64, + "SSD1306_96X16": SSD1306Model.SSD1306_MODEL_96_16, + "SSD1306_64X48": SSD1306Model.SSD1306_MODEL_64_48, + "SH1106_128X32": SSD1306Model.SH1106_MODEL_128_32, + "SH1106_128X64": SSD1306Model.SH1106_MODEL_128_64, + "SH1106_96X16": SSD1306Model.SH1106_MODEL_96_16, + "SH1106_64X48": SSD1306Model.SH1106_MODEL_64_48, } SSD1306_MODEL = cv.enum(MODELS, upper=True, space="_") -SSD1306_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend({ - cv.Required(CONF_MODEL): SSD1306_MODEL, - cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, - cv.Optional(CONF_EXTERNAL_VCC): cv.boolean, -}).extend(cv.polling_component_schema('1s')) +SSD1306_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend( + { + cv.Required(CONF_MODEL): SSD1306_MODEL, + cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, + cv.Optional(CONF_EXTERNAL_VCC): cv.boolean, + } +).extend(cv.polling_component_schema("1s")) @coroutine @@ -46,5 +53,6 @@ def setup_ssd1036(var, config): cg.add(var.set_external_vcc(config[CONF_EXTERNAL_VCC])) if CONF_LAMBDA in config: lambda_ = yield cg.process_lambda( - config[CONF_LAMBDA], [(display.DisplayBufferRef, 'it')], return_type=cg.void) + config[CONF_LAMBDA], [(display.DisplayBufferRef, "it")], return_type=cg.void + ) cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/ssd1306_i2c/display.py b/esphome/components/ssd1306_i2c/display.py index eaa656f26..c51ef1cfb 100644 --- a/esphome/components/ssd1306_i2c/display.py +++ b/esphome/components/ssd1306_i2c/display.py @@ -3,16 +3,22 @@ import esphome.config_validation as cv from esphome.components import ssd1306_base, i2c from esphome.const import CONF_ID, CONF_LAMBDA, CONF_PAGES -AUTO_LOAD = ['ssd1306_base'] -DEPENDENCIES = ['i2c'] +AUTO_LOAD = ["ssd1306_base"] +DEPENDENCIES = ["i2c"] -ssd1306_i2c = cg.esphome_ns.namespace('ssd1306_i2c') -I2CSSD1306 = ssd1306_i2c.class_('I2CSSD1306', ssd1306_base.SSD1306, i2c.I2CDevice) +ssd1306_i2c = cg.esphome_ns.namespace("ssd1306_i2c") +I2CSSD1306 = ssd1306_i2c.class_("I2CSSD1306", ssd1306_base.SSD1306, i2c.I2CDevice) -CONFIG_SCHEMA = cv.All(ssd1306_base.SSD1306_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(I2CSSD1306), -}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x3C)), - cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) +CONFIG_SCHEMA = cv.All( + ssd1306_base.SSD1306_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(I2CSSD1306), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x3C)), + cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), +) def to_code(config): diff --git a/esphome/components/ssd1306_spi/display.py b/esphome/components/ssd1306_spi/display.py index 19882af6c..b1558ac41 100644 --- a/esphome/components/ssd1306_spi/display.py +++ b/esphome/components/ssd1306_spi/display.py @@ -4,17 +4,23 @@ from esphome import pins from esphome.components import spi, ssd1306_base from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES -AUTO_LOAD = ['ssd1306_base'] -DEPENDENCIES = ['spi'] +AUTO_LOAD = ["ssd1306_base"] +DEPENDENCIES = ["spi"] -ssd1306_spi = cg.esphome_ns.namespace('ssd1306_spi') -SPISSD1306 = ssd1306_spi.class_('SPISSD1306', ssd1306_base.SSD1306, spi.SPIDevice) +ssd1306_spi = cg.esphome_ns.namespace("ssd1306_spi") +SPISSD1306 = ssd1306_spi.class_("SPISSD1306", ssd1306_base.SSD1306, spi.SPIDevice) -CONFIG_SCHEMA = cv.All(ssd1306_base.SSD1306_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(SPISSD1306), - cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, -}).extend(cv.COMPONENT_SCHEMA).extend(spi.spi_device_schema()), - cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) +CONFIG_SCHEMA = cv.All( + ssd1306_base.SSD1306_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(SPISSD1306), + cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(spi.spi_device_schema()), + cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), +) def to_code(config): diff --git a/esphome/components/ssd1322_base/__init__.py b/esphome/components/ssd1322_base/__init__.py index addfec415..0792fd0f8 100644 --- a/esphome/components/ssd1322_base/__init__.py +++ b/esphome/components/ssd1322_base/__init__.py @@ -2,28 +2,35 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.components import display -from esphome.const import CONF_BRIGHTNESS, CONF_EXTERNAL_VCC, CONF_LAMBDA, CONF_MODEL, \ - CONF_RESET_PIN +from esphome.const import ( + CONF_BRIGHTNESS, + CONF_EXTERNAL_VCC, + CONF_LAMBDA, + CONF_MODEL, + CONF_RESET_PIN, +) from esphome.core import coroutine -CODEOWNERS = ['@kbx81'] +CODEOWNERS = ["@kbx81"] -ssd1322_base_ns = cg.esphome_ns.namespace('ssd1322_base') -SSD1322 = ssd1322_base_ns.class_('SSD1322', cg.PollingComponent, display.DisplayBuffer) -SSD1322Model = ssd1322_base_ns.enum('SSD1322Model') +ssd1322_base_ns = cg.esphome_ns.namespace("ssd1322_base") +SSD1322 = ssd1322_base_ns.class_("SSD1322", cg.PollingComponent, display.DisplayBuffer) +SSD1322Model = ssd1322_base_ns.enum("SSD1322Model") MODELS = { - 'SSD1322_256X64': SSD1322Model.SSD1322_MODEL_256_64, + "SSD1322_256X64": SSD1322Model.SSD1322_MODEL_256_64, } SSD1322_MODEL = cv.enum(MODELS, upper=True, space="_") -SSD1322_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend({ - cv.Required(CONF_MODEL): SSD1322_MODEL, - cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, - cv.Optional(CONF_EXTERNAL_VCC): cv.boolean, -}).extend(cv.polling_component_schema('1s')) +SSD1322_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend( + { + cv.Required(CONF_MODEL): SSD1322_MODEL, + cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, + cv.Optional(CONF_EXTERNAL_VCC): cv.boolean, + } +).extend(cv.polling_component_schema("1s")) @coroutine @@ -41,5 +48,6 @@ def setup_ssd1322(var, config): cg.add(var.set_external_vcc(config[CONF_EXTERNAL_VCC])) if CONF_LAMBDA in config: lambda_ = yield cg.process_lambda( - config[CONF_LAMBDA], [(display.DisplayBufferRef, 'it')], return_type=cg.void) + config[CONF_LAMBDA], [(display.DisplayBufferRef, "it")], return_type=cg.void + ) cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/ssd1322_spi/display.py b/esphome/components/ssd1322_spi/display.py index cf900e9e2..fa094acc5 100644 --- a/esphome/components/ssd1322_spi/display.py +++ b/esphome/components/ssd1322_spi/display.py @@ -4,19 +4,25 @@ from esphome import pins from esphome.components import spi, ssd1322_base from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES -CODEOWNERS = ['@kbx81'] +CODEOWNERS = ["@kbx81"] -AUTO_LOAD = ['ssd1322_base'] -DEPENDENCIES = ['spi'] +AUTO_LOAD = ["ssd1322_base"] +DEPENDENCIES = ["spi"] -ssd1322_spi = cg.esphome_ns.namespace('ssd1322_spi') -SPISSD1322 = ssd1322_spi.class_('SPISSD1322', ssd1322_base.SSD1322, spi.SPIDevice) +ssd1322_spi = cg.esphome_ns.namespace("ssd1322_spi") +SPISSD1322 = ssd1322_spi.class_("SPISSD1322", ssd1322_base.SSD1322, spi.SPIDevice) -CONFIG_SCHEMA = cv.All(ssd1322_base.SSD1322_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(SPISSD1322), - cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, -}).extend(cv.COMPONENT_SCHEMA).extend(spi.spi_device_schema(cs_pin_required=False)), - cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) +CONFIG_SCHEMA = cv.All( + ssd1322_base.SSD1322_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(SPISSD1322), + cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(spi.spi_device_schema(cs_pin_required=False)), + cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), +) def to_code(config): diff --git a/esphome/components/ssd1325_base/__init__.py b/esphome/components/ssd1325_base/__init__.py index e51f67e8b..1e6535c7e 100644 --- a/esphome/components/ssd1325_base/__init__.py +++ b/esphome/components/ssd1325_base/__init__.py @@ -2,32 +2,39 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.components import display -from esphome.const import CONF_BRIGHTNESS, CONF_EXTERNAL_VCC, CONF_LAMBDA, CONF_MODEL, \ - CONF_RESET_PIN +from esphome.const import ( + CONF_BRIGHTNESS, + CONF_EXTERNAL_VCC, + CONF_LAMBDA, + CONF_MODEL, + CONF_RESET_PIN, +) from esphome.core import coroutine -CODEOWNERS = ['@kbx81'] +CODEOWNERS = ["@kbx81"] -ssd1325_base_ns = cg.esphome_ns.namespace('ssd1325_base') -SSD1325 = ssd1325_base_ns.class_('SSD1325', cg.PollingComponent, display.DisplayBuffer) -SSD1325Model = ssd1325_base_ns.enum('SSD1325Model') +ssd1325_base_ns = cg.esphome_ns.namespace("ssd1325_base") +SSD1325 = ssd1325_base_ns.class_("SSD1325", cg.PollingComponent, display.DisplayBuffer) +SSD1325Model = ssd1325_base_ns.enum("SSD1325Model") MODELS = { - 'SSD1325_128X32': SSD1325Model.SSD1325_MODEL_128_32, - 'SSD1325_128X64': SSD1325Model.SSD1325_MODEL_128_64, - 'SSD1325_96X16': SSD1325Model.SSD1325_MODEL_96_16, - 'SSD1325_64X48': SSD1325Model.SSD1325_MODEL_64_48, - 'SSD1327_128X128': SSD1325Model.SSD1327_MODEL_128_128, + "SSD1325_128X32": SSD1325Model.SSD1325_MODEL_128_32, + "SSD1325_128X64": SSD1325Model.SSD1325_MODEL_128_64, + "SSD1325_96X16": SSD1325Model.SSD1325_MODEL_96_16, + "SSD1325_64X48": SSD1325Model.SSD1325_MODEL_64_48, + "SSD1327_128X128": SSD1325Model.SSD1327_MODEL_128_128, } SSD1325_MODEL = cv.enum(MODELS, upper=True, space="_") -SSD1325_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend({ - cv.Required(CONF_MODEL): SSD1325_MODEL, - cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, - cv.Optional(CONF_EXTERNAL_VCC): cv.boolean, -}).extend(cv.polling_component_schema('1s')) +SSD1325_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend( + { + cv.Required(CONF_MODEL): SSD1325_MODEL, + cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, + cv.Optional(CONF_EXTERNAL_VCC): cv.boolean, + } +).extend(cv.polling_component_schema("1s")) @coroutine @@ -45,5 +52,6 @@ def setup_ssd1325(var, config): cg.add(var.set_external_vcc(config[CONF_EXTERNAL_VCC])) if CONF_LAMBDA in config: lambda_ = yield cg.process_lambda( - config[CONF_LAMBDA], [(display.DisplayBufferRef, 'it')], return_type=cg.void) + config[CONF_LAMBDA], [(display.DisplayBufferRef, "it")], return_type=cg.void + ) cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/ssd1325_spi/display.py b/esphome/components/ssd1325_spi/display.py index 9471cf9c7..6ce133bec 100644 --- a/esphome/components/ssd1325_spi/display.py +++ b/esphome/components/ssd1325_spi/display.py @@ -4,19 +4,25 @@ from esphome import pins from esphome.components import spi, ssd1325_base from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES -CODEOWNERS = ['@kbx81'] +CODEOWNERS = ["@kbx81"] -AUTO_LOAD = ['ssd1325_base'] -DEPENDENCIES = ['spi'] +AUTO_LOAD = ["ssd1325_base"] +DEPENDENCIES = ["spi"] -ssd1325_spi = cg.esphome_ns.namespace('ssd1325_spi') -SPISSD1325 = ssd1325_spi.class_('SPISSD1325', ssd1325_base.SSD1325, spi.SPIDevice) +ssd1325_spi = cg.esphome_ns.namespace("ssd1325_spi") +SPISSD1325 = ssd1325_spi.class_("SPISSD1325", ssd1325_base.SSD1325, spi.SPIDevice) -CONFIG_SCHEMA = cv.All(ssd1325_base.SSD1325_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(SPISSD1325), - cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, -}).extend(cv.COMPONENT_SCHEMA).extend(spi.spi_device_schema(cs_pin_required=False)), - cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) +CONFIG_SCHEMA = cv.All( + ssd1325_base.SSD1325_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(SPISSD1325), + cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(spi.spi_device_schema(cs_pin_required=False)), + cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), +) def to_code(config): diff --git a/esphome/components/ssd1327_base/__init__.py b/esphome/components/ssd1327_base/__init__.py index ee282f215..74446d6f0 100644 --- a/esphome/components/ssd1327_base/__init__.py +++ b/esphome/components/ssd1327_base/__init__.py @@ -5,23 +5,25 @@ from esphome.components import display from esphome.const import CONF_BRIGHTNESS, CONF_LAMBDA, CONF_MODEL, CONF_RESET_PIN from esphome.core import coroutine -CODEOWNERS = ['@kbx81'] +CODEOWNERS = ["@kbx81"] -ssd1327_base_ns = cg.esphome_ns.namespace('ssd1327_base') -SSD1327 = ssd1327_base_ns.class_('SSD1327', cg.PollingComponent, display.DisplayBuffer) -SSD1327Model = ssd1327_base_ns.enum('SSD1327Model') +ssd1327_base_ns = cg.esphome_ns.namespace("ssd1327_base") +SSD1327 = ssd1327_base_ns.class_("SSD1327", cg.PollingComponent, display.DisplayBuffer) +SSD1327Model = ssd1327_base_ns.enum("SSD1327Model") MODELS = { - 'SSD1327_128X128': SSD1327Model.SSD1327_MODEL_128_128, + "SSD1327_128X128": SSD1327Model.SSD1327_MODEL_128_128, } SSD1327_MODEL = cv.enum(MODELS, upper=True, space="_") -SSD1327_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend({ - cv.Required(CONF_MODEL): SSD1327_MODEL, - cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, -}).extend(cv.polling_component_schema('1s')) +SSD1327_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend( + { + cv.Required(CONF_MODEL): SSD1327_MODEL, + cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, + } +).extend(cv.polling_component_schema("1s")) @coroutine @@ -37,5 +39,6 @@ def setup_ssd1327(var, config): cg.add(var.init_brightness(config[CONF_BRIGHTNESS])) if CONF_LAMBDA in config: lambda_ = yield cg.process_lambda( - config[CONF_LAMBDA], [(display.DisplayBufferRef, 'it')], return_type=cg.void) + config[CONF_LAMBDA], [(display.DisplayBufferRef, "it")], return_type=cg.void + ) cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/ssd1327_i2c/display.py b/esphome/components/ssd1327_i2c/display.py index 9caa0ce03..f13ed003a 100644 --- a/esphome/components/ssd1327_i2c/display.py +++ b/esphome/components/ssd1327_i2c/display.py @@ -3,18 +3,24 @@ import esphome.config_validation as cv from esphome.components import ssd1327_base, i2c from esphome.const import CONF_ID, CONF_LAMBDA, CONF_PAGES -CODEOWNERS = ['@kbx81'] +CODEOWNERS = ["@kbx81"] -AUTO_LOAD = ['ssd1327_base'] -DEPENDENCIES = ['i2c'] +AUTO_LOAD = ["ssd1327_base"] +DEPENDENCIES = ["i2c"] -ssd1327_i2c = cg.esphome_ns.namespace('ssd1327_i2c') -I2CSSD1327 = ssd1327_i2c.class_('I2CSSD1327', ssd1327_base.SSD1327, i2c.I2CDevice) +ssd1327_i2c = cg.esphome_ns.namespace("ssd1327_i2c") +I2CSSD1327 = ssd1327_i2c.class_("I2CSSD1327", ssd1327_base.SSD1327, i2c.I2CDevice) -CONFIG_SCHEMA = cv.All(ssd1327_base.SSD1327_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(I2CSSD1327), -}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x3D)), - cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) +CONFIG_SCHEMA = cv.All( + ssd1327_base.SSD1327_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(I2CSSD1327), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x3D)), + cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), +) def to_code(config): diff --git a/esphome/components/ssd1327_spi/display.py b/esphome/components/ssd1327_spi/display.py index 5e3d21dae..fe119836a 100644 --- a/esphome/components/ssd1327_spi/display.py +++ b/esphome/components/ssd1327_spi/display.py @@ -4,19 +4,25 @@ from esphome import pins from esphome.components import spi, ssd1327_base from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES -CODEOWNERS = ['@kbx81'] +CODEOWNERS = ["@kbx81"] -AUTO_LOAD = ['ssd1327_base'] -DEPENDENCIES = ['spi'] +AUTO_LOAD = ["ssd1327_base"] +DEPENDENCIES = ["spi"] -ssd1327_spi = cg.esphome_ns.namespace('ssd1327_spi') -SPISSD1327 = ssd1327_spi.class_('SPISSD1327', ssd1327_base.SSD1327, spi.SPIDevice) +ssd1327_spi = cg.esphome_ns.namespace("ssd1327_spi") +SPISSD1327 = ssd1327_spi.class_("SPISSD1327", ssd1327_base.SSD1327, spi.SPIDevice) -CONFIG_SCHEMA = cv.All(ssd1327_base.SSD1327_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(SPISSD1327), - cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, -}).extend(cv.COMPONENT_SCHEMA).extend(spi.spi_device_schema(cs_pin_required=False)), - cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) +CONFIG_SCHEMA = cv.All( + ssd1327_base.SSD1327_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(SPISSD1327), + cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(spi.spi_device_schema(cs_pin_required=False)), + cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), +) def to_code(config): diff --git a/esphome/components/ssd1331_base/__init__.py b/esphome/components/ssd1331_base/__init__.py index f6423f4aa..e151d3fe1 100644 --- a/esphome/components/ssd1331_base/__init__.py +++ b/esphome/components/ssd1331_base/__init__.py @@ -5,15 +5,17 @@ from esphome.components import display from esphome.const import CONF_BRIGHTNESS, CONF_LAMBDA, CONF_RESET_PIN from esphome.core import coroutine -CODEOWNERS = ['@kbx81'] +CODEOWNERS = ["@kbx81"] -ssd1331_base_ns = cg.esphome_ns.namespace('ssd1331_base') -SSD1331 = ssd1331_base_ns.class_('SSD1331', cg.PollingComponent, display.DisplayBuffer) +ssd1331_base_ns = cg.esphome_ns.namespace("ssd1331_base") +SSD1331 = ssd1331_base_ns.class_("SSD1331", cg.PollingComponent, display.DisplayBuffer) -SSD1331_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend({ - cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, -}).extend(cv.polling_component_schema('1s')) +SSD1331_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend( + { + cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, + } +).extend(cv.polling_component_schema("1s")) @coroutine @@ -28,5 +30,6 @@ def setup_ssd1331(var, config): cg.add(var.init_brightness(config[CONF_BRIGHTNESS])) if CONF_LAMBDA in config: lambda_ = yield cg.process_lambda( - config[CONF_LAMBDA], [(display.DisplayBufferRef, 'it')], return_type=cg.void) + config[CONF_LAMBDA], [(display.DisplayBufferRef, "it")], return_type=cg.void + ) cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/ssd1331_spi/display.py b/esphome/components/ssd1331_spi/display.py index c10d34539..c4e9dad8b 100644 --- a/esphome/components/ssd1331_spi/display.py +++ b/esphome/components/ssd1331_spi/display.py @@ -4,19 +4,25 @@ from esphome import pins from esphome.components import spi, ssd1331_base from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES -CODEOWNERS = ['@kbx81'] +CODEOWNERS = ["@kbx81"] -AUTO_LOAD = ['ssd1331_base'] -DEPENDENCIES = ['spi'] +AUTO_LOAD = ["ssd1331_base"] +DEPENDENCIES = ["spi"] -ssd1331_spi = cg.esphome_ns.namespace('ssd1331_spi') -SPISSD1331 = ssd1331_spi.class_('SPISSD1331', ssd1331_base.SSD1331, spi.SPIDevice) +ssd1331_spi = cg.esphome_ns.namespace("ssd1331_spi") +SPISSD1331 = ssd1331_spi.class_("SPISSD1331", ssd1331_base.SSD1331, spi.SPIDevice) -CONFIG_SCHEMA = cv.All(ssd1331_base.SSD1331_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(SPISSD1331), - cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, -}).extend(cv.COMPONENT_SCHEMA).extend(spi.spi_device_schema()), - cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) +CONFIG_SCHEMA = cv.All( + ssd1331_base.SSD1331_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(SPISSD1331), + cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(spi.spi_device_schema()), + cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), +) def to_code(config): diff --git a/esphome/components/ssd1351_base/__init__.py b/esphome/components/ssd1351_base/__init__.py index 3bff245b8..5e2c14cb6 100644 --- a/esphome/components/ssd1351_base/__init__.py +++ b/esphome/components/ssd1351_base/__init__.py @@ -5,24 +5,26 @@ from esphome.components import display from esphome.const import CONF_BRIGHTNESS, CONF_LAMBDA, CONF_MODEL, CONF_RESET_PIN from esphome.core import coroutine -CODEOWNERS = ['@kbx81'] +CODEOWNERS = ["@kbx81"] -ssd1351_base_ns = cg.esphome_ns.namespace('ssd1351_base') -SSD1351 = ssd1351_base_ns.class_('SSD1351', cg.PollingComponent, display.DisplayBuffer) -SSD1351Model = ssd1351_base_ns.enum('SSD1351Model') +ssd1351_base_ns = cg.esphome_ns.namespace("ssd1351_base") +SSD1351 = ssd1351_base_ns.class_("SSD1351", cg.PollingComponent, display.DisplayBuffer) +SSD1351Model = ssd1351_base_ns.enum("SSD1351Model") MODELS = { - 'SSD1351_128X96': SSD1351Model.SSD1351_MODEL_128_96, - 'SSD1351_128X128': SSD1351Model.SSD1351_MODEL_128_128, + "SSD1351_128X96": SSD1351Model.SSD1351_MODEL_128_96, + "SSD1351_128X128": SSD1351Model.SSD1351_MODEL_128_128, } SSD1351_MODEL = cv.enum(MODELS, upper=True, space="_") -SSD1351_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend({ - cv.Required(CONF_MODEL): SSD1351_MODEL, - cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, -}).extend(cv.polling_component_schema('1s')) +SSD1351_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend( + { + cv.Required(CONF_MODEL): SSD1351_MODEL, + cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, + } +).extend(cv.polling_component_schema("1s")) @coroutine @@ -38,5 +40,6 @@ def setup_ssd1351(var, config): cg.add(var.init_brightness(config[CONF_BRIGHTNESS])) if CONF_LAMBDA in config: lambda_ = yield cg.process_lambda( - config[CONF_LAMBDA], [(display.DisplayBufferRef, 'it')], return_type=cg.void) + config[CONF_LAMBDA], [(display.DisplayBufferRef, "it")], return_type=cg.void + ) cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/ssd1351_spi/display.py b/esphome/components/ssd1351_spi/display.py index 30b4c7308..66e4fad02 100644 --- a/esphome/components/ssd1351_spi/display.py +++ b/esphome/components/ssd1351_spi/display.py @@ -4,19 +4,25 @@ from esphome import pins from esphome.components import spi, ssd1351_base from esphome.const import CONF_DC_PIN, CONF_ID, CONF_LAMBDA, CONF_PAGES -CODEOWNERS = ['@kbx81'] +CODEOWNERS = ["@kbx81"] -AUTO_LOAD = ['ssd1351_base'] -DEPENDENCIES = ['spi'] +AUTO_LOAD = ["ssd1351_base"] +DEPENDENCIES = ["spi"] -ssd1351_spi = cg.esphome_ns.namespace('ssd1351_spi') -SPISSD1351 = ssd1351_spi.class_('SPISSD1351', ssd1351_base.SSD1351, spi.SPIDevice) +ssd1351_spi = cg.esphome_ns.namespace("ssd1351_spi") +SPISSD1351 = ssd1351_spi.class_("SPISSD1351", ssd1351_base.SSD1351, spi.SPIDevice) -CONFIG_SCHEMA = cv.All(ssd1351_base.SSD1351_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(SPISSD1351), - cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, -}).extend(cv.COMPONENT_SCHEMA).extend(spi.spi_device_schema()), - cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) +CONFIG_SCHEMA = cv.All( + ssd1351_base.SSD1351_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(SPISSD1351), + cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(spi.spi_device_schema()), + cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), +) def to_code(config): diff --git a/esphome/components/st7735/__init__.py b/esphome/components/st7735/__init__.py index 9f1d58b67..ba854bb0a 100644 --- a/esphome/components/st7735/__init__.py +++ b/esphome/components/st7735/__init__.py @@ -1,2 +1,3 @@ import esphome.codegen as cg -st7735_ns = cg.esphome_ns.namespace('st7735') + +st7735_ns = cg.esphome_ns.namespace("st7735") diff --git a/esphome/components/st7789v/__init__.py b/esphome/components/st7789v/__init__.py index dc85fa6b7..3e64d09c5 100644 --- a/esphome/components/st7789v/__init__.py +++ b/esphome/components/st7789v/__init__.py @@ -1,3 +1,3 @@ import esphome.codegen as cg -st7789v_ns = cg.esphome_ns.namespace('st7789v') +st7789v_ns = cg.esphome_ns.namespace("st7789v") diff --git a/esphome/components/st7789v/display.py b/esphome/components/st7789v/display.py index 5815ae599..9b3d55037 100644 --- a/esphome/components/st7789v/display.py +++ b/esphome/components/st7789v/display.py @@ -2,26 +2,40 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.components import display, spi -from esphome.const import CONF_BACKLIGHT_PIN, CONF_BRIGHTNESS, CONF_CS_PIN, CONF_DC_PIN, CONF_ID, \ - CONF_LAMBDA, CONF_RESET_PIN +from esphome.const import ( + CONF_BACKLIGHT_PIN, + CONF_BRIGHTNESS, + CONF_CS_PIN, + CONF_DC_PIN, + CONF_ID, + CONF_LAMBDA, + CONF_RESET_PIN, +) from . import st7789v_ns -CODEOWNERS = ['@kbx81'] +CODEOWNERS = ["@kbx81"] -DEPENDENCIES = ['spi'] +DEPENDENCIES = ["spi"] -ST7789V = st7789v_ns.class_('ST7789V', cg.PollingComponent, spi.SPIDevice, - display.DisplayBuffer) -ST7789VRef = ST7789V.operator('ref') +ST7789V = st7789v_ns.class_( + "ST7789V", cg.PollingComponent, spi.SPIDevice, display.DisplayBuffer +) +ST7789VRef = ST7789V.operator("ref") -CONFIG_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(ST7789V), - cv.Required(CONF_RESET_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_CS_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_BACKLIGHT_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, -}).extend(cv.polling_component_schema('5s')).extend(spi.spi_device_schema()) +CONFIG_SCHEMA = ( + display.FULL_DISPLAY_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(ST7789V), + cv.Required(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_CS_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_BACKLIGHT_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_BRIGHTNESS, default=1.0): cv.percentage, + } + ) + .extend(cv.polling_component_schema("5s")) + .extend(spi.spi_device_schema()) +) def to_code(config): @@ -40,7 +54,8 @@ def to_code(config): if CONF_LAMBDA in config: lambda_ = yield cg.process_lambda( - config[CONF_LAMBDA], [(display.DisplayBufferRef, 'it')], return_type=cg.void) + config[CONF_LAMBDA], [(display.DisplayBufferRef, "it")], return_type=cg.void + ) cg.add(var.set_writer(lambda_)) yield display.register_display(var, config) diff --git a/esphome/components/status/binary_sensor.py b/esphome/components/status/binary_sensor.py index 9963461ce..3a52b0b61 100644 --- a/esphome/components/status/binary_sensor.py +++ b/esphome/components/status/binary_sensor.py @@ -3,15 +3,19 @@ import esphome.config_validation as cv from esphome.components import binary_sensor from esphome.const import CONF_ID, CONF_DEVICE_CLASS, DEVICE_CLASS_CONNECTIVITY -status_ns = cg.esphome_ns.namespace('status') -StatusBinarySensor = status_ns.class_('StatusBinarySensor', binary_sensor.BinarySensor, - cg.Component) +status_ns = cg.esphome_ns.namespace("status") +StatusBinarySensor = status_ns.class_( + "StatusBinarySensor", binary_sensor.BinarySensor, cg.Component +) -CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(StatusBinarySensor), - - cv.Optional(CONF_DEVICE_CLASS, default=DEVICE_CLASS_CONNECTIVITY): binary_sensor.device_class, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(StatusBinarySensor), + cv.Optional( + CONF_DEVICE_CLASS, default=DEVICE_CLASS_CONNECTIVITY + ): binary_sensor.device_class, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/status_led/__init__.py b/esphome/components/status_led/__init__.py index 26105b5e9..76fbc01f3 100644 --- a/esphome/components/status_led/__init__.py +++ b/esphome/components/status_led/__init__.py @@ -4,13 +4,15 @@ import esphome.codegen as cg from esphome.const import CONF_ID, CONF_PIN from esphome.core import coroutine_with_priority -status_led_ns = cg.esphome_ns.namespace('status_led') -StatusLED = status_led_ns.class_('StatusLED', cg.Component) +status_led_ns = cg.esphome_ns.namespace("status_led") +StatusLED = status_led_ns.class_("StatusLED", cg.Component) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(StatusLED), - cv.Required(CONF_PIN): pins.gpio_output_pin_schema, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(StatusLED), + cv.Required(CONF_PIN): pins.gpio_output_pin_schema, + } +).extend(cv.COMPONENT_SCHEMA) @coroutine_with_priority(80.0) @@ -20,4 +22,4 @@ def to_code(config): var = cg.Pvariable(config[CONF_ID], rhs) yield cg.register_component(var, config) cg.add(var.pre_setup()) - cg.add_define('USE_STATUS_LED') + cg.add_define("USE_STATUS_LED") diff --git a/esphome/components/stepper/__init__.py b/esphome/components/stepper/__init__.py index c61aaa7fc..53ddc82e0 100644 --- a/esphome/components/stepper/__init__.py +++ b/esphome/components/stepper/__init__.py @@ -1,28 +1,35 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation -from esphome.const import CONF_ACCELERATION, CONF_DECELERATION, CONF_ID, CONF_MAX_SPEED, \ - CONF_POSITION, CONF_TARGET, CONF_SPEED +from esphome.const import ( + CONF_ACCELERATION, + CONF_DECELERATION, + CONF_ID, + CONF_MAX_SPEED, + CONF_POSITION, + CONF_TARGET, + CONF_SPEED, +) from esphome.core import CORE, coroutine, coroutine_with_priority IS_PLATFORM_COMPONENT = True # pylint: disable=invalid-name -stepper_ns = cg.esphome_ns.namespace('stepper') -Stepper = stepper_ns.class_('Stepper') +stepper_ns = cg.esphome_ns.namespace("stepper") +Stepper = stepper_ns.class_("Stepper") -SetTargetAction = stepper_ns.class_('SetTargetAction', automation.Action) -ReportPositionAction = stepper_ns.class_('ReportPositionAction', automation.Action) -SetSpeedAction = stepper_ns.class_('SetSpeedAction', automation.Action) +SetTargetAction = stepper_ns.class_("SetTargetAction", automation.Action) +ReportPositionAction = stepper_ns.class_("ReportPositionAction", automation.Action) +SetSpeedAction = stepper_ns.class_("SetSpeedAction", automation.Action) def validate_acceleration(value): value = cv.string(value) - for suffix in ('steps/s^2', 'steps/s*s', 'steps/s/s', 'steps/ss', 'steps/(s*s)'): + for suffix in ("steps/s^2", "steps/s*s", "steps/s/s", "steps/ss", "steps/(s*s)"): if value.endswith(suffix): - value = value[:-len(suffix)] + value = value[: -len(suffix)] - if value == 'inf': + if value == "inf": return 1e6 try: @@ -39,11 +46,11 @@ def validate_acceleration(value): def validate_speed(value): value = cv.string(value) - for suffix in ('steps/s', 'steps/s'): + for suffix in ("steps/s", "steps/s"): if value.endswith(suffix): - value = value[:-len(suffix)] + value = value[: -len(suffix)] - if value == 'inf': + if value == "inf": return 1e6 try: @@ -58,11 +65,13 @@ def validate_speed(value): return value -STEPPER_SCHEMA = cv.Schema({ - cv.Required(CONF_MAX_SPEED): validate_speed, - cv.Optional(CONF_ACCELERATION, default='inf'): validate_acceleration, - cv.Optional(CONF_DECELERATION, default='inf'): validate_acceleration, -}) +STEPPER_SCHEMA = cv.Schema( + { + cv.Required(CONF_MAX_SPEED): validate_speed, + cv.Optional(CONF_ACCELERATION, default="inf"): validate_acceleration, + cv.Optional(CONF_DECELERATION, default="inf"): validate_acceleration, + } +) @coroutine @@ -82,10 +91,16 @@ def register_stepper(var, config): yield setup_stepper_core_(var, config) -@automation.register_action('stepper.set_target', SetTargetAction, cv.Schema({ - cv.Required(CONF_ID): cv.use_id(Stepper), - cv.Required(CONF_TARGET): cv.templatable(cv.int_), -})) +@automation.register_action( + "stepper.set_target", + SetTargetAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(Stepper), + cv.Required(CONF_TARGET): cv.templatable(cv.int_), + } + ), +) def stepper_set_target_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) @@ -94,10 +109,16 @@ def stepper_set_target_to_code(config, action_id, template_arg, args): yield var -@automation.register_action('stepper.report_position', ReportPositionAction, cv.Schema({ - cv.Required(CONF_ID): cv.use_id(Stepper), - cv.Required(CONF_POSITION): cv.templatable(cv.int_), -})) +@automation.register_action( + "stepper.report_position", + ReportPositionAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(Stepper), + cv.Required(CONF_POSITION): cv.templatable(cv.int_), + } + ), +) def stepper_report_position_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) @@ -106,10 +127,16 @@ def stepper_report_position_to_code(config, action_id, template_arg, args): yield var -@automation.register_action('stepper.set_speed', SetSpeedAction, cv.Schema({ - cv.Required(CONF_ID): cv.use_id(Stepper), - cv.Required(CONF_SPEED): cv.templatable(validate_speed), -})) +@automation.register_action( + "stepper.set_speed", + SetSpeedAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(Stepper), + cv.Required(CONF_SPEED): cv.templatable(validate_speed), + } + ), +) def stepper_set_speed_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) diff --git a/esphome/components/sts3x/sensor.py b/esphome/components/sts3x/sensor.py index f13ddf397..5e44c3ca3 100644 --- a/esphome/components/sts3x/sensor.py +++ b/esphome/components/sts3x/sensor.py @@ -3,16 +3,24 @@ import esphome.config_validation as cv from esphome.components import i2c, sensor from esphome.const import CONF_ID, DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, UNIT_CELSIUS -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -sts3x_ns = cg.esphome_ns.namespace('sts3x') +sts3x_ns = cg.esphome_ns.namespace("sts3x") -STS3XComponent = sts3x_ns.class_('STS3XComponent', sensor.Sensor, - cg.PollingComponent, i2c.I2CDevice) +STS3XComponent = sts3x_ns.class_( + "STS3XComponent", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice +) -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE).extend({ - cv.GenerateID(): cv.declare_id(STS3XComponent), -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x4A)) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE) + .extend( + { + cv.GenerateID(): cv.declare_id(STS3XComponent), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x4A)) +) def to_code(config): diff --git a/esphome/components/substitutions/__init__.py b/esphome/components/substitutions/__init__.py index 1cc5b50f4..61ad4a698 100644 --- a/esphome/components/substitutions/__init__.py +++ b/esphome/components/substitutions/__init__.py @@ -6,18 +6,19 @@ from esphome import core from esphome.const import CONF_SUBSTITUTIONS from esphome.yaml_util import ESPHomeDataBase, make_data_base -CODEOWNERS = ['@esphome/core'] +CODEOWNERS = ["@esphome/core"] _LOGGER = logging.getLogger(__name__) -VALID_SUBSTITUTIONS_CHARACTERS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' \ - '0123456789_' +VALID_SUBSTITUTIONS_CHARACTERS = ( + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" +) def validate_substitution_key(value): value = cv.string(value) if not value: raise cv.Invalid("Substitution key must not be empty") - if value[0] == '$': + if value[0] == "$": value = value[1:] if value[0].isdigit(): raise cv.Invalid("First character in substitutions cannot be a digit.") @@ -25,24 +26,29 @@ def validate_substitution_key(value): if char not in VALID_SUBSTITUTIONS_CHARACTERS: raise cv.Invalid( "Substitution must only consist of upper/lowercase characters, the underscore " - "and numbers. The character '{}' cannot be used".format(char)) + "and numbers. The character '{}' cannot be used".format(char) + ) return value -CONFIG_SCHEMA = cv.Schema({ - validate_substitution_key: cv.string_strict, -}) +CONFIG_SCHEMA = cv.Schema( + { + validate_substitution_key: cv.string_strict, + } +) def to_code(config): pass -VARIABLE_PROG = re.compile('\\$([{0}]+|\\{{[{0}]*\\}})'.format(VALID_SUBSTITUTIONS_CHARACTERS)) +VARIABLE_PROG = re.compile( + "\\$([{0}]+|\\{{[{0}]*\\}})".format(VALID_SUBSTITUTIONS_CHARACTERS) +) def _expand_substitutions(substitutions, value, path): - if '$' not in value: + if "$" not in value: return value orig_value = value @@ -56,11 +62,16 @@ def _expand_substitutions(substitutions, value, path): i, j = m.span(0) name = m.group(1) - if name.startswith('{') and name.endswith('}'): + if name.startswith("{") and name.endswith("}"): name = name[1:-1] if name not in substitutions: - _LOGGER.warning("Found '%s' (see %s) which looks like a substitution, but '%s' was " - "not declared", orig_value, '->'.join(str(x) for x in path), name) + _LOGGER.warning( + "Found '%s' (see %s) which looks like a substitution, but '%s' was " + "not declared", + orig_value, + "->".join(str(x) for x in path), + name, + ) i = j continue @@ -119,10 +130,12 @@ def do_substitution_pass(config, command_line_substitutions): substitutions = command_line_substitutions elif command_line_substitutions: substitutions = {**substitutions, **command_line_substitutions} - with cv.prepend_path('substitutions'): + with cv.prepend_path("substitutions"): if not isinstance(substitutions, dict): - raise cv.Invalid("Substitutions must be a key to value mapping, got {}" - "".format(type(substitutions))) + raise cv.Invalid( + "Substitutions must be a key to value mapping, got {}" + "".format(type(substitutions)) + ) replace_keys = [] for key, value in substitutions.items(): diff --git a/esphome/components/sun/__init__.py b/esphome/components/sun/__init__.py index a92442ea5..5241f1bb5 100644 --- a/esphome/components/sun/__init__.py +++ b/esphome/components/sun/__init__.py @@ -4,58 +4,67 @@ from esphome import automation from esphome.components import time from esphome.const import CONF_TIME_ID, CONF_ID, CONF_TRIGGER_ID -CODEOWNERS = ['@OttoWinter'] -sun_ns = cg.esphome_ns.namespace('sun') +CODEOWNERS = ["@OttoWinter"] +sun_ns = cg.esphome_ns.namespace("sun") -Sun = sun_ns.class_('Sun') -SunTrigger = sun_ns.class_('SunTrigger', cg.PollingComponent, automation.Trigger.template()) -SunCondition = sun_ns.class_('SunCondition', automation.Condition) +Sun = sun_ns.class_("Sun") +SunTrigger = sun_ns.class_( + "SunTrigger", cg.PollingComponent, automation.Trigger.template() +) +SunCondition = sun_ns.class_("SunCondition", automation.Condition) -CONF_SUN_ID = 'sun_id' -CONF_LATITUDE = 'latitude' -CONF_LONGITUDE = 'longitude' -CONF_ELEVATION = 'elevation' -CONF_ON_SUNRISE = 'on_sunrise' -CONF_ON_SUNSET = 'on_sunset' +CONF_SUN_ID = "sun_id" +CONF_LATITUDE = "latitude" +CONF_LONGITUDE = "longitude" +CONF_ELEVATION = "elevation" +CONF_ON_SUNRISE = "on_sunrise" +CONF_ON_SUNSET = "on_sunset" # Default sun elevation is a bit below horizon because sunset # means time when the entire sun disk is below the horizon DEFAULT_ELEVATION = -0.883 ELEVATION_MAP = { - 'sunrise': 0.0, - 'sunset': 0.0, - 'civil': -6.0, - 'nautical': -12.0, - 'astronomical': -18.0, + "sunrise": 0.0, + "sunset": 0.0, + "civil": -6.0, + "nautical": -12.0, + "astronomical": -18.0, } def elevation(value): if isinstance(value, str): try: - value = ELEVATION_MAP[cv.one_of(*ELEVATION_MAP, lower=True, space='_')(value)] + value = ELEVATION_MAP[ + cv.one_of(*ELEVATION_MAP, lower=True, space="_")(value) + ] except cv.Invalid: pass value = cv.angle(value) return cv.float_range(min=-180, max=180)(value) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(Sun), - cv.GenerateID(CONF_TIME_ID): cv.use_id(time.RealTimeClock), - cv.Required(CONF_LATITUDE): cv.float_range(min=-90, max=90), - cv.Required(CONF_LONGITUDE): cv.float_range(min=-180, max=180), - - cv.Optional(CONF_ON_SUNRISE): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SunTrigger), - cv.Optional(CONF_ELEVATION, default=DEFAULT_ELEVATION): elevation, - }), - cv.Optional(CONF_ON_SUNSET): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SunTrigger), - cv.Optional(CONF_ELEVATION, default=DEFAULT_ELEVATION): elevation, - }), -}) +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(Sun), + cv.GenerateID(CONF_TIME_ID): cv.use_id(time.RealTimeClock), + cv.Required(CONF_LATITUDE): cv.float_range(min=-90, max=90), + cv.Required(CONF_LONGITUDE): cv.float_range(min=-180, max=180), + cv.Optional(CONF_ON_SUNRISE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SunTrigger), + cv.Optional(CONF_ELEVATION, default=DEFAULT_ELEVATION): elevation, + } + ), + cv.Optional(CONF_ON_SUNSET): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SunTrigger), + cv.Optional(CONF_ELEVATION, default=DEFAULT_ELEVATION): elevation, + } + ), + } +) def to_code(config): @@ -82,10 +91,18 @@ def to_code(config): yield automation.build_automation(trigger, [], conf) -@automation.register_condition('sun.is_above_horizon', SunCondition, cv.Schema({ - cv.GenerateID(): cv.use_id(Sun), - cv.Optional(CONF_ELEVATION, default=DEFAULT_ELEVATION): cv.templatable(elevation), -})) +@automation.register_condition( + "sun.is_above_horizon", + SunCondition, + cv.Schema( + { + cv.GenerateID(): cv.use_id(Sun), + cv.Optional(CONF_ELEVATION, default=DEFAULT_ELEVATION): cv.templatable( + elevation + ), + } + ), +) def sun_above_horizon_to_code(config, condition_id, template_arg, args): var = cg.new_Pvariable(condition_id, template_arg) yield cg.register_parented(var, config[CONF_ID]) @@ -95,10 +112,18 @@ def sun_above_horizon_to_code(config, condition_id, template_arg, args): yield var -@automation.register_condition('sun.is_below_horizon', SunCondition, cv.Schema({ - cv.GenerateID(): cv.use_id(Sun), - cv.Optional(CONF_ELEVATION, default=DEFAULT_ELEVATION): cv.templatable(elevation), -})) +@automation.register_condition( + "sun.is_below_horizon", + SunCondition, + cv.Schema( + { + cv.GenerateID(): cv.use_id(Sun), + cv.Optional(CONF_ELEVATION, default=DEFAULT_ELEVATION): cv.templatable( + elevation + ), + } + ), +) def sun_below_horizon_to_code(config, condition_id, template_arg, args): var = cg.new_Pvariable(condition_id, template_arg) yield cg.register_parented(var, config[CONF_ID]) diff --git a/esphome/components/sun/sensor/__init__.py b/esphome/components/sun/sensor/__init__.py index 880e271fc..02e1ef28e 100644 --- a/esphome/components/sun/sensor/__init__.py +++ b/esphome/components/sun/sensor/__init__.py @@ -1,25 +1,35 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor -from esphome.const import DEVICE_CLASS_EMPTY, UNIT_DEGREES, ICON_WEATHER_SUNSET, CONF_ID, CONF_TYPE +from esphome.const import ( + DEVICE_CLASS_EMPTY, + UNIT_DEGREES, + ICON_WEATHER_SUNSET, + CONF_ID, + CONF_TYPE, +) from .. import sun_ns, CONF_SUN_ID, Sun -DEPENDENCIES = ['sun'] +DEPENDENCIES = ["sun"] -SunSensor = sun_ns.class_('SunSensor', sensor.Sensor, cg.PollingComponent) -SensorType = sun_ns.enum('SensorType') +SunSensor = sun_ns.class_("SunSensor", sensor.Sensor, cg.PollingComponent) +SensorType = sun_ns.enum("SensorType") TYPES = { - 'elevation': SensorType.SUN_SENSOR_ELEVATION, - 'azimuth': SensorType.SUN_SENSOR_AZIMUTH, + "elevation": SensorType.SUN_SENSOR_ELEVATION, + "azimuth": SensorType.SUN_SENSOR_AZIMUTH, } -CONFIG_SCHEMA = sensor.sensor_schema( - UNIT_DEGREES, ICON_WEATHER_SUNSET, 1, DEVICE_CLASS_EMPTY -).extend({ - cv.GenerateID(): cv.declare_id(SunSensor), - cv.GenerateID(CONF_SUN_ID): cv.use_id(Sun), - cv.Required(CONF_TYPE): cv.enum(TYPES, lower=True), -}).extend(cv.polling_component_schema('60s')) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_DEGREES, ICON_WEATHER_SUNSET, 1, DEVICE_CLASS_EMPTY) + .extend( + { + cv.GenerateID(): cv.declare_id(SunSensor), + cv.GenerateID(CONF_SUN_ID): cv.use_id(Sun), + cv.Required(CONF_TYPE): cv.enum(TYPES, lower=True), + } + ) + .extend(cv.polling_component_schema("60s")) +) def to_code(config): diff --git a/esphome/components/sun/text_sensor/__init__.py b/esphome/components/sun/text_sensor/__init__.py index 984250f9f..b527da699 100644 --- a/esphome/components/sun/text_sensor/__init__.py +++ b/esphome/components/sun/text_sensor/__init__.py @@ -1,16 +1,24 @@ from esphome.components import text_sensor import esphome.config_validation as cv import esphome.codegen as cg -from esphome.const import CONF_ICON, ICON_WEATHER_SUNSET_DOWN, ICON_WEATHER_SUNSET_UP, CONF_TYPE, \ - CONF_ID, CONF_FORMAT +from esphome.const import ( + CONF_ICON, + ICON_WEATHER_SUNSET_DOWN, + ICON_WEATHER_SUNSET_UP, + CONF_TYPE, + CONF_ID, + CONF_FORMAT, +) from .. import sun_ns, CONF_SUN_ID, Sun, CONF_ELEVATION, elevation, DEFAULT_ELEVATION -DEPENDENCIES = ['sun'] +DEPENDENCIES = ["sun"] -SunTextSensor = sun_ns.class_('SunTextSensor', text_sensor.TextSensor, cg.PollingComponent) +SunTextSensor = sun_ns.class_( + "SunTextSensor", text_sensor.TextSensor, cg.PollingComponent +) SUN_TYPES = { - 'sunset': False, - 'sunrise': True, + "sunset": False, + "sunrise": True, } @@ -18,19 +26,24 @@ def validate_optional_icon(config): if CONF_ICON not in config: config = config.copy() config[CONF_ICON] = { - 'sunset': ICON_WEATHER_SUNSET_DOWN, - 'sunrise': ICON_WEATHER_SUNSET_UP, + "sunset": ICON_WEATHER_SUNSET_DOWN, + "sunrise": ICON_WEATHER_SUNSET_UP, }[config[CONF_TYPE]] return config -CONFIG_SCHEMA = cv.All(text_sensor.TEXT_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(SunTextSensor), - cv.GenerateID(CONF_SUN_ID): cv.use_id(Sun), - cv.Required(CONF_TYPE): cv.one_of(*SUN_TYPES, lower=True), - cv.Optional(CONF_ELEVATION, default=DEFAULT_ELEVATION): elevation, - cv.Optional(CONF_FORMAT, default='%X'): cv.string_strict, -}).extend(cv.polling_component_schema('60s')), validate_optional_icon) +CONFIG_SCHEMA = cv.All( + text_sensor.TEXT_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(SunTextSensor), + cv.GenerateID(CONF_SUN_ID): cv.use_id(Sun), + cv.Required(CONF_TYPE): cv.one_of(*SUN_TYPES, lower=True), + cv.Optional(CONF_ELEVATION, default=DEFAULT_ELEVATION): elevation, + cv.Optional(CONF_FORMAT, default="%X"): cv.string_strict, + } + ).extend(cv.polling_component_schema("60s")), + validate_optional_icon, +) def to_code(config): diff --git a/esphome/components/switch/__init__.py b/esphome/components/switch/__init__.py index 7378b2a14..cc47b059c 100644 --- a/esphome/components/switch/__init__.py +++ b/esphome/components/switch/__init__.py @@ -3,40 +3,58 @@ import esphome.config_validation as cv from esphome import automation from esphome.automation import Condition, maybe_simple_id from esphome.components import mqtt -from esphome.const import CONF_ICON, CONF_ID, CONF_INTERNAL, CONF_INVERTED, CONF_ON_TURN_OFF, \ - CONF_ON_TURN_ON, CONF_TRIGGER_ID, CONF_MQTT_ID, CONF_NAME +from esphome.const import ( + CONF_ICON, + CONF_ID, + CONF_INTERNAL, + CONF_INVERTED, + CONF_ON_TURN_OFF, + CONF_ON_TURN_ON, + CONF_TRIGGER_ID, + CONF_MQTT_ID, + CONF_NAME, +) from esphome.core import CORE, coroutine, coroutine_with_priority -CODEOWNERS = ['@esphome/core'] +CODEOWNERS = ["@esphome/core"] IS_PLATFORM_COMPONENT = True -switch_ns = cg.esphome_ns.namespace('switch_') -Switch = switch_ns.class_('Switch', cg.Nameable) -SwitchPtr = Switch.operator('ptr') +switch_ns = cg.esphome_ns.namespace("switch_") +Switch = switch_ns.class_("Switch", cg.Nameable) +SwitchPtr = Switch.operator("ptr") -ToggleAction = switch_ns.class_('ToggleAction', automation.Action) -TurnOffAction = switch_ns.class_('TurnOffAction', automation.Action) -TurnOnAction = switch_ns.class_('TurnOnAction', automation.Action) -SwitchPublishAction = switch_ns.class_('SwitchPublishAction', automation.Action) +ToggleAction = switch_ns.class_("ToggleAction", automation.Action) +TurnOffAction = switch_ns.class_("TurnOffAction", automation.Action) +TurnOnAction = switch_ns.class_("TurnOnAction", automation.Action) +SwitchPublishAction = switch_ns.class_("SwitchPublishAction", automation.Action) -SwitchCondition = switch_ns.class_('SwitchCondition', Condition) -SwitchTurnOnTrigger = switch_ns.class_('SwitchTurnOnTrigger', automation.Trigger.template()) -SwitchTurnOffTrigger = switch_ns.class_('SwitchTurnOffTrigger', automation.Trigger.template()) +SwitchCondition = switch_ns.class_("SwitchCondition", Condition) +SwitchTurnOnTrigger = switch_ns.class_( + "SwitchTurnOnTrigger", automation.Trigger.template() +) +SwitchTurnOffTrigger = switch_ns.class_( + "SwitchTurnOffTrigger", automation.Trigger.template() +) icon = cv.icon -SWITCH_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ - cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTSwitchComponent), - - cv.Optional(CONF_ICON): icon, - cv.Optional(CONF_INVERTED): cv.boolean, - cv.Optional(CONF_ON_TURN_ON): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SwitchTurnOnTrigger), - }), - cv.Optional(CONF_ON_TURN_OFF): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SwitchTurnOffTrigger), - }), -}) +SWITCH_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend( + { + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTSwitchComponent), + cv.Optional(CONF_ICON): icon, + cv.Optional(CONF_INVERTED): cv.boolean, + cv.Optional(CONF_ON_TURN_ON): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SwitchTurnOnTrigger), + } + ), + cv.Optional(CONF_ON_TURN_OFF): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SwitchTurnOffTrigger), + } + ), + } +) @coroutine @@ -68,26 +86,28 @@ def register_switch(var, config): yield setup_switch_core_(var, config) -SWITCH_ACTION_SCHEMA = maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(Switch), -}) +SWITCH_ACTION_SCHEMA = maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(Switch), + } +) -@automation.register_action('switch.toggle', ToggleAction, SWITCH_ACTION_SCHEMA) -@automation.register_action('switch.turn_off', TurnOffAction, SWITCH_ACTION_SCHEMA) -@automation.register_action('switch.turn_on', TurnOnAction, SWITCH_ACTION_SCHEMA) +@automation.register_action("switch.toggle", ToggleAction, SWITCH_ACTION_SCHEMA) +@automation.register_action("switch.turn_off", TurnOffAction, SWITCH_ACTION_SCHEMA) +@automation.register_action("switch.turn_on", TurnOnAction, SWITCH_ACTION_SCHEMA) def switch_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_condition('switch.is_on', SwitchCondition, SWITCH_ACTION_SCHEMA) +@automation.register_condition("switch.is_on", SwitchCondition, SWITCH_ACTION_SCHEMA) def switch_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('switch.is_off', SwitchCondition, SWITCH_ACTION_SCHEMA) +@automation.register_condition("switch.is_off", SwitchCondition, SWITCH_ACTION_SCHEMA) def switch_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) @@ -96,4 +116,4 @@ def switch_is_off_to_code(config, condition_id, template_arg, args): @coroutine_with_priority(100.0) def to_code(config): cg.add_global(switch_ns.using) - cg.add_define('USE_SWITCH') + cg.add_define("USE_SWITCH") diff --git a/esphome/components/sx1509/__init__.py b/esphome/components/sx1509/__init__.py index 11fcfe395..06ee364e1 100644 --- a/esphome/components/sx1509/__init__.py +++ b/esphome/components/sx1509/__init__.py @@ -4,39 +4,47 @@ from esphome import pins from esphome.components import i2c from esphome.const import CONF_ID, CONF_NUMBER, CONF_MODE, CONF_INVERTED -CONF_KEYPAD = 'keypad' -CONF_KEY_ROWS = 'key_rows' -CONF_KEY_COLUMNS = 'key_columns' -CONF_SLEEP_TIME = 'sleep_time' -CONF_SCAN_TIME = 'scan_time' -CONF_DEBOUNCE_TIME = 'debounce_time' +CONF_KEYPAD = "keypad" +CONF_KEY_ROWS = "key_rows" +CONF_KEY_COLUMNS = "key_columns" +CONF_SLEEP_TIME = "sleep_time" +CONF_SCAN_TIME = "scan_time" +CONF_DEBOUNCE_TIME = "debounce_time" -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] MULTI_CONF = True -sx1509_ns = cg.esphome_ns.namespace('sx1509') -SX1509GPIOMode = sx1509_ns.enum('SX1509GPIOMode') +sx1509_ns = cg.esphome_ns.namespace("sx1509") +SX1509GPIOMode = sx1509_ns.enum("SX1509GPIOMode") SX1509_GPIO_MODES = { - 'INPUT': SX1509GPIOMode.SX1509_INPUT, - 'INPUT_PULLUP': SX1509GPIOMode.SX1509_INPUT_PULLUP, - 'OUTPUT': SX1509GPIOMode.SX1509_OUTPUT + "INPUT": SX1509GPIOMode.SX1509_INPUT, + "INPUT_PULLUP": SX1509GPIOMode.SX1509_INPUT_PULLUP, + "OUTPUT": SX1509GPIOMode.SX1509_OUTPUT, } -SX1509Component = sx1509_ns.class_('SX1509Component', cg.Component, i2c.I2CDevice) -SX1509GPIOPin = sx1509_ns.class_('SX1509GPIOPin', cg.GPIOPin) +SX1509Component = sx1509_ns.class_("SX1509Component", cg.Component, i2c.I2CDevice) +SX1509GPIOPin = sx1509_ns.class_("SX1509GPIOPin", cg.GPIOPin) -KEYPAD_SCHEMA = cv.Schema({ - cv.Required(CONF_KEY_ROWS): cv.int_range(min=1, max=8), - cv.Required(CONF_KEY_COLUMNS): cv.int_range(min=1, max=8), - cv.Optional(CONF_SLEEP_TIME): cv.int_range(min=128, max=8192), - cv.Optional(CONF_SCAN_TIME): cv.int_range(min=1, max=128), - cv.Optional(CONF_DEBOUNCE_TIME): cv.int_range(min=1, max=64), -}) +KEYPAD_SCHEMA = cv.Schema( + { + cv.Required(CONF_KEY_ROWS): cv.int_range(min=1, max=8), + cv.Required(CONF_KEY_COLUMNS): cv.int_range(min=1, max=8), + cv.Optional(CONF_SLEEP_TIME): cv.int_range(min=128, max=8192), + cv.Optional(CONF_SCAN_TIME): cv.int_range(min=1, max=128), + cv.Optional(CONF_DEBOUNCE_TIME): cv.int_range(min=1, max=64), + } +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(SX1509Component), - cv.Optional(CONF_KEYPAD): cv.Schema(KEYPAD_SCHEMA), -}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x3E)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(SX1509Component), + cv.Optional(CONF_KEYPAD): cv.Schema(KEYPAD_SCHEMA), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x3E)) +) def to_code(config): @@ -46,32 +54,44 @@ def to_code(config): if CONF_KEYPAD in config: keypad = config[CONF_KEYPAD] cg.add(var.set_rows_cols(keypad[CONF_KEY_ROWS], keypad[CONF_KEY_COLUMNS])) - if CONF_SLEEP_TIME in keypad and CONF_SCAN_TIME in keypad and CONF_DEBOUNCE_TIME in keypad: + if ( + CONF_SLEEP_TIME in keypad + and CONF_SCAN_TIME in keypad + and CONF_DEBOUNCE_TIME in keypad + ): cg.add(var.set_sleep_time(keypad[CONF_SLEEP_TIME])) cg.add(var.set_scan_time(keypad[CONF_SCAN_TIME])) cg.add(var.set_debounce_time(keypad[CONF_DEBOUNCE_TIME])) -CONF_SX1509 = 'sx1509' -CONF_SX1509_ID = 'sx1509_id' +CONF_SX1509 = "sx1509" +CONF_SX1509_ID = "sx1509_id" -SX1509_OUTPUT_PIN_SCHEMA = cv.Schema({ - cv.Required(CONF_SX1509): cv.use_id(SX1509Component), - cv.Required(CONF_NUMBER): cv.int_, - cv.Optional(CONF_MODE, default="OUTPUT"): cv.enum(SX1509_GPIO_MODES, upper=True), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) -SX1509_INPUT_PIN_SCHEMA = cv.Schema({ - cv.Required(CONF_SX1509): cv.use_id(SX1509Component), - cv.Required(CONF_NUMBER): cv.int_, - cv.Optional(CONF_MODE, default="INPUT"): cv.enum(SX1509_GPIO_MODES, upper=True), - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) +SX1509_OUTPUT_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_SX1509): cv.use_id(SX1509Component), + cv.Required(CONF_NUMBER): cv.int_, + cv.Optional(CONF_MODE, default="OUTPUT"): cv.enum( + SX1509_GPIO_MODES, upper=True + ), + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) +SX1509_INPUT_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_SX1509): cv.use_id(SX1509Component), + cv.Required(CONF_NUMBER): cv.int_, + cv.Optional(CONF_MODE, default="INPUT"): cv.enum(SX1509_GPIO_MODES, upper=True), + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) -@pins.PIN_SCHEMA_REGISTRY.register(CONF_SX1509, - (SX1509_OUTPUT_PIN_SCHEMA, SX1509_INPUT_PIN_SCHEMA)) +@pins.PIN_SCHEMA_REGISTRY.register( + CONF_SX1509, (SX1509_OUTPUT_PIN_SCHEMA, SX1509_INPUT_PIN_SCHEMA) +) def sx1509_pin_to_code(config): parent = yield cg.get_variable(config[CONF_SX1509]) - yield SX1509GPIOPin.new(parent, config[CONF_NUMBER], config[CONF_MODE], - config[CONF_INVERTED]) + yield SX1509GPIOPin.new( + parent, config[CONF_NUMBER], config[CONF_MODE], config[CONF_INVERTED] + ) diff --git a/esphome/components/sx1509/binary_sensor/__init__.py b/esphome/components/sx1509/binary_sensor/__init__.py index 9a6552438..e2344cd4a 100644 --- a/esphome/components/sx1509/binary_sensor/__init__.py +++ b/esphome/components/sx1509/binary_sensor/__init__.py @@ -4,19 +4,21 @@ from esphome.components import binary_sensor from esphome.const import CONF_ID from .. import SX1509Component, sx1509_ns, CONF_SX1509_ID -CONF_ROW = 'row' -CONF_COL = 'col' +CONF_ROW = "row" +CONF_COL = "col" -DEPENDENCIES = ['sx1509'] +DEPENDENCIES = ["sx1509"] -SX1509BinarySensor = sx1509_ns.class_('SX1509BinarySensor', binary_sensor.BinarySensor) +SX1509BinarySensor = sx1509_ns.class_("SX1509BinarySensor", binary_sensor.BinarySensor) -CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(SX1509BinarySensor), - cv.GenerateID(CONF_SX1509_ID): cv.use_id(SX1509Component), - cv.Required(CONF_ROW): cv.int_range(min=0, max=4), - cv.Required(CONF_COL): cv.int_range(min=0, max=4), -}) +CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(SX1509BinarySensor), + cv.GenerateID(CONF_SX1509_ID): cv.use_id(SX1509Component), + cv.Required(CONF_ROW): cv.int_range(min=0, max=4), + cv.Required(CONF_COL): cv.int_range(min=0, max=4), + } +) def to_code(config): diff --git a/esphome/components/sx1509/output/__init__.py b/esphome/components/sx1509/output/__init__.py index 80aec0afd..878534e82 100644 --- a/esphome/components/sx1509/output/__init__.py +++ b/esphome/components/sx1509/output/__init__.py @@ -4,16 +4,19 @@ from esphome.components import output from esphome.const import CONF_PIN, CONF_ID from .. import SX1509Component, sx1509_ns, CONF_SX1509_ID -DEPENDENCIES = ['sx1509'] +DEPENDENCIES = ["sx1509"] -SX1509FloatOutputChannel = sx1509_ns.class_('SX1509FloatOutputChannel', - output.FloatOutput, cg.Component) +SX1509FloatOutputChannel = sx1509_ns.class_( + "SX1509FloatOutputChannel", output.FloatOutput, cg.Component +) -CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend({ - cv.Required(CONF_ID): cv.declare_id(SX1509FloatOutputChannel), - cv.GenerateID(CONF_SX1509_ID): cv.use_id(SX1509Component), - cv.Required(CONF_PIN): cv.int_range(min=0, max=15), -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( + { + cv.Required(CONF_ID): cv.declare_id(SX1509FloatOutputChannel), + cv.GenerateID(CONF_SX1509_ID): cv.use_id(SX1509Component), + cv.Required(CONF_PIN): cv.int_range(min=0, max=15), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/tcl112/climate.py b/esphome/components/tcl112/climate.py index 11ebdc7be..587bdcfbe 100644 --- a/esphome/components/tcl112/climate.py +++ b/esphome/components/tcl112/climate.py @@ -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"] -tcl112_ns = cg.esphome_ns.namespace('tcl112') -Tcl112Climate = tcl112_ns.class_('Tcl112Climate', climate_ir.ClimateIR) +tcl112_ns = cg.esphome_ns.namespace("tcl112") +Tcl112Climate = tcl112_ns.class_("Tcl112Climate", climate_ir.ClimateIR) -CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(Tcl112Climate), -}) +CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(Tcl112Climate), + } +) def to_code(config): diff --git a/esphome/components/tcs34725/sensor.py b/esphome/components/tcs34725/sensor.py index acd484db3..84e3c290b 100644 --- a/esphome/components/tcs34725/sensor.py +++ b/esphome/components/tcs34725/sensor.py @@ -1,55 +1,81 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, sensor -from esphome.const import CONF_COLOR_TEMPERATURE, CONF_GAIN, CONF_ID, CONF_ILLUMINANCE, \ - CONF_INTEGRATION_TIME, DEVICE_CLASS_EMPTY, DEVICE_CLASS_ILLUMINANCE, ICON_EMPTY, \ - ICON_LIGHTBULB, UNIT_PERCENT, ICON_THERMOMETER, UNIT_KELVIN, UNIT_LUX +from esphome.const import ( + CONF_COLOR_TEMPERATURE, + CONF_GAIN, + CONF_ID, + CONF_ILLUMINANCE, + CONF_INTEGRATION_TIME, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_ILLUMINANCE, + ICON_EMPTY, + ICON_LIGHTBULB, + UNIT_PERCENT, + ICON_THERMOMETER, + UNIT_KELVIN, + UNIT_LUX, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -CONF_RED_CHANNEL = 'red_channel' -CONF_GREEN_CHANNEL = 'green_channel' -CONF_BLUE_CHANNEL = 'blue_channel' -CONF_CLEAR_CHANNEL = 'clear_channel' +CONF_RED_CHANNEL = "red_channel" +CONF_GREEN_CHANNEL = "green_channel" +CONF_BLUE_CHANNEL = "blue_channel" +CONF_CLEAR_CHANNEL = "clear_channel" -tcs34725_ns = cg.esphome_ns.namespace('tcs34725') -TCS34725Component = tcs34725_ns.class_('TCS34725Component', cg.PollingComponent, i2c.I2CDevice) +tcs34725_ns = cg.esphome_ns.namespace("tcs34725") +TCS34725Component = tcs34725_ns.class_( + "TCS34725Component", cg.PollingComponent, i2c.I2CDevice +) -TCS34725IntegrationTime = tcs34725_ns.enum('TCS34725IntegrationTime') +TCS34725IntegrationTime = tcs34725_ns.enum("TCS34725IntegrationTime") TCS34725_INTEGRATION_TIMES = { - '2.4ms': TCS34725IntegrationTime.TCS34725_INTEGRATION_TIME_2_4MS, - '24ms': TCS34725IntegrationTime.TCS34725_INTEGRATION_TIME_24MS, - '50ms': TCS34725IntegrationTime.TCS34725_INTEGRATION_TIME_50MS, - '101ms': TCS34725IntegrationTime.TCS34725_INTEGRATION_TIME_101MS, - '154ms': TCS34725IntegrationTime.TCS34725_INTEGRATION_TIME_154MS, - '700ms': TCS34725IntegrationTime.TCS34725_INTEGRATION_TIME_700MS, + "2.4ms": TCS34725IntegrationTime.TCS34725_INTEGRATION_TIME_2_4MS, + "24ms": TCS34725IntegrationTime.TCS34725_INTEGRATION_TIME_24MS, + "50ms": TCS34725IntegrationTime.TCS34725_INTEGRATION_TIME_50MS, + "101ms": TCS34725IntegrationTime.TCS34725_INTEGRATION_TIME_101MS, + "154ms": TCS34725IntegrationTime.TCS34725_INTEGRATION_TIME_154MS, + "700ms": TCS34725IntegrationTime.TCS34725_INTEGRATION_TIME_700MS, } -TCS34725Gain = tcs34725_ns.enum('TCS34725Gain') +TCS34725Gain = tcs34725_ns.enum("TCS34725Gain") TCS34725_GAINS = { - '1X': TCS34725Gain.TCS34725_GAIN_1X, - '4X': TCS34725Gain.TCS34725_GAIN_4X, - '16X': TCS34725Gain.TCS34725_GAIN_16X, - '60X': TCS34725Gain.TCS34725_GAIN_60X, + "1X": TCS34725Gain.TCS34725_GAIN_1X, + "4X": TCS34725Gain.TCS34725_GAIN_4X, + "16X": TCS34725Gain.TCS34725_GAIN_16X, + "60X": TCS34725Gain.TCS34725_GAIN_60X, } -color_channel_schema = sensor.sensor_schema(UNIT_PERCENT, ICON_LIGHTBULB, 1, DEVICE_CLASS_EMPTY) -color_temperature_schema = sensor.sensor_schema(UNIT_KELVIN, ICON_THERMOMETER, 1, - DEVICE_CLASS_EMPTY) -illuminance_schema = sensor.sensor_schema(UNIT_LUX, ICON_EMPTY, 1, DEVICE_CLASS_ILLUMINANCE) +color_channel_schema = sensor.sensor_schema( + UNIT_PERCENT, ICON_LIGHTBULB, 1, DEVICE_CLASS_EMPTY +) +color_temperature_schema = sensor.sensor_schema( + UNIT_KELVIN, ICON_THERMOMETER, 1, DEVICE_CLASS_EMPTY +) +illuminance_schema = sensor.sensor_schema( + UNIT_LUX, ICON_EMPTY, 1, DEVICE_CLASS_ILLUMINANCE +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(TCS34725Component), - cv.Optional(CONF_RED_CHANNEL): color_channel_schema, - cv.Optional(CONF_GREEN_CHANNEL): color_channel_schema, - cv.Optional(CONF_BLUE_CHANNEL): color_channel_schema, - cv.Optional(CONF_CLEAR_CHANNEL): color_channel_schema, - cv.Optional(CONF_ILLUMINANCE): illuminance_schema, - cv.Optional(CONF_COLOR_TEMPERATURE): color_temperature_schema, - cv.Optional(CONF_INTEGRATION_TIME, default='2.4ms'): - cv.enum(TCS34725_INTEGRATION_TIMES, lower=True), - cv.Optional(CONF_GAIN, default='1X'): cv.enum(TCS34725_GAINS, upper=True), -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x29)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(TCS34725Component), + cv.Optional(CONF_RED_CHANNEL): color_channel_schema, + cv.Optional(CONF_GREEN_CHANNEL): color_channel_schema, + cv.Optional(CONF_BLUE_CHANNEL): color_channel_schema, + cv.Optional(CONF_CLEAR_CHANNEL): color_channel_schema, + cv.Optional(CONF_ILLUMINANCE): illuminance_schema, + cv.Optional(CONF_COLOR_TEMPERATURE): color_temperature_schema, + cv.Optional(CONF_INTEGRATION_TIME, default="2.4ms"): cv.enum( + TCS34725_INTEGRATION_TIMES, lower=True + ), + cv.Optional(CONF_GAIN, default="1X"): cv.enum(TCS34725_GAINS, upper=True), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x29)) +) def to_code(config): diff --git a/esphome/components/teleinfo/__init__.py b/esphome/components/teleinfo/__init__.py index 00ca59227..2e279e892 100644 --- a/esphome/components/teleinfo/__init__.py +++ b/esphome/components/teleinfo/__init__.py @@ -1 +1 @@ -CODEOWNERS = ['@0hax'] +CODEOWNERS = ["@0hax"] diff --git a/esphome/components/teleinfo/sensor.py b/esphome/components/teleinfo/sensor.py index 600464aa2..9f6c2c8e8 100644 --- a/esphome/components/teleinfo/sensor.py +++ b/esphome/components/teleinfo/sensor.py @@ -1,27 +1,42 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, uart -from esphome.const import CONF_ID, CONF_SENSOR, DEVICE_CLASS_POWER, ICON_EMPTY, UNIT_WATT_HOURS +from esphome.const import ( + CONF_ID, + CONF_SENSOR, + DEVICE_CLASS_POWER, + ICON_EMPTY, + UNIT_WATT_HOURS, +) -DEPENDENCIES = ['uart'] +DEPENDENCIES = ["uart"] -teleinfo_ns = cg.esphome_ns.namespace('teleinfo') -TeleInfo = teleinfo_ns.class_('TeleInfo', cg.PollingComponent, uart.UARTDevice) +teleinfo_ns = cg.esphome_ns.namespace("teleinfo") +TeleInfo = teleinfo_ns.class_("TeleInfo", cg.PollingComponent, uart.UARTDevice) CONF_TAG_NAME = "tag_name" -TELEINFO_TAG_SCHEMA = cv.Schema({ - cv.Required(CONF_TAG_NAME): cv.string, - cv.Required(CONF_SENSOR): sensor.sensor_schema(UNIT_WATT_HOURS, ICON_EMPTY, 0, - DEVICE_CLASS_POWER) -}) +TELEINFO_TAG_SCHEMA = cv.Schema( + { + cv.Required(CONF_TAG_NAME): cv.string, + cv.Required(CONF_SENSOR): sensor.sensor_schema( + UNIT_WATT_HOURS, ICON_EMPTY, 0, DEVICE_CLASS_POWER + ), + } +) CONF_TAGS = "tags" CONF_HISTORICAL_MODE = "historical_mode" -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(TeleInfo), - cv.Optional(CONF_HISTORICAL_MODE, default=False): cv.boolean, - cv.Optional(CONF_TAGS): cv.ensure_list(TELEINFO_TAG_SCHEMA), -}).extend(cv.polling_component_schema('60s')).extend(uart.UART_DEVICE_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(TeleInfo), + cv.Optional(CONF_HISTORICAL_MODE, default=False): cv.boolean, + cv.Optional(CONF_TAGS): cv.ensure_list(TELEINFO_TAG_SCHEMA), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(uart.UART_DEVICE_SCHEMA) +) def to_code(config): diff --git a/esphome/components/template/__init__.py b/esphome/components/template/__init__.py index 44c59260d..6253af909 100644 --- a/esphome/components/template/__init__.py +++ b/esphome/components/template/__init__.py @@ -1,3 +1,3 @@ import esphome.codegen as cg -template_ns = cg.esphome_ns.namespace('template_') +template_ns = cg.esphome_ns.namespace("template_") diff --git a/esphome/components/template/binary_sensor/__init__.py b/esphome/components/template/binary_sensor/__init__.py index 14f9f23ec..d23e6423a 100644 --- a/esphome/components/template/binary_sensor/__init__.py +++ b/esphome/components/template/binary_sensor/__init__.py @@ -5,13 +5,16 @@ from esphome.components import binary_sensor from esphome.const import CONF_ID, CONF_LAMBDA, CONF_STATE from .. import template_ns -TemplateBinarySensor = template_ns.class_('TemplateBinarySensor', binary_sensor.BinarySensor, - cg.Component) +TemplateBinarySensor = template_ns.class_( + "TemplateBinarySensor", binary_sensor.BinarySensor, cg.Component +) -CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(TemplateBinarySensor), - cv.Optional(CONF_LAMBDA): cv.returning_lambda, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(TemplateBinarySensor), + cv.Optional(CONF_LAMBDA): cv.returning_lambda, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): @@ -20,17 +23,22 @@ def to_code(config): yield binary_sensor.register_binary_sensor(var, config) if CONF_LAMBDA in config: - template_ = yield cg.process_lambda(config[CONF_LAMBDA], [], - return_type=cg.optional.template(bool)) + template_ = yield cg.process_lambda( + config[CONF_LAMBDA], [], return_type=cg.optional.template(bool) + ) cg.add(var.set_template(template_)) -@automation.register_action('binary_sensor.template.publish', - binary_sensor.BinarySensorPublishAction, - cv.Schema({ - cv.Required(CONF_ID): cv.use_id(binary_sensor.BinarySensor), - cv.Required(CONF_STATE): cv.templatable(cv.boolean), - })) +@automation.register_action( + "binary_sensor.template.publish", + binary_sensor.BinarySensorPublishAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(binary_sensor.BinarySensor), + cv.Required(CONF_STATE): cv.templatable(cv.boolean), + } + ), +) def binary_sensor_template_publish_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) diff --git a/esphome/components/template/cover/__init__.py b/esphome/components/template/cover/__init__.py index 607d9d006..0c81e095b 100644 --- a/esphome/components/template/cover/__init__.py +++ b/esphome/components/template/cover/__init__.py @@ -2,37 +2,54 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.components import cover -from esphome.const import CONF_ASSUMED_STATE, CONF_CLOSE_ACTION, CONF_CURRENT_OPERATION, CONF_ID, \ - CONF_LAMBDA, CONF_OPEN_ACTION, CONF_OPTIMISTIC, CONF_POSITION, CONF_RESTORE_MODE, \ - CONF_STATE, CONF_STOP_ACTION, CONF_TILT, CONF_TILT_ACTION, CONF_TILT_LAMBDA, \ - CONF_POSITION_ACTION +from esphome.const import ( + CONF_ASSUMED_STATE, + CONF_CLOSE_ACTION, + CONF_CURRENT_OPERATION, + CONF_ID, + CONF_LAMBDA, + CONF_OPEN_ACTION, + CONF_OPTIMISTIC, + CONF_POSITION, + CONF_RESTORE_MODE, + CONF_STATE, + CONF_STOP_ACTION, + CONF_TILT, + CONF_TILT_ACTION, + CONF_TILT_LAMBDA, + CONF_POSITION_ACTION, +) from .. import template_ns -TemplateCover = template_ns.class_('TemplateCover', cover.Cover, cg.Component) +TemplateCover = template_ns.class_("TemplateCover", cover.Cover, cg.Component) -TemplateCoverRestoreMode = template_ns.enum('TemplateCoverRestoreMode') +TemplateCoverRestoreMode = template_ns.enum("TemplateCoverRestoreMode") RESTORE_MODES = { - 'NO_RESTORE': TemplateCoverRestoreMode.COVER_NO_RESTORE, - 'RESTORE': TemplateCoverRestoreMode.COVER_RESTORE, - 'RESTORE_AND_CALL': TemplateCoverRestoreMode.COVER_RESTORE_AND_CALL, + "NO_RESTORE": TemplateCoverRestoreMode.COVER_NO_RESTORE, + "RESTORE": TemplateCoverRestoreMode.COVER_RESTORE, + "RESTORE_AND_CALL": TemplateCoverRestoreMode.COVER_RESTORE_AND_CALL, } -CONF_HAS_POSITION = 'has_position' +CONF_HAS_POSITION = "has_position" -CONFIG_SCHEMA = cover.COVER_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(TemplateCover), - cv.Optional(CONF_LAMBDA): cv.returning_lambda, - cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean, - cv.Optional(CONF_ASSUMED_STATE, default=False): cv.boolean, - cv.Optional(CONF_HAS_POSITION, default=False): cv.boolean, - cv.Optional(CONF_OPEN_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_CLOSE_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_STOP_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_TILT_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_TILT_LAMBDA): cv.returning_lambda, - cv.Optional(CONF_POSITION_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_RESTORE_MODE, default='RESTORE'): cv.enum(RESTORE_MODES, upper=True), -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cover.COVER_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(TemplateCover), + cv.Optional(CONF_LAMBDA): cv.returning_lambda, + cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean, + cv.Optional(CONF_ASSUMED_STATE, default=False): cv.boolean, + cv.Optional(CONF_HAS_POSITION, default=False): cv.boolean, + cv.Optional(CONF_OPEN_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_CLOSE_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_STOP_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_TILT_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_TILT_LAMBDA): cv.returning_lambda, + cv.Optional(CONF_POSITION_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_RESTORE_MODE, default="RESTORE"): cv.enum( + RESTORE_MODES, upper=True + ), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): @@ -40,26 +57,36 @@ def to_code(config): yield cg.register_component(var, config) yield cover.register_cover(var, config) if CONF_LAMBDA in config: - template_ = yield cg.process_lambda(config[CONF_LAMBDA], [], - return_type=cg.optional.template(float)) + template_ = yield cg.process_lambda( + config[CONF_LAMBDA], [], return_type=cg.optional.template(float) + ) cg.add(var.set_state_lambda(template_)) if CONF_OPEN_ACTION in config: - yield automation.build_automation(var.get_open_trigger(), [], config[CONF_OPEN_ACTION]) + yield automation.build_automation( + var.get_open_trigger(), [], config[CONF_OPEN_ACTION] + ) if CONF_CLOSE_ACTION in config: - 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_STOP_ACTION in 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] + ) if CONF_TILT_ACTION in config: - yield automation.build_automation(var.get_tilt_trigger(), [(float, 'tilt')], - config[CONF_TILT_ACTION]) + yield automation.build_automation( + var.get_tilt_trigger(), [(float, "tilt")], config[CONF_TILT_ACTION] + ) cg.add(var.set_has_tilt(True)) if CONF_TILT_LAMBDA in config: - tilt_template_ = yield cg.process_lambda(config[CONF_TILT_LAMBDA], [], - return_type=cg.optional.template(float)) + tilt_template_ = yield cg.process_lambda( + config[CONF_TILT_LAMBDA], [], return_type=cg.optional.template(float) + ) cg.add(var.set_tilt_lambda(tilt_template_)) if CONF_POSITION_ACTION in config: - yield automation.build_automation(var.get_position_trigger(), [(float, 'pos')], - config[CONF_POSITION_ACTION]) + yield automation.build_automation( + var.get_position_trigger(), [(float, "pos")], config[CONF_POSITION_ACTION] + ) cg.add(var.set_has_position(True)) else: cg.add(var.set_has_position(config[CONF_HAS_POSITION])) @@ -68,13 +95,21 @@ def to_code(config): cg.add(var.set_restore_mode(config[CONF_RESTORE_MODE])) -@automation.register_action('cover.template.publish', cover.CoverPublishAction, cv.Schema({ - cv.Required(CONF_ID): cv.use_id(cover.Cover), - cv.Exclusive(CONF_STATE, 'pos'): cv.templatable(cover.validate_cover_state), - cv.Exclusive(CONF_POSITION, 'pos'): cv.templatable(cv.zero_to_one_float), - cv.Optional(CONF_CURRENT_OPERATION): cv.templatable(cover.validate_cover_operation), - cv.Optional(CONF_TILT): cv.templatable(cv.zero_to_one_float), -})) +@automation.register_action( + "cover.template.publish", + cover.CoverPublishAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(cover.Cover), + cv.Exclusive(CONF_STATE, "pos"): cv.templatable(cover.validate_cover_state), + cv.Exclusive(CONF_POSITION, "pos"): cv.templatable(cv.zero_to_one_float), + cv.Optional(CONF_CURRENT_OPERATION): cv.templatable( + cover.validate_cover_operation + ), + cv.Optional(CONF_TILT): cv.templatable(cv.zero_to_one_float), + } + ), +) def cover_template_publish_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) @@ -88,6 +123,8 @@ def cover_template_publish_to_code(config, action_id, template_arg, args): template_ = yield cg.templatable(config[CONF_TILT], args, float) cg.add(var.set_tilt(template_)) if CONF_CURRENT_OPERATION in config: - template_ = yield cg.templatable(config[CONF_CURRENT_OPERATION], args, cover.CoverOperation) + template_ = yield cg.templatable( + config[CONF_CURRENT_OPERATION], args, cover.CoverOperation + ) cg.add(var.set_current_operation(template_)) yield var diff --git a/esphome/components/template/output/__init__.py b/esphome/components/template/output/__init__.py index cc85a9da6..61286772d 100644 --- a/esphome/components/template/output/__init__.py +++ b/esphome/components/template/output/__init__.py @@ -5,30 +5,43 @@ from esphome.components import output from esphome.const import CONF_ID, CONF_TYPE, CONF_BINARY from .. import template_ns -TemplateBinaryOutput = template_ns.class_('TemplateBinaryOutput', output.BinaryOutput) -TemplateFloatOutput = template_ns.class_('TemplateFloatOutput', output.FloatOutput) +TemplateBinaryOutput = template_ns.class_("TemplateBinaryOutput", output.BinaryOutput) +TemplateFloatOutput = template_ns.class_("TemplateFloatOutput", output.FloatOutput) -CONF_FLOAT = 'float' -CONF_WRITE_ACTION = 'write_action' +CONF_FLOAT = "float" +CONF_WRITE_ACTION = "write_action" -CONFIG_SCHEMA = cv.typed_schema({ - CONF_BINARY: output.BINARY_OUTPUT_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(TemplateBinaryOutput), - cv.Required(CONF_WRITE_ACTION): automation.validate_automation(single=True), - }), - CONF_FLOAT: output.FLOAT_OUTPUT_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(TemplateFloatOutput), - cv.Required(CONF_WRITE_ACTION): automation.validate_automation(single=True), - }), -}, lower=True) +CONFIG_SCHEMA = cv.typed_schema( + { + CONF_BINARY: output.BINARY_OUTPUT_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(TemplateBinaryOutput), + cv.Required(CONF_WRITE_ACTION): automation.validate_automation( + single=True + ), + } + ), + CONF_FLOAT: output.FLOAT_OUTPUT_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(TemplateFloatOutput), + cv.Required(CONF_WRITE_ACTION): automation.validate_automation( + single=True + ), + } + ), + }, + lower=True, +) def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) if config[CONF_TYPE] == CONF_BINARY: - yield automation.build_automation(var.get_trigger(), [(bool, 'state')], - config[CONF_WRITE_ACTION]) + yield automation.build_automation( + var.get_trigger(), [(bool, "state")], config[CONF_WRITE_ACTION] + ) else: - yield automation.build_automation(var.get_trigger(), [(float, 'state')], - config[CONF_WRITE_ACTION]) + yield automation.build_automation( + var.get_trigger(), [(float, "state")], config[CONF_WRITE_ACTION] + ) yield output.register_output(var, config) diff --git a/esphome/components/template/sensor/__init__.py b/esphome/components/template/sensor/__init__.py index 7ebfc1047..21ef5db32 100644 --- a/esphome/components/template/sensor/__init__.py +++ b/esphome/components/template/sensor/__init__.py @@ -2,16 +2,30 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.components import sensor -from esphome.const import CONF_ID, CONF_LAMBDA, CONF_STATE, DEVICE_CLASS_EMPTY, UNIT_EMPTY, \ - ICON_EMPTY +from esphome.const import ( + CONF_ID, + CONF_LAMBDA, + CONF_STATE, + DEVICE_CLASS_EMPTY, + UNIT_EMPTY, + ICON_EMPTY, +) from .. import template_ns -TemplateSensor = template_ns.class_('TemplateSensor', sensor.Sensor, cg.PollingComponent) +TemplateSensor = template_ns.class_( + "TemplateSensor", sensor.Sensor, cg.PollingComponent +) -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_EMPTY, ICON_EMPTY, 1, DEVICE_CLASS_EMPTY).extend({ - cv.GenerateID(): cv.declare_id(TemplateSensor), - cv.Optional(CONF_LAMBDA): cv.returning_lambda, -}).extend(cv.polling_component_schema('60s')) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_EMPTY, ICON_EMPTY, 1, DEVICE_CLASS_EMPTY) + .extend( + { + cv.GenerateID(): cv.declare_id(TemplateSensor), + cv.Optional(CONF_LAMBDA): cv.returning_lambda, + } + ) + .extend(cv.polling_component_schema("60s")) +) def to_code(config): @@ -20,16 +34,22 @@ def to_code(config): yield sensor.register_sensor(var, config) if CONF_LAMBDA in config: - template_ = yield cg.process_lambda(config[CONF_LAMBDA], [], - return_type=cg.optional.template(float)) + template_ = yield cg.process_lambda( + config[CONF_LAMBDA], [], return_type=cg.optional.template(float) + ) cg.add(var.set_template(template_)) -@automation.register_action('sensor.template.publish', sensor.SensorPublishAction, - cv.Schema({ - cv.Required(CONF_ID): cv.use_id(sensor.Sensor), - cv.Required(CONF_STATE): cv.templatable(cv.float_), - })) +@automation.register_action( + "sensor.template.publish", + sensor.SensorPublishAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(sensor.Sensor), + cv.Required(CONF_STATE): cv.templatable(cv.float_), + } + ), +) def sensor_template_publish_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) diff --git a/esphome/components/template/switch/__init__.py b/esphome/components/template/switch/__init__.py index 783f5a192..7698e4f2a 100644 --- a/esphome/components/template/switch/__init__.py +++ b/esphome/components/template/switch/__init__.py @@ -2,21 +2,31 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.components import switch -from esphome.const import CONF_ASSUMED_STATE, CONF_ID, CONF_LAMBDA, CONF_OPTIMISTIC, \ - CONF_RESTORE_STATE, CONF_STATE, CONF_TURN_OFF_ACTION, CONF_TURN_ON_ACTION +from esphome.const import ( + CONF_ASSUMED_STATE, + CONF_ID, + CONF_LAMBDA, + CONF_OPTIMISTIC, + CONF_RESTORE_STATE, + CONF_STATE, + CONF_TURN_OFF_ACTION, + CONF_TURN_ON_ACTION, +) from .. import template_ns -TemplateSwitch = template_ns.class_('TemplateSwitch', switch.Switch, cg.Component) +TemplateSwitch = template_ns.class_("TemplateSwitch", switch.Switch, cg.Component) -CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(TemplateSwitch), - cv.Optional(CONF_LAMBDA): cv.returning_lambda, - cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean, - cv.Optional(CONF_ASSUMED_STATE, default=False): cv.boolean, - cv.Optional(CONF_TURN_OFF_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_TURN_ON_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_RESTORE_STATE, default=False): cv.boolean, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(TemplateSwitch), + cv.Optional(CONF_LAMBDA): cv.returning_lambda, + cv.Optional(CONF_OPTIMISTIC, default=False): cv.boolean, + cv.Optional(CONF_ASSUMED_STATE, default=False): cv.boolean, + cv.Optional(CONF_TURN_OFF_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_TURN_ON_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_RESTORE_STATE, default=False): cv.boolean, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): @@ -25,24 +35,33 @@ def to_code(config): yield switch.register_switch(var, config) if CONF_LAMBDA in config: - template_ = yield cg.process_lambda(config[CONF_LAMBDA], [], - return_type=cg.optional.template(bool)) + template_ = yield cg.process_lambda( + config[CONF_LAMBDA], [], return_type=cg.optional.template(bool) + ) cg.add(var.set_state_lambda(template_)) if CONF_TURN_OFF_ACTION in config: - yield automation.build_automation(var.get_turn_off_trigger(), [], - config[CONF_TURN_OFF_ACTION]) + yield automation.build_automation( + var.get_turn_off_trigger(), [], config[CONF_TURN_OFF_ACTION] + ) if CONF_TURN_ON_ACTION in config: - yield automation.build_automation(var.get_turn_on_trigger(), [], - config[CONF_TURN_ON_ACTION]) + yield automation.build_automation( + var.get_turn_on_trigger(), [], config[CONF_TURN_ON_ACTION] + ) cg.add(var.set_optimistic(config[CONF_OPTIMISTIC])) cg.add(var.set_assumed_state(config[CONF_ASSUMED_STATE])) cg.add(var.set_restore_state(config[CONF_RESTORE_STATE])) -@automation.register_action('switch.template.publish', switch.SwitchPublishAction, cv.Schema({ - cv.Required(CONF_ID): cv.use_id(switch.Switch), - cv.Required(CONF_STATE): cv.templatable(cv.boolean), -})) +@automation.register_action( + "switch.template.publish", + switch.SwitchPublishAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(switch.Switch), + cv.Required(CONF_STATE): cv.templatable(cv.boolean), + } + ), +) def switch_template_publish_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) diff --git a/esphome/components/template/text_sensor/__init__.py b/esphome/components/template/text_sensor/__init__.py index dae99dc9b..cae00e393 100644 --- a/esphome/components/template/text_sensor/__init__.py +++ b/esphome/components/template/text_sensor/__init__.py @@ -6,13 +6,16 @@ from esphome.components.text_sensor import TextSensorPublishAction from esphome.const import CONF_ID, CONF_LAMBDA, CONF_STATE from .. import template_ns -TemplateTextSensor = template_ns.class_('TemplateTextSensor', text_sensor.TextSensor, - cg.PollingComponent) +TemplateTextSensor = template_ns.class_( + "TemplateTextSensor", text_sensor.TextSensor, cg.PollingComponent +) -CONFIG_SCHEMA = text_sensor.TEXT_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(TemplateTextSensor), - cv.Optional(CONF_LAMBDA): cv.returning_lambda, -}).extend(cv.polling_component_schema('60s')) +CONFIG_SCHEMA = text_sensor.TEXT_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(TemplateTextSensor), + cv.Optional(CONF_LAMBDA): cv.returning_lambda, + } +).extend(cv.polling_component_schema("60s")) def to_code(config): @@ -21,15 +24,22 @@ def to_code(config): yield text_sensor.register_text_sensor(var, config) if CONF_LAMBDA in config: - template_ = yield cg.process_lambda(config[CONF_LAMBDA], [], - return_type=cg.optional.template(cg.std_string)) + template_ = yield cg.process_lambda( + config[CONF_LAMBDA], [], return_type=cg.optional.template(cg.std_string) + ) cg.add(var.set_template(template_)) -@automation.register_action('text_sensor.template.publish', TextSensorPublishAction, cv.Schema({ - cv.Required(CONF_ID): cv.use_id(text_sensor.TextSensor), - cv.Required(CONF_STATE): cv.templatable(cv.string_strict), -})) +@automation.register_action( + "text_sensor.template.publish", + TextSensorPublishAction, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(text_sensor.TextSensor), + cv.Required(CONF_STATE): cv.templatable(cv.string_strict), + } + ), +) def text_sensor_template_publish_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) diff --git a/esphome/components/text_sensor/__init__.py b/esphome/components/text_sensor/__init__.py index f138f38d2..ff73889d6 100644 --- a/esphome/components/text_sensor/__init__.py +++ b/esphome/components/text_sensor/__init__.py @@ -2,31 +2,48 @@ 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_ICON, CONF_ID, CONF_INTERNAL, CONF_ON_VALUE, \ - CONF_TRIGGER_ID, CONF_MQTT_ID, CONF_NAME, CONF_STATE +from esphome.const import ( + CONF_ICON, + CONF_ID, + CONF_INTERNAL, + CONF_ON_VALUE, + CONF_TRIGGER_ID, + CONF_MQTT_ID, + CONF_NAME, + CONF_STATE, +) from esphome.core import CORE, coroutine, coroutine_with_priority IS_PLATFORM_COMPONENT = True # pylint: disable=invalid-name -text_sensor_ns = cg.esphome_ns.namespace('text_sensor') -TextSensor = text_sensor_ns.class_('TextSensor', cg.Nameable) -TextSensorPtr = TextSensor.operator('ptr') +text_sensor_ns = cg.esphome_ns.namespace("text_sensor") +TextSensor = text_sensor_ns.class_("TextSensor", cg.Nameable) +TextSensorPtr = TextSensor.operator("ptr") -TextSensorStateTrigger = text_sensor_ns.class_('TextSensorStateTrigger', - automation.Trigger.template(cg.std_string)) -TextSensorPublishAction = text_sensor_ns.class_('TextSensorPublishAction', automation.Action) -TextSensorStateCondition = text_sensor_ns.class_('TextSensorStateCondition', automation.Condition) +TextSensorStateTrigger = text_sensor_ns.class_( + "TextSensorStateTrigger", automation.Trigger.template(cg.std_string) +) +TextSensorPublishAction = text_sensor_ns.class_( + "TextSensorPublishAction", automation.Action +) +TextSensorStateCondition = text_sensor_ns.class_( + "TextSensorStateCondition", automation.Condition +) icon = cv.icon -TEXT_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({ - cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTTextSensor), - cv.Optional(CONF_ICON): icon, - cv.Optional(CONF_ON_VALUE): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TextSensorStateTrigger), - }), -}) +TEXT_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend( + { + cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id(mqtt.MQTTTextSensor), + cv.Optional(CONF_ICON): icon, + cv.Optional(CONF_ON_VALUE): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TextSensorStateTrigger), + } + ), + } +) @coroutine @@ -39,7 +56,7 @@ def setup_text_sensor_core_(var, config): for conf in config.get(CONF_ON_VALUE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) - yield automation.build_automation(trigger, [(cg.std_string, 'x')], conf) + yield automation.build_automation(trigger, [(cg.std_string, "x")], conf) if CONF_MQTT_ID in config: mqtt_ = cg.new_Pvariable(config[CONF_MQTT_ID], var) @@ -56,14 +73,20 @@ def register_text_sensor(var, config): @coroutine_with_priority(100.0) def to_code(config): - cg.add_define('USE_TEXT_SENSOR') + cg.add_define("USE_TEXT_SENSOR") cg.add_global(text_sensor_ns.using) -@automation.register_condition('text_sensor.state', TextSensorStateCondition, cv.Schema({ - cv.Required(CONF_ID): cv.use_id(TextSensor), - cv.Required(CONF_STATE): cv.templatable(cv.string_strict), -})) +@automation.register_condition( + "text_sensor.state", + TextSensorStateCondition, + cv.Schema( + { + cv.Required(CONF_ID): cv.use_id(TextSensor), + cv.Required(CONF_STATE): cv.templatable(cv.string_strict), + } + ), +) def text_sensor_state_to_code(config, condition_id, template_arg, args): paren = yield cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(condition_id, template_arg, paren) diff --git a/esphome/components/thermostat/climate.py b/esphome/components/thermostat/climate.py index bd8633ee1..04584583a 100644 --- a/esphome/components/thermostat/climate.py +++ b/esphome/components/thermostat/climate.py @@ -2,109 +2,224 @@ 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_AUTO_MODE, CONF_AWAY_CONFIG, CONF_COOL_ACTION, CONF_COOL_MODE, \ - CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_DRY_ACTION, \ - CONF_DRY_MODE, CONF_FAN_MODE_ON_ACTION, CONF_FAN_MODE_OFF_ACTION, CONF_FAN_MODE_AUTO_ACTION, \ - CONF_FAN_MODE_LOW_ACTION, CONF_FAN_MODE_MEDIUM_ACTION, CONF_FAN_MODE_HIGH_ACTION, \ - CONF_FAN_MODE_MIDDLE_ACTION, CONF_FAN_MODE_FOCUS_ACTION, CONF_FAN_MODE_DIFFUSE_ACTION, \ - CONF_FAN_ONLY_ACTION, CONF_FAN_ONLY_MODE, CONF_HEAT_ACTION, CONF_HEAT_MODE, CONF_HYSTERESIS, \ - CONF_ID, CONF_IDLE_ACTION, CONF_OFF_MODE, CONF_SENSOR, CONF_SWING_BOTH_ACTION, \ - CONF_SWING_HORIZONTAL_ACTION, CONF_SWING_OFF_ACTION, CONF_SWING_VERTICAL_ACTION +from esphome.const import ( + CONF_AUTO_MODE, + CONF_AWAY_CONFIG, + CONF_COOL_ACTION, + CONF_COOL_MODE, + CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, + CONF_DEFAULT_TARGET_TEMPERATURE_LOW, + CONF_DRY_ACTION, + CONF_DRY_MODE, + CONF_FAN_MODE_ON_ACTION, + CONF_FAN_MODE_OFF_ACTION, + CONF_FAN_MODE_AUTO_ACTION, + CONF_FAN_MODE_LOW_ACTION, + CONF_FAN_MODE_MEDIUM_ACTION, + CONF_FAN_MODE_HIGH_ACTION, + CONF_FAN_MODE_MIDDLE_ACTION, + CONF_FAN_MODE_FOCUS_ACTION, + CONF_FAN_MODE_DIFFUSE_ACTION, + CONF_FAN_ONLY_ACTION, + CONF_FAN_ONLY_MODE, + CONF_HEAT_ACTION, + CONF_HEAT_MODE, + CONF_HYSTERESIS, + CONF_ID, + CONF_IDLE_ACTION, + CONF_OFF_MODE, + CONF_SENSOR, + CONF_SWING_BOTH_ACTION, + CONF_SWING_HORIZONTAL_ACTION, + CONF_SWING_OFF_ACTION, + CONF_SWING_VERTICAL_ACTION, +) -CODEOWNERS = ['@kbx81'] +CODEOWNERS = ["@kbx81"] -thermostat_ns = cg.esphome_ns.namespace('thermostat') -ThermostatClimate = thermostat_ns.class_('ThermostatClimate', climate.Climate, cg.Component) -ThermostatClimateTargetTempConfig = thermostat_ns.struct('ThermostatClimateTargetTempConfig') +thermostat_ns = cg.esphome_ns.namespace("thermostat") +ThermostatClimate = thermostat_ns.class_( + "ThermostatClimate", climate.Climate, cg.Component +) +ThermostatClimateTargetTempConfig = thermostat_ns.struct( + "ThermostatClimateTargetTempConfig" +) def validate_thermostat(config): # verify corresponding climate action action exists for any defined climate mode action if CONF_COOL_MODE in config and CONF_COOL_ACTION not in config: - raise cv.Invalid("{} must be defined to use {}".format(CONF_COOL_ACTION, CONF_COOL_MODE)) + raise cv.Invalid( + "{} must be defined to use {}".format(CONF_COOL_ACTION, CONF_COOL_MODE) + ) if CONF_DRY_MODE in config and CONF_DRY_ACTION not in config: - raise cv.Invalid("{} must be defined to use {}".format(CONF_DRY_ACTION, CONF_DRY_MODE)) + raise cv.Invalid( + "{} must be defined to use {}".format(CONF_DRY_ACTION, CONF_DRY_MODE) + ) if CONF_FAN_ONLY_MODE in config and CONF_FAN_ONLY_ACTION not in config: - raise cv.Invalid("{} must be defined to use {}".format(CONF_FAN_ONLY_ACTION, - CONF_FAN_ONLY_MODE)) + raise cv.Invalid( + "{} must be defined to use {}".format( + CONF_FAN_ONLY_ACTION, CONF_FAN_ONLY_MODE + ) + ) if CONF_HEAT_MODE in config and CONF_HEAT_ACTION not in config: - raise cv.Invalid("{} must be defined to use {}".format(CONF_HEAT_ACTION, CONF_HEAT_MODE)) + raise cv.Invalid( + "{} must be defined to use {}".format(CONF_HEAT_ACTION, CONF_HEAT_MODE) + ) # verify corresponding default target temperature exists when a given climate action exists - if CONF_DEFAULT_TARGET_TEMPERATURE_HIGH not in config and (CONF_COOL_ACTION in config - or CONF_FAN_ONLY_ACTION in config): - raise cv.Invalid("{} must be defined when using {} or {}".format( - CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, CONF_COOL_ACTION, CONF_FAN_ONLY_ACTION)) + if CONF_DEFAULT_TARGET_TEMPERATURE_HIGH not in config and ( + CONF_COOL_ACTION in config or CONF_FAN_ONLY_ACTION in config + ): + raise cv.Invalid( + "{} must be defined when using {} or {}".format( + CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, + CONF_COOL_ACTION, + CONF_FAN_ONLY_ACTION, + ) + ) if CONF_DEFAULT_TARGET_TEMPERATURE_LOW not in config and CONF_HEAT_ACTION in config: - raise cv.Invalid("{} must be defined when using {}".format( - CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION)) + raise cv.Invalid( + "{} must be defined when using {}".format( + CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION + ) + ) # if a given climate action is NOT defined, it should not have a default target temperature - if CONF_DEFAULT_TARGET_TEMPERATURE_HIGH in config and (CONF_COOL_ACTION not in config - and CONF_FAN_ONLY_ACTION not in config): - raise cv.Invalid("{} is defined with no {}".format( - CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, CONF_COOL_ACTION)) + if CONF_DEFAULT_TARGET_TEMPERATURE_HIGH in config and ( + CONF_COOL_ACTION not in config and CONF_FAN_ONLY_ACTION not in config + ): + raise cv.Invalid( + "{} is defined with no {}".format( + CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, CONF_COOL_ACTION + ) + ) if CONF_DEFAULT_TARGET_TEMPERATURE_LOW in config and CONF_HEAT_ACTION not in config: - raise cv.Invalid("{} is defined with no {}".format( - CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION)) + raise cv.Invalid( + "{} is defined with no {}".format( + CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION + ) + ) if CONF_AWAY_CONFIG in config: away = config[CONF_AWAY_CONFIG] # verify corresponding default target temperature exists when a given climate action exists - if CONF_DEFAULT_TARGET_TEMPERATURE_HIGH not in away and (CONF_COOL_ACTION in config or - CONF_FAN_ONLY_ACTION in config): - raise cv.Invalid("{} must be defined in away configuration when using {} or {}".format( - CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, CONF_COOL_ACTION, CONF_FAN_ONLY_ACTION)) - if CONF_DEFAULT_TARGET_TEMPERATURE_LOW not in away and CONF_HEAT_ACTION in config: - raise cv.Invalid("{} must be defined in away configuration when using {}".format( - CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION)) + if CONF_DEFAULT_TARGET_TEMPERATURE_HIGH not in away and ( + CONF_COOL_ACTION in config or CONF_FAN_ONLY_ACTION in config + ): + raise cv.Invalid( + "{} must be defined in away configuration when using {} or {}".format( + CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, + CONF_COOL_ACTION, + CONF_FAN_ONLY_ACTION, + ) + ) + if ( + CONF_DEFAULT_TARGET_TEMPERATURE_LOW not in away + and CONF_HEAT_ACTION in config + ): + raise cv.Invalid( + "{} must be defined in away configuration when using {}".format( + CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION + ) + ) # if a given climate action is NOT defined, it should not have a default target temperature - if CONF_DEFAULT_TARGET_TEMPERATURE_HIGH in away and (CONF_COOL_ACTION not in config and - CONF_FAN_ONLY_ACTION not in config): - raise cv.Invalid("{} is defined in away configuration with no {} or {}".format( - CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, CONF_COOL_ACTION, CONF_FAN_ONLY_ACTION)) - if CONF_DEFAULT_TARGET_TEMPERATURE_LOW in away and CONF_HEAT_ACTION not in config: - raise cv.Invalid("{} is defined in away configuration with no {}".format( - CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION)) + if CONF_DEFAULT_TARGET_TEMPERATURE_HIGH in away and ( + CONF_COOL_ACTION not in config and CONF_FAN_ONLY_ACTION not in config + ): + raise cv.Invalid( + "{} is defined in away configuration with no {} or {}".format( + CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, + CONF_COOL_ACTION, + CONF_FAN_ONLY_ACTION, + ) + ) + if ( + CONF_DEFAULT_TARGET_TEMPERATURE_LOW in away + and CONF_HEAT_ACTION not in config + ): + raise cv.Invalid( + "{} is defined in away configuration with no {}".format( + CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION + ) + ) return config -CONFIG_SCHEMA = cv.All(climate.CLIMATE_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(ThermostatClimate), - cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor), - cv.Required(CONF_IDLE_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_COOL_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_DRY_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_ONLY_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_HEAT_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_AUTO_MODE): automation.validate_automation(single=True), - cv.Optional(CONF_COOL_MODE): automation.validate_automation(single=True), - cv.Optional(CONF_DRY_MODE): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_ONLY_MODE): automation.validate_automation(single=True), - cv.Optional(CONF_HEAT_MODE): automation.validate_automation(single=True), - cv.Optional(CONF_OFF_MODE): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_ON_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_OFF_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_AUTO_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_LOW_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_MEDIUM_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_HIGH_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_MIDDLE_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_FOCUS_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_FAN_MODE_DIFFUSE_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_SWING_BOTH_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_SWING_HORIZONTAL_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_SWING_OFF_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_SWING_VERTICAL_ACTION): automation.validate_automation(single=True), - cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature, - cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, - cv.Optional(CONF_HYSTERESIS, default=0.5): cv.temperature, - cv.Optional(CONF_AWAY_CONFIG): cv.Schema({ - cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature, - cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, - }), -}).extend(cv.COMPONENT_SCHEMA), cv.has_at_least_one_key(CONF_COOL_ACTION, CONF_DRY_ACTION, - CONF_FAN_ONLY_ACTION, CONF_HEAT_ACTION), - validate_thermostat) +CONFIG_SCHEMA = cv.All( + climate.CLIMATE_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(ThermostatClimate), + cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor), + cv.Required(CONF_IDLE_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_COOL_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_DRY_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_FAN_ONLY_ACTION): automation.validate_automation( + single=True + ), + cv.Optional(CONF_HEAT_ACTION): automation.validate_automation(single=True), + cv.Optional(CONF_AUTO_MODE): automation.validate_automation(single=True), + cv.Optional(CONF_COOL_MODE): automation.validate_automation(single=True), + cv.Optional(CONF_DRY_MODE): automation.validate_automation(single=True), + cv.Optional(CONF_FAN_ONLY_MODE): automation.validate_automation( + single=True + ), + cv.Optional(CONF_HEAT_MODE): automation.validate_automation(single=True), + cv.Optional(CONF_OFF_MODE): automation.validate_automation(single=True), + cv.Optional(CONF_FAN_MODE_ON_ACTION): automation.validate_automation( + single=True + ), + cv.Optional(CONF_FAN_MODE_OFF_ACTION): automation.validate_automation( + single=True + ), + cv.Optional(CONF_FAN_MODE_AUTO_ACTION): automation.validate_automation( + single=True + ), + cv.Optional(CONF_FAN_MODE_LOW_ACTION): automation.validate_automation( + single=True + ), + cv.Optional(CONF_FAN_MODE_MEDIUM_ACTION): automation.validate_automation( + single=True + ), + cv.Optional(CONF_FAN_MODE_HIGH_ACTION): automation.validate_automation( + single=True + ), + cv.Optional(CONF_FAN_MODE_MIDDLE_ACTION): automation.validate_automation( + single=True + ), + cv.Optional(CONF_FAN_MODE_FOCUS_ACTION): automation.validate_automation( + single=True + ), + cv.Optional(CONF_FAN_MODE_DIFFUSE_ACTION): automation.validate_automation( + single=True + ), + cv.Optional(CONF_SWING_BOTH_ACTION): automation.validate_automation( + single=True + ), + cv.Optional(CONF_SWING_HORIZONTAL_ACTION): automation.validate_automation( + single=True + ), + cv.Optional(CONF_SWING_OFF_ACTION): automation.validate_automation( + single=True + ), + cv.Optional(CONF_SWING_VERTICAL_ACTION): automation.validate_automation( + single=True + ), + cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature, + cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, + cv.Optional(CONF_HYSTERESIS, default=0.5): cv.temperature, + cv.Optional(CONF_AWAY_CONFIG): cv.Schema( + { + cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature, + cv.Optional(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, + } + ), + } + ).extend(cv.COMPONENT_SCHEMA), + cv.has_at_least_one_key( + CONF_COOL_ACTION, CONF_DRY_ACTION, CONF_FAN_ONLY_ACTION, CONF_HEAT_ACTION + ), + validate_thermostat, +) def to_code(config): @@ -113,8 +228,9 @@ def to_code(config): yield climate.register_climate(var, config) auto_mode_available = CONF_HEAT_ACTION in config and CONF_COOL_ACTION in config - two_points_available = CONF_HEAT_ACTION in config and (CONF_COOL_ACTION in config or - CONF_FAN_ONLY_ACTION in config) + two_points_available = CONF_HEAT_ACTION in config and ( + CONF_COOL_ACTION in config or CONF_FAN_ONLY_ACTION in config + ) sens = yield cg.get_variable(config[CONF_SENSOR]) cg.add(var.set_sensor(sens)) @@ -124,7 +240,7 @@ def to_code(config): cg.add(var.set_supports_two_points(True)) normal_config = ThermostatClimateTargetTempConfig( config[CONF_DEFAULT_TARGET_TEMPERATURE_LOW], - config[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH] + config[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH], ) elif CONF_DEFAULT_TARGET_TEMPERATURE_HIGH in config: cg.add(var.set_supports_two_points(False)) @@ -138,8 +254,9 @@ def to_code(config): ) cg.add(var.set_normal_config(normal_config)) - yield automation.build_automation(var.get_idle_action_trigger(), [], - config[CONF_IDLE_ACTION]) + yield automation.build_automation( + var.get_idle_action_trigger(), [], config[CONF_IDLE_ACTION] + ) if auto_mode_available is True: cg.add(var.set_supports_auto(True)) @@ -147,94 +264,121 @@ def to_code(config): cg.add(var.set_supports_auto(False)) if CONF_COOL_ACTION in config: - yield automation.build_automation(var.get_cool_action_trigger(), [], - config[CONF_COOL_ACTION]) + yield automation.build_automation( + var.get_cool_action_trigger(), [], config[CONF_COOL_ACTION] + ) cg.add(var.set_supports_cool(True)) if CONF_DRY_ACTION in config: - yield automation.build_automation(var.get_dry_action_trigger(), [], - config[CONF_DRY_ACTION]) + yield automation.build_automation( + var.get_dry_action_trigger(), [], config[CONF_DRY_ACTION] + ) cg.add(var.set_supports_dry(True)) if CONF_FAN_ONLY_ACTION in config: - yield automation.build_automation(var.get_fan_only_action_trigger(), [], - config[CONF_FAN_ONLY_ACTION]) + yield automation.build_automation( + var.get_fan_only_action_trigger(), [], config[CONF_FAN_ONLY_ACTION] + ) cg.add(var.set_supports_fan_only(True)) if CONF_HEAT_ACTION in config: - yield automation.build_automation(var.get_heat_action_trigger(), [], - config[CONF_HEAT_ACTION]) + yield automation.build_automation( + var.get_heat_action_trigger(), [], config[CONF_HEAT_ACTION] + ) cg.add(var.set_supports_heat(True)) if CONF_AUTO_MODE in config: - yield automation.build_automation(var.get_auto_mode_trigger(), [], - config[CONF_AUTO_MODE]) + yield automation.build_automation( + var.get_auto_mode_trigger(), [], config[CONF_AUTO_MODE] + ) if CONF_COOL_MODE in config: - yield automation.build_automation(var.get_cool_mode_trigger(), [], - config[CONF_COOL_MODE]) + yield automation.build_automation( + var.get_cool_mode_trigger(), [], config[CONF_COOL_MODE] + ) cg.add(var.set_supports_cool(True)) if CONF_DRY_MODE in config: - yield automation.build_automation(var.get_dry_mode_trigger(), [], - config[CONF_DRY_MODE]) + yield automation.build_automation( + var.get_dry_mode_trigger(), [], config[CONF_DRY_MODE] + ) cg.add(var.set_supports_dry(True)) if CONF_FAN_ONLY_MODE in config: - yield automation.build_automation(var.get_fan_only_mode_trigger(), [], - config[CONF_FAN_ONLY_MODE]) + yield automation.build_automation( + var.get_fan_only_mode_trigger(), [], config[CONF_FAN_ONLY_MODE] + ) cg.add(var.set_supports_fan_only(True)) if CONF_HEAT_MODE in config: - yield automation.build_automation(var.get_heat_mode_trigger(), [], - config[CONF_HEAT_MODE]) + yield automation.build_automation( + var.get_heat_mode_trigger(), [], config[CONF_HEAT_MODE] + ) cg.add(var.set_supports_heat(True)) if CONF_OFF_MODE in config: - yield automation.build_automation(var.get_off_mode_trigger(), [], - config[CONF_OFF_MODE]) + yield automation.build_automation( + var.get_off_mode_trigger(), [], config[CONF_OFF_MODE] + ) if CONF_FAN_MODE_ON_ACTION in config: - yield automation.build_automation(var.get_fan_mode_on_trigger(), [], - config[CONF_FAN_MODE_ON_ACTION]) + yield automation.build_automation( + var.get_fan_mode_on_trigger(), [], config[CONF_FAN_MODE_ON_ACTION] + ) cg.add(var.set_supports_fan_mode_on(True)) if CONF_FAN_MODE_OFF_ACTION in config: - yield automation.build_automation(var.get_fan_mode_off_trigger(), [], - config[CONF_FAN_MODE_OFF_ACTION]) + yield automation.build_automation( + var.get_fan_mode_off_trigger(), [], config[CONF_FAN_MODE_OFF_ACTION] + ) cg.add(var.set_supports_fan_mode_off(True)) if CONF_FAN_MODE_AUTO_ACTION in config: - yield automation.build_automation(var.get_fan_mode_auto_trigger(), [], - config[CONF_FAN_MODE_AUTO_ACTION]) + yield automation.build_automation( + var.get_fan_mode_auto_trigger(), [], config[CONF_FAN_MODE_AUTO_ACTION] + ) cg.add(var.set_supports_fan_mode_auto(True)) if CONF_FAN_MODE_LOW_ACTION in config: - yield automation.build_automation(var.get_fan_mode_low_trigger(), [], - config[CONF_FAN_MODE_LOW_ACTION]) + yield automation.build_automation( + var.get_fan_mode_low_trigger(), [], config[CONF_FAN_MODE_LOW_ACTION] + ) cg.add(var.set_supports_fan_mode_low(True)) if CONF_FAN_MODE_MEDIUM_ACTION in config: - yield automation.build_automation(var.get_fan_mode_medium_trigger(), [], - config[CONF_FAN_MODE_MEDIUM_ACTION]) + yield automation.build_automation( + var.get_fan_mode_medium_trigger(), [], config[CONF_FAN_MODE_MEDIUM_ACTION] + ) cg.add(var.set_supports_fan_mode_medium(True)) if CONF_FAN_MODE_HIGH_ACTION in config: - yield automation.build_automation(var.get_fan_mode_high_trigger(), [], - config[CONF_FAN_MODE_HIGH_ACTION]) + yield automation.build_automation( + var.get_fan_mode_high_trigger(), [], config[CONF_FAN_MODE_HIGH_ACTION] + ) cg.add(var.set_supports_fan_mode_high(True)) if CONF_FAN_MODE_MIDDLE_ACTION in config: - yield automation.build_automation(var.get_fan_mode_middle_trigger(), [], - config[CONF_FAN_MODE_MIDDLE_ACTION]) + yield automation.build_automation( + var.get_fan_mode_middle_trigger(), [], config[CONF_FAN_MODE_MIDDLE_ACTION] + ) cg.add(var.set_supports_fan_mode_middle(True)) if CONF_FAN_MODE_FOCUS_ACTION in config: - yield automation.build_automation(var.get_fan_mode_focus_trigger(), [], - config[CONF_FAN_MODE_FOCUS_ACTION]) + yield automation.build_automation( + var.get_fan_mode_focus_trigger(), [], config[CONF_FAN_MODE_FOCUS_ACTION] + ) cg.add(var.set_supports_fan_mode_focus(True)) if CONF_FAN_MODE_DIFFUSE_ACTION in config: - yield automation.build_automation(var.get_fan_mode_diffuse_trigger(), [], - config[CONF_FAN_MODE_DIFFUSE_ACTION]) + yield automation.build_automation( + var.get_fan_mode_diffuse_trigger(), [], config[CONF_FAN_MODE_DIFFUSE_ACTION] + ) cg.add(var.set_supports_fan_mode_diffuse(True)) if CONF_SWING_BOTH_ACTION in config: - yield automation.build_automation(var.get_swing_mode_both_trigger(), [], - config[CONF_SWING_BOTH_ACTION]) + yield automation.build_automation( + var.get_swing_mode_both_trigger(), [], config[CONF_SWING_BOTH_ACTION] + ) cg.add(var.set_supports_swing_mode_both(True)) if CONF_SWING_HORIZONTAL_ACTION in config: - yield automation.build_automation(var.get_swing_mode_horizontal_trigger(), [], - config[CONF_SWING_HORIZONTAL_ACTION]) + yield automation.build_automation( + var.get_swing_mode_horizontal_trigger(), + [], + config[CONF_SWING_HORIZONTAL_ACTION], + ) cg.add(var.set_supports_swing_mode_horizontal(True)) if CONF_SWING_OFF_ACTION in config: - yield automation.build_automation(var.get_swing_mode_off_trigger(), [], - config[CONF_SWING_OFF_ACTION]) + yield automation.build_automation( + var.get_swing_mode_off_trigger(), [], config[CONF_SWING_OFF_ACTION] + ) cg.add(var.set_supports_swing_mode_off(True)) if CONF_SWING_VERTICAL_ACTION in config: - yield automation.build_automation(var.get_swing_mode_vertical_trigger(), [], - config[CONF_SWING_VERTICAL_ACTION]) + yield automation.build_automation( + var.get_swing_mode_vertical_trigger(), + [], + config[CONF_SWING_VERTICAL_ACTION], + ) cg.add(var.set_supports_swing_mode_vertical(True)) if CONF_AWAY_CONFIG in config: @@ -243,7 +387,7 @@ def to_code(config): if two_points_available is True: away_config = ThermostatClimateTargetTempConfig( away[CONF_DEFAULT_TARGET_TEMPERATURE_LOW], - away[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH] + away[CONF_DEFAULT_TARGET_TEMPERATURE_HIGH], ) elif CONF_DEFAULT_TARGET_TEMPERATURE_HIGH in away: away_config = ThermostatClimateTargetTempConfig( diff --git a/esphome/components/time/__init__.py b/esphome/components/time/__init__.py index 5f30a8f2e..b1c938c18 100644 --- a/esphome/components/time/__init__.py +++ b/esphome/components/time/__init__.py @@ -10,23 +10,38 @@ import tzlocal import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation -from esphome.const import CONF_ID, CONF_CRON, CONF_DAYS_OF_MONTH, CONF_DAYS_OF_WEEK, CONF_HOURS, \ - CONF_MINUTES, CONF_MONTHS, CONF_ON_TIME, CONF_ON_TIME_SYNC, CONF_SECONDS, CONF_TIMEZONE, \ - CONF_TRIGGER_ID, CONF_AT, CONF_SECOND, CONF_HOUR, CONF_MINUTE +from esphome.const import ( + CONF_ID, + CONF_CRON, + CONF_DAYS_OF_MONTH, + CONF_DAYS_OF_WEEK, + CONF_HOURS, + CONF_MINUTES, + CONF_MONTHS, + CONF_ON_TIME, + CONF_ON_TIME_SYNC, + CONF_SECONDS, + CONF_TIMEZONE, + CONF_TRIGGER_ID, + CONF_AT, + CONF_SECOND, + CONF_HOUR, + CONF_MINUTE, +) from esphome.core import coroutine, coroutine_with_priority from esphome.automation import Condition _LOGGER = logging.getLogger(__name__) -CODEOWNERS = ['@OttoWinter'] +CODEOWNERS = ["@OttoWinter"] IS_PLATFORM_COMPONENT = True -time_ns = cg.esphome_ns.namespace('time') -RealTimeClock = time_ns.class_('RealTimeClock', cg.PollingComponent) -CronTrigger = time_ns.class_('CronTrigger', automation.Trigger.template(), cg.Component) -SyncTrigger = time_ns.class_('SyncTrigger', automation.Trigger.template(), cg.Component) -ESPTime = time_ns.struct('ESPTime') -TimeHasTimeCondition = time_ns.class_('TimeHasTimeCondition', Condition) +time_ns = cg.esphome_ns.namespace("time") +RealTimeClock = time_ns.class_("RealTimeClock", cg.PollingComponent) +CronTrigger = time_ns.class_("CronTrigger", automation.Trigger.template(), cg.Component) +SyncTrigger = time_ns.class_("SyncTrigger", automation.Trigger.template(), cg.Component) +ESPTime = time_ns.struct("ESPTime") +TimeHasTimeCondition = time_ns.class_("TimeHasTimeCondition", Condition) def _tz_timedelta(td): @@ -34,12 +49,12 @@ def _tz_timedelta(td): offset_minute = int(abs(td.total_seconds() / 60)) % 60 offset_second = int(abs(td.total_seconds())) % 60 if offset_hour == 0 and offset_minute == 0 and offset_second == 0: - return '0' + return "0" if offset_minute == 0 and offset_second == 0: - return f'{offset_hour}' + return f"{offset_hour}" if offset_second == 0: - return f'{offset_hour}:{offset_minute}' - return f'{offset_hour}:{offset_minute}:{offset_second}' + return f"{offset_hour}:{offset_minute}" + return f"{offset_hour}:{offset_minute}:{offset_second}" # https://stackoverflow.com/a/16804556/8924614 @@ -52,8 +67,9 @@ def _week_of_month(dt): def _tz_dst_str(dt): td = datetime.timedelta(hours=dt.hour, minutes=dt.minute, seconds=dt.second) - return 'M{}.{}.{}/{}'.format(dt.month, _week_of_month(dt), dt.isoweekday() % 7, - _tz_timedelta(td)) + return "M{}.{}.{}/{}".format( + dt.month, _week_of_month(dt), dt.isoweekday() % 7, _tz_timedelta(td) + ) def _safe_tzname(tz, dt): @@ -62,16 +78,17 @@ def _safe_tzname(tz, dt): # For example: 'Europe/Saratov' returns '+04' # Work around it by using a generic name for the timezone if not all(c in string.ascii_letters for c in tzname): - return 'TZ' + return "TZ" return tzname def _non_dst_tz(tz, dt): tzname = _safe_tzname(tz, dt) utcoffset = tz.utcoffset(dt) - _LOGGER.info("Detected timezone '%s' with UTC offset %s", - tzname, _tz_timedelta(utcoffset)) - tzbase = '{}{}'.format(tzname, _tz_timedelta(-1 * utcoffset)) + _LOGGER.info( + "Detected timezone '%s' with UTC offset %s", tzname, _tz_timedelta(utcoffset) + ) + tzbase = "{}{}".format(tzname, _tz_timedelta(-1 * utcoffset)) return tzbase @@ -112,15 +129,22 @@ def convert_tz(pytz_obj): dst_ends_utc = transition_times[idx2] dst_ends_local = dst_ends_utc + utcoffset_on - tzbase = '{}{}'.format(tzname_off, _tz_timedelta(-1 * utcoffset_off)) + tzbase = "{}{}".format(tzname_off, _tz_timedelta(-1 * utcoffset_off)) - tzext = '{}{},{},{}'.format(tzname_on, _tz_timedelta(-1 * utcoffset_on), - _tz_dst_str(dst_begins_local), _tz_dst_str(dst_ends_local)) - _LOGGER.info("Detected timezone '%s' with UTC offset %s and daylight savings time from " - "%s to %s", - tzname_off, _tz_timedelta(utcoffset_off), - dst_begins_local.strftime("%d %B %X"), - dst_ends_local.strftime("%d %B %X")) + tzext = "{}{},{},{}".format( + tzname_on, + _tz_timedelta(-1 * utcoffset_on), + _tz_dst_str(dst_begins_local), + _tz_dst_str(dst_ends_local), + ) + _LOGGER.info( + "Detected timezone '%s' with UTC offset %s and daylight savings time from " + "%s to %s", + tzname_off, + _tz_timedelta(utcoffset_off), + dst_begins_local.strftime("%d %B %X"), + dst_ends_local.strftime("%d %B %X"), + ) return tzbase + tzext @@ -129,7 +153,7 @@ def detect_tz(): tz = tzlocal.get_localzone() except pytz.exceptions.UnknownTimeZoneError: _LOGGER.warning("Could not auto-detect timezone. Using UTC...") - return 'UTC' + return "UTC" return convert_tz(tz) @@ -146,42 +170,61 @@ def _parse_cron_int(value, special_mapping, message): def _parse_cron_part(part, min_value, max_value, special_mapping): - if part in ('*', '?'): + if part in ("*", "?"): return set(range(min_value, max_value + 1)) - if '/' in part: - data = part.split('/') + if "/" in part: + data = part.split("/") if len(data) > 2: - raise cv.Invalid("Can't have more than two '/' in one time expression, got {}" - .format(part)) + raise cv.Invalid( + "Can't have more than two '/' in one time expression, got {}".format( + part + ) + ) offset, repeat = data offset_n = 0 if offset: - offset_n = _parse_cron_int(offset, special_mapping, - "Offset for '/' time expression must be an integer, got {}") + offset_n = _parse_cron_int( + offset, + special_mapping, + "Offset for '/' time expression must be an integer, got {}", + ) try: repeat_n = int(repeat) except ValueError: # pylint: disable=raise-missing-from - raise cv.Invalid("Repeat for '/' time expression must be an integer, got {}" - .format(repeat)) + raise cv.Invalid( + "Repeat for '/' time expression must be an integer, got {}".format( + repeat + ) + ) return set(range(offset_n, max_value + 1, repeat_n)) - if '-' in part: - data = part.split('-') + if "-" in part: + data = part.split("-") if len(data) > 2: - raise cv.Invalid("Can't have more than two '-' in range time expression '{}'" - .format(part)) + raise cv.Invalid( + "Can't have more than two '-' in range time expression '{}'".format( + part + ) + ) begin, end = data - begin_n = _parse_cron_int(begin, special_mapping, "Number for time range must be integer, " - "got {}") - end_n = _parse_cron_int(end, special_mapping, "Number for time range must be integer, " - "got {}") + begin_n = _parse_cron_int( + begin, special_mapping, "Number for time range must be integer, " "got {}" + ) + end_n = _parse_cron_int( + end, special_mapping, "Number for time range must be integer, " "got {}" + ) if end_n < begin_n: return set(range(end_n, max_value + 1)) | set(range(min_value, begin_n + 1)) return set(range(begin_n, end_n + 1)) - return {_parse_cron_int(part, special_mapping, "Number for time expression must be an " - "integer, got {}")} + return { + _parse_cron_int( + part, + special_mapping, + "Number for time expression must be an " "integer, got {}", + ) + } def cron_expression_validator(name, min_value, max_value, special_mapping=None): @@ -190,42 +233,71 @@ def cron_expression_validator(name, min_value, max_value, special_mapping=None): for v in value: if not isinstance(v, int): raise cv.Invalid( - "Expected integer for {} '{}', got {}".format(v, name, type(v))) + "Expected integer for {} '{}', got {}".format(v, name, type(v)) + ) if v < min_value or v > max_value: raise cv.Invalid( - "{} {} is out of range (min={} max={}).".format(name, v, min_value, - max_value)) + "{} {} is out of range (min={} max={}).".format( + name, v, min_value, max_value + ) + ) return list(sorted(value)) value = cv.string(value) values = set() - for part in value.split(','): + for part in value.split(","): values |= _parse_cron_part(part, min_value, max_value, special_mapping) return validator(list(values)) return validator -validate_cron_seconds = cron_expression_validator('seconds', 0, 60) -validate_cron_minutes = cron_expression_validator('minutes', 0, 59) -validate_cron_hours = cron_expression_validator('hours', 0, 23) -validate_cron_days_of_month = cron_expression_validator('days of month', 1, 31) -validate_cron_months = cron_expression_validator('months', 1, 12, { - 'JAN': 1, 'FEB': 2, 'MAR': 3, 'APR': 4, 'MAY': 5, 'JUN': 6, 'JUL': 7, 'AUG': 8, - 'SEP': 9, 'OCT': 10, 'NOV': 11, 'DEC': 12 -}) -validate_cron_days_of_week = cron_expression_validator('days of week', 1, 7, { - 'SUN': 1, 'MON': 2, 'TUE': 3, 'WED': 4, 'THU': 5, 'FRI': 6, 'SAT': 7 -}) -CRON_KEYS = [CONF_SECONDS, CONF_MINUTES, CONF_HOURS, CONF_DAYS_OF_MONTH, CONF_MONTHS, - CONF_DAYS_OF_WEEK] +validate_cron_seconds = cron_expression_validator("seconds", 0, 60) +validate_cron_minutes = cron_expression_validator("minutes", 0, 59) +validate_cron_hours = cron_expression_validator("hours", 0, 23) +validate_cron_days_of_month = cron_expression_validator("days of month", 1, 31) +validate_cron_months = cron_expression_validator( + "months", + 1, + 12, + { + "JAN": 1, + "FEB": 2, + "MAR": 3, + "APR": 4, + "MAY": 5, + "JUN": 6, + "JUL": 7, + "AUG": 8, + "SEP": 9, + "OCT": 10, + "NOV": 11, + "DEC": 12, + }, +) +validate_cron_days_of_week = cron_expression_validator( + "days of week", + 1, + 7, + {"SUN": 1, "MON": 2, "TUE": 3, "WED": 4, "THU": 5, "FRI": 6, "SAT": 7}, +) +CRON_KEYS = [ + CONF_SECONDS, + CONF_MINUTES, + CONF_HOURS, + CONF_DAYS_OF_MONTH, + CONF_MONTHS, + CONF_DAYS_OF_WEEK, +] def validate_cron_raw(value): value = cv.string(value) - value = value.split(' ') + value = value.split(" ") if len(value) != 6: - raise cv.Invalid("Cron expression must consist of exactly 6 space-separated parts, " - "not {}".format(len(value))) + raise cv.Invalid( + "Cron expression must consist of exactly 6 space-separated parts, " + "not {}".format(len(value)) + ) seconds, minutes, hours, days_of_month, months, days_of_week = value return { CONF_SECONDS: validate_cron_seconds(seconds), @@ -243,9 +315,9 @@ def validate_time_at(value): CONF_HOURS: [value[CONF_HOUR]], CONF_MINUTES: [value[CONF_MINUTE]], CONF_SECONDS: [value[CONF_SECOND]], - CONF_DAYS_OF_MONTH: validate_cron_days_of_month('*'), - CONF_MONTHS: validate_cron_months('*'), - CONF_DAYS_OF_WEEK: validate_cron_days_of_week('*'), + CONF_DAYS_OF_MONTH: validate_cron_days_of_month("*"), + CONF_MONTHS: validate_cron_months("*"), + CONF_DAYS_OF_WEEK: validate_cron_days_of_week("*"), } @@ -282,23 +354,30 @@ def validate_tz(value): return convert_tz(pytz_obj) -TIME_SCHEMA = cv.Schema({ - cv.Optional(CONF_TIMEZONE, default=detect_tz): validate_tz, - cv.Optional(CONF_ON_TIME): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CronTrigger), - cv.Optional(CONF_SECONDS): validate_cron_seconds, - cv.Optional(CONF_MINUTES): validate_cron_minutes, - cv.Optional(CONF_HOURS): validate_cron_hours, - cv.Optional(CONF_DAYS_OF_MONTH): validate_cron_days_of_month, - cv.Optional(CONF_MONTHS): validate_cron_months, - cv.Optional(CONF_DAYS_OF_WEEK): validate_cron_days_of_week, - cv.Optional(CONF_CRON): validate_cron_raw, - cv.Optional(CONF_AT): validate_time_at, - }, validate_cron_keys), - cv.Optional(CONF_ON_TIME_SYNC): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SyncTrigger), - }), -}).extend(cv.polling_component_schema('15min')) +TIME_SCHEMA = cv.Schema( + { + cv.Optional(CONF_TIMEZONE, default=detect_tz): validate_tz, + cv.Optional(CONF_ON_TIME): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CronTrigger), + cv.Optional(CONF_SECONDS): validate_cron_seconds, + cv.Optional(CONF_MINUTES): validate_cron_minutes, + cv.Optional(CONF_HOURS): validate_cron_hours, + cv.Optional(CONF_DAYS_OF_MONTH): validate_cron_days_of_month, + cv.Optional(CONF_MONTHS): validate_cron_months, + cv.Optional(CONF_DAYS_OF_WEEK): validate_cron_days_of_week, + cv.Optional(CONF_CRON): validate_cron_raw, + cv.Optional(CONF_AT): validate_time_at, + }, + validate_cron_keys, + ), + cv.Optional(CONF_ON_TIME_SYNC): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(SyncTrigger), + } + ), + } +).extend(cv.polling_component_schema("15min")) @coroutine @@ -338,13 +417,19 @@ def register_time(time_var, config): @coroutine_with_priority(100.0) def to_code(config): - cg.add_define('USE_TIME') + cg.add_define("USE_TIME") cg.add_global(time_ns.using) -@automation.register_condition('time.has_time', TimeHasTimeCondition, cv.Schema({ - cv.GenerateID(): cv.use_id(RealTimeClock), -})) +@automation.register_condition( + "time.has_time", + TimeHasTimeCondition, + cv.Schema( + { + cv.GenerateID(): cv.use_id(RealTimeClock), + } + ), +) def time_has_time_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) diff --git a/esphome/components/time_based/cover.py b/esphome/components/time_based/cover.py index dcb8d9505..9246f7888 100644 --- a/esphome/components/time_based/cover.py +++ b/esphome/components/time_based/cover.py @@ -2,27 +2,33 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.components import cover -from esphome.const import CONF_CLOSE_ACTION, CONF_CLOSE_DURATION, CONF_ID, CONF_OPEN_ACTION, \ - CONF_OPEN_DURATION, CONF_STOP_ACTION, CONF_ASSUMED_STATE +from esphome.const import ( + CONF_CLOSE_ACTION, + CONF_CLOSE_DURATION, + CONF_ID, + CONF_OPEN_ACTION, + CONF_OPEN_DURATION, + CONF_STOP_ACTION, + CONF_ASSUMED_STATE, +) -time_based_ns = cg.esphome_ns.namespace('time_based') -TimeBasedCover = time_based_ns.class_('TimeBasedCover', cover.Cover, cg.Component) +time_based_ns = cg.esphome_ns.namespace("time_based") +TimeBasedCover = time_based_ns.class_("TimeBasedCover", cover.Cover, cg.Component) -CONF_HAS_BUILT_IN_ENDSTOP = 'has_built_in_endstop' +CONF_HAS_BUILT_IN_ENDSTOP = "has_built_in_endstop" -CONFIG_SCHEMA = cover.COVER_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(TimeBasedCover), - cv.Required(CONF_STOP_ACTION): automation.validate_automation(single=True), - - 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_DURATION): cv.positive_time_period_milliseconds, - - cv.Optional(CONF_HAS_BUILT_IN_ENDSTOP, default=False): cv.boolean, - cv.Optional(CONF_ASSUMED_STATE, default=True): cv.boolean, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cover.COVER_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(TimeBasedCover), + cv.Required(CONF_STOP_ACTION): automation.validate_automation(single=True), + 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_DURATION): cv.positive_time_period_milliseconds, + cv.Optional(CONF_HAS_BUILT_IN_ENDSTOP, default=False): cv.boolean, + cv.Optional(CONF_ASSUMED_STATE, default=True): cv.boolean, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): @@ -30,13 +36,19 @@ 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] + ) 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] + ) 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] + ) cg.add(var.set_has_built_in_endstop(config[CONF_HAS_BUILT_IN_ENDSTOP])) cg.add(var.set_assumed_state(config[CONF_ASSUMED_STATE])) diff --git a/esphome/components/tlc59208f/__init__.py b/esphome/components/tlc59208f/__init__.py index 4666b63b4..ff5b75954 100644 --- a/esphome/components/tlc59208f/__init__.py +++ b/esphome/components/tlc59208f/__init__.py @@ -3,15 +3,21 @@ import esphome.config_validation as cv from esphome.components import i2c from esphome.const import CONF_ID -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] MULTI_CONF = True -tlc59208f_ns = cg.esphome_ns.namespace('tlc59208f') -TLC59208FOutput = tlc59208f_ns.class_('TLC59208FOutput', cg.Component, i2c.I2CDevice) +tlc59208f_ns = cg.esphome_ns.namespace("tlc59208f") +TLC59208FOutput = tlc59208f_ns.class_("TLC59208FOutput", cg.Component, i2c.I2CDevice) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(TLC59208FOutput), -}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x20)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(TLC59208FOutput), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x20)) +) def to_code(config): diff --git a/esphome/components/tlc59208f/output.py b/esphome/components/tlc59208f/output.py index f61f7729e..94cf529a7 100644 --- a/esphome/components/tlc59208f/output.py +++ b/esphome/components/tlc59208f/output.py @@ -4,17 +4,18 @@ from esphome.components import output from esphome.const import CONF_CHANNEL, CONF_ID from . import TLC59208FOutput, tlc59208f_ns -DEPENDENCIES = ['tlc59208f'] +DEPENDENCIES = ["tlc59208f"] -TLC59208FChannel = tlc59208f_ns.class_('TLC59208FChannel', output.FloatOutput) -CONF_TLC59208F_ID = 'tlc59208f_id' +TLC59208FChannel = tlc59208f_ns.class_("TLC59208FChannel", output.FloatOutput) +CONF_TLC59208F_ID = "tlc59208f_id" -CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend({ - cv.Required(CONF_ID): cv.declare_id(TLC59208FChannel), - cv.GenerateID(CONF_TLC59208F_ID): cv.use_id(TLC59208FOutput), - - cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=7), -}) +CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend( + { + cv.Required(CONF_ID): cv.declare_id(TLC59208FChannel), + cv.GenerateID(CONF_TLC59208F_ID): cv.use_id(TLC59208FOutput), + cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=7), + } +) def to_code(config): diff --git a/esphome/components/tm1637/display.py b/esphome/components/tm1637/display.py index c2692e30d..06a9716e5 100644 --- a/esphome/components/tm1637/display.py +++ b/esphome/components/tm1637/display.py @@ -2,21 +2,30 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.components import display -from esphome.const import CONF_CLK_PIN, CONF_DIO_PIN, CONF_ID, CONF_LAMBDA, CONF_INTENSITY +from esphome.const import ( + CONF_CLK_PIN, + CONF_DIO_PIN, + CONF_ID, + CONF_LAMBDA, + CONF_INTENSITY, +) -CODEOWNERS = ['@glmnet'] +CODEOWNERS = ["@glmnet"] -tm1637_ns = cg.esphome_ns.namespace('tm1637') -TM1637Display = tm1637_ns.class_('TM1637Display', cg.PollingComponent) -TM1637DisplayRef = TM1637Display.operator('ref') +tm1637_ns = cg.esphome_ns.namespace("tm1637") +TM1637Display = tm1637_ns.class_("TM1637Display", cg.PollingComponent) +TM1637DisplayRef = TM1637Display.operator("ref") -CONFIG_SCHEMA = display.BASIC_DISPLAY_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(TM1637Display), - - cv.Optional(CONF_INTENSITY, default=7): cv.All(cv.uint8_t, cv.Range(min=0, max=7)), - cv.Required(CONF_CLK_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_DIO_PIN): pins.gpio_output_pin_schema, -}).extend(cv.polling_component_schema('1s')) +CONFIG_SCHEMA = display.BASIC_DISPLAY_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(TM1637Display), + cv.Optional(CONF_INTENSITY, default=7): cv.All( + cv.uint8_t, cv.Range(min=0, max=7) + ), + cv.Required(CONF_CLK_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_DIO_PIN): pins.gpio_output_pin_schema, + } +).extend(cv.polling_component_schema("1s")) def to_code(config): @@ -32,6 +41,7 @@ def to_code(config): cg.add(var.set_intensity(config[CONF_INTENSITY])) if CONF_LAMBDA in config: - lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], [(TM1637DisplayRef, 'it')], - return_type=cg.void) + lambda_ = yield cg.process_lambda( + config[CONF_LAMBDA], [(TM1637DisplayRef, "it")], return_type=cg.void + ) cg.add(var.set_writer(lambda_)) diff --git a/esphome/components/tm1651/__init__.py b/esphome/components/tm1651/__init__.py index aa972552f..97c1e472e 100644 --- a/esphome/components/tm1651/__init__.py +++ b/esphome/components/tm1651/__init__.py @@ -2,30 +2,38 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins, automation from esphome.automation import maybe_simple_id -from esphome.const import CONF_ID, CONF_CLK_PIN, CONF_DIO_PIN, CONF_LEVEL, CONF_BRIGHTNESS +from esphome.const import ( + CONF_ID, + CONF_CLK_PIN, + CONF_DIO_PIN, + CONF_LEVEL, + CONF_BRIGHTNESS, +) -tm1651_ns = cg.esphome_ns.namespace('tm1651') -TM1651Display = tm1651_ns.class_('TM1651Display', cg.Component) +tm1651_ns = cg.esphome_ns.namespace("tm1651") +TM1651Display = tm1651_ns.class_("TM1651Display", cg.Component) -SetLevelPercentAction = tm1651_ns.class_('SetLevelPercentAction', automation.Action) -SetLevelAction = tm1651_ns.class_('SetLevelAction', automation.Action) -SetBrightnessAction = tm1651_ns.class_('SetBrightnessAction', automation.Action) -TurnOnAction = tm1651_ns.class_('SetLevelPercentAction', automation.Action) -TurnOffAction = tm1651_ns.class_('SetLevelPercentAction', automation.Action) +SetLevelPercentAction = tm1651_ns.class_("SetLevelPercentAction", automation.Action) +SetLevelAction = tm1651_ns.class_("SetLevelAction", automation.Action) +SetBrightnessAction = tm1651_ns.class_("SetBrightnessAction", automation.Action) +TurnOnAction = tm1651_ns.class_("SetLevelPercentAction", automation.Action) +TurnOffAction = tm1651_ns.class_("SetLevelPercentAction", automation.Action) -CONF_LEVEL_PERCENT = 'level_percent' +CONF_LEVEL_PERCENT = "level_percent" TM1651_BRIGHTNESS_OPTIONS = { 1: TM1651Display.TM1651_BRIGHTNESS_LOW, 2: TM1651Display.TM1651_BRIGHTNESS_MEDIUM, - 3: TM1651Display.TM1651_BRIGHTNESS_HIGH + 3: TM1651Display.TM1651_BRIGHTNESS_HIGH, } -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(TM1651Display), - cv.Required(CONF_CLK_PIN): pins.internal_gpio_output_pin_schema, - cv.Required(CONF_DIO_PIN): pins.internal_gpio_output_pin_schema, -}) +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(TM1651Display), + cv.Required(CONF_CLK_PIN): pins.internal_gpio_output_pin_schema, + cv.Required(CONF_DIO_PIN): pins.internal_gpio_output_pin_schema, + } +) validate_level_percent = cv.All(cv.int_range(min=0, max=100)) validate_level = cv.All(cv.int_range(min=0, max=7)) @@ -42,22 +50,26 @@ def to_code(config): cg.add(var.set_dio_pin(dio_pin)) # https://platformio.org/lib/show/6865/TM1651 - cg.add_library('6865', '1.0.1') + cg.add_library("6865", "1.0.1") -BINARY_OUTPUT_ACTION_SCHEMA = maybe_simple_id({ - cv.Required(CONF_ID): cv.use_id(TM1651Display), -}) +BINARY_OUTPUT_ACTION_SCHEMA = maybe_simple_id( + { + cv.Required(CONF_ID): cv.use_id(TM1651Display), + } +) -@automation.register_action('tm1651.turn_on', TurnOnAction, BINARY_OUTPUT_ACTION_SCHEMA) +@automation.register_action("tm1651.turn_on", TurnOnAction, BINARY_OUTPUT_ACTION_SCHEMA) def output_turn_on_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('tm1651.turn_off', TurnOffAction, BINARY_OUTPUT_ACTION_SCHEMA) +@automation.register_action( + "tm1651.turn_off", TurnOffAction, BINARY_OUTPUT_ACTION_SCHEMA +) def output_turn_off_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) yield cg.register_parented(var, config[CONF_ID]) @@ -65,12 +77,16 @@ def output_turn_off_to_code(config, action_id, template_arg, args): @automation.register_action( - 'tm1651.set_level_percent', + "tm1651.set_level_percent", SetLevelPercentAction, - cv.maybe_simple_value({ - cv.GenerateID(): cv.use_id(TM1651Display), - cv.Required(CONF_LEVEL_PERCENT): cv.templatable(validate_level_percent), - }, key=CONF_LEVEL_PERCENT)) + cv.maybe_simple_value( + { + cv.GenerateID(): cv.use_id(TM1651Display), + cv.Required(CONF_LEVEL_PERCENT): cv.templatable(validate_level_percent), + }, + key=CONF_LEVEL_PERCENT, + ), +) def tm1651_set_level_percent_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) yield cg.register_parented(var, config[CONF_ID]) @@ -80,12 +96,16 @@ def tm1651_set_level_percent_to_code(config, action_id, template_arg, args): @automation.register_action( - 'tm1651.set_level', + "tm1651.set_level", SetLevelAction, - cv.maybe_simple_value({ - cv.GenerateID(): cv.use_id(TM1651Display), - cv.Required(CONF_LEVEL): cv.templatable(validate_level), - }, key=CONF_LEVEL)) + cv.maybe_simple_value( + { + cv.GenerateID(): cv.use_id(TM1651Display), + cv.Required(CONF_LEVEL): cv.templatable(validate_level), + }, + key=CONF_LEVEL, + ), +) def tm1651_set_level_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) yield cg.register_parented(var, config[CONF_ID]) @@ -95,12 +115,16 @@ def tm1651_set_level_to_code(config, action_id, template_arg, args): @automation.register_action( - 'tm1651.set_brightness', + "tm1651.set_brightness", SetBrightnessAction, - cv.maybe_simple_value({ - cv.GenerateID(): cv.use_id(TM1651Display), - cv.Required(CONF_BRIGHTNESS): cv.templatable(validate_brightness), - }, key=CONF_BRIGHTNESS)) + cv.maybe_simple_value( + { + cv.GenerateID(): cv.use_id(TM1651Display), + cv.Required(CONF_BRIGHTNESS): cv.templatable(validate_brightness), + }, + key=CONF_BRIGHTNESS, + ), +) def tm1651_set_brightness_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) yield cg.register_parented(var, config[CONF_ID]) diff --git a/esphome/components/tmp102/sensor.py b/esphome/components/tmp102/sensor.py index 05f33c43a..4c04271d9 100644 --- a/esphome/components/tmp102/sensor.py +++ b/esphome/components/tmp102/sensor.py @@ -12,16 +12,24 @@ import esphome.config_validation as cv from esphome.components import i2c, sensor from esphome.const import CONF_ID, DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, UNIT_CELSIUS -CODEOWNERS = ['@timsavage'] -DEPENDENCIES = ['i2c'] +CODEOWNERS = ["@timsavage"] +DEPENDENCIES = ["i2c"] -tmp102_ns = cg.esphome_ns.namespace('tmp102') -TMP102Component = tmp102_ns.class_("TMP102Component", cg.PollingComponent, i2c.I2CDevice, - sensor.Sensor) +tmp102_ns = cg.esphome_ns.namespace("tmp102") +TMP102Component = tmp102_ns.class_( + "TMP102Component", cg.PollingComponent, i2c.I2CDevice, sensor.Sensor +) -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE).extend({ - cv.GenerateID(): cv.declare_id(TMP102Component), -}).extend(cv.polling_component_schema("60s")).extend(i2c.i2c_device_schema(0x48)) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE) + .extend( + { + cv.GenerateID(): cv.declare_id(TMP102Component), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x48)) +) def to_code(config): diff --git a/esphome/components/tmp117/sensor.py b/esphome/components/tmp117/sensor.py index 4d2e662b5..33c13e3f3 100644 --- a/esphome/components/tmp117/sensor.py +++ b/esphome/components/tmp117/sensor.py @@ -1,20 +1,31 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, sensor -from esphome.const import CONF_ID, CONF_UPDATE_INTERVAL, DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, \ - UNIT_CELSIUS +from esphome.const import ( + CONF_ID, + CONF_UPDATE_INTERVAL, + DEVICE_CLASS_TEMPERATURE, + ICON_EMPTY, + UNIT_CELSIUS, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -tmp117_ns = cg.esphome_ns.namespace('tmp117') -TMP117Component = tmp117_ns.class_('TMP117Component', - cg.PollingComponent, i2c.I2CDevice, sensor.Sensor) +tmp117_ns = cg.esphome_ns.namespace("tmp117") +TMP117Component = tmp117_ns.class_( + "TMP117Component", cg.PollingComponent, i2c.I2CDevice, sensor.Sensor +) -CONFIG_SCHEMA = cv.All(sensor.sensor_schema( - UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE -).extend({ - cv.GenerateID(): cv.declare_id(TMP117Component), -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x48))) +CONFIG_SCHEMA = cv.All( + sensor.sensor_schema(UNIT_CELSIUS, ICON_EMPTY, 1, DEVICE_CLASS_TEMPERATURE) + .extend( + { + cv.GenerateID(): cv.declare_id(TMP117Component), + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x48)) +) def determine_config_register(polling_period): diff --git a/esphome/components/toshiba/climate.py b/esphome/components/toshiba/climate.py index ea7efbf2f..3021697f2 100644 --- a/esphome/components/toshiba/climate.py +++ b/esphome/components/toshiba/climate.py @@ -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"] -toshiba_ns = cg.esphome_ns.namespace('toshiba') -ToshibaClimate = toshiba_ns.class_('ToshibaClimate', climate_ir.ClimateIR) +toshiba_ns = cg.esphome_ns.namespace("toshiba") +ToshibaClimate = toshiba_ns.class_("ToshibaClimate", climate_ir.ClimateIR) -CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(ToshibaClimate), -}) +CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(ToshibaClimate), + } +) def to_code(config): diff --git a/esphome/components/total_daily_energy/sensor.py b/esphome/components/total_daily_energy/sensor.py index 7fde9f558..150cab77b 100644 --- a/esphome/components/total_daily_energy/sensor.py +++ b/esphome/components/total_daily_energy/sensor.py @@ -3,17 +3,21 @@ import esphome.config_validation as cv from esphome.components import sensor, time from esphome.const import CONF_ID, CONF_TIME_ID -DEPENDENCIES = ['time'] +DEPENDENCIES = ["time"] -CONF_POWER_ID = 'power_id' -total_daily_energy_ns = cg.esphome_ns.namespace('total_daily_energy') -TotalDailyEnergy = total_daily_energy_ns.class_('TotalDailyEnergy', sensor.Sensor, cg.Component) +CONF_POWER_ID = "power_id" +total_daily_energy_ns = cg.esphome_ns.namespace("total_daily_energy") +TotalDailyEnergy = total_daily_energy_ns.class_( + "TotalDailyEnergy", sensor.Sensor, cg.Component +) -CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(TotalDailyEnergy), - cv.GenerateID(CONF_TIME_ID): cv.use_id(time.RealTimeClock), - cv.Required(CONF_POWER_ID): cv.use_id(sensor.Sensor), -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(TotalDailyEnergy), + cv.GenerateID(CONF_TIME_ID): cv.use_id(time.RealTimeClock), + cv.Required(CONF_POWER_ID): cv.use_id(sensor.Sensor), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/tsl2561/sensor.py b/esphome/components/tsl2561/sensor.py index 92ad64e2e..d0219fc07 100644 --- a/esphome/components/tsl2561/sensor.py +++ b/esphome/components/tsl2561/sensor.py @@ -1,26 +1,32 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import i2c, sensor -from esphome.const import CONF_GAIN, CONF_ID, CONF_INTEGRATION_TIME, DEVICE_CLASS_ILLUMINANCE, \ - ICON_EMPTY, UNIT_LUX +from esphome.const import ( + CONF_GAIN, + CONF_ID, + CONF_INTEGRATION_TIME, + DEVICE_CLASS_ILLUMINANCE, + ICON_EMPTY, + UNIT_LUX, +) -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -tsl2561_ns = cg.esphome_ns.namespace('tsl2561') -TSL2561IntegrationTime = tsl2561_ns.enum('TSL2561IntegrationTime') +tsl2561_ns = cg.esphome_ns.namespace("tsl2561") +TSL2561IntegrationTime = tsl2561_ns.enum("TSL2561IntegrationTime") INTEGRATION_TIMES = { 14: TSL2561IntegrationTime.TSL2561_INTEGRATION_14MS, 101: TSL2561IntegrationTime.TSL2561_INTEGRATION_101MS, 402: TSL2561IntegrationTime.TSL2561_INTEGRATION_402MS, } -TSL2561Gain = tsl2561_ns.enum('TSL2561Gain') +TSL2561Gain = tsl2561_ns.enum("TSL2561Gain") GAINS = { - '1X': TSL2561Gain.TSL2561_GAIN_1X, - '16X': TSL2561Gain.TSL2561_GAIN_16X, + "1X": TSL2561Gain.TSL2561_GAIN_1X, + "16X": TSL2561Gain.TSL2561_GAIN_16X, } -CONF_IS_CS_PACKAGE = 'is_cs_package' +CONF_IS_CS_PACKAGE = "is_cs_package" def validate_integration_time(value): @@ -28,15 +34,25 @@ def validate_integration_time(value): return cv.enum(INTEGRATION_TIMES, int=True)(value) -TSL2561Sensor = tsl2561_ns.class_('TSL2561Sensor', sensor.Sensor, cg.PollingComponent, - i2c.I2CDevice) +TSL2561Sensor = tsl2561_ns.class_( + "TSL2561Sensor", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice +) -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_LUX, ICON_EMPTY, 1, DEVICE_CLASS_ILLUMINANCE).extend({ - cv.GenerateID(): cv.declare_id(TSL2561Sensor), - cv.Optional(CONF_INTEGRATION_TIME, default='402ms'): validate_integration_time, - cv.Optional(CONF_GAIN, default='1X'): cv.enum(GAINS, upper=True), - cv.Optional(CONF_IS_CS_PACKAGE, default=False): cv.boolean, -}).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x39)) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_LUX, ICON_EMPTY, 1, DEVICE_CLASS_ILLUMINANCE) + .extend( + { + cv.GenerateID(): cv.declare_id(TSL2561Sensor), + cv.Optional( + CONF_INTEGRATION_TIME, default="402ms" + ): validate_integration_time, + cv.Optional(CONF_GAIN, default="1X"): cv.enum(GAINS, upper=True), + cv.Optional(CONF_IS_CS_PACKAGE, default=False): cv.boolean, + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x39)) +) def to_code(config): diff --git a/esphome/components/ttp229_bsf/__init__.py b/esphome/components/ttp229_bsf/__init__.py index 5ec182d46..8707c9efe 100644 --- a/esphome/components/ttp229_bsf/__init__.py +++ b/esphome/components/ttp229_bsf/__init__.py @@ -3,20 +3,22 @@ import esphome.config_validation as cv from esphome import pins from esphome.const import CONF_ID, CONF_SDO_PIN, CONF_SCL_PIN -DEPENDENCIES = ['i2c'] -AUTO_LOAD = ['binary_sensor'] +DEPENDENCIES = ["i2c"] +AUTO_LOAD = ["binary_sensor"] -CONF_TTP229_ID = 'ttp229_id' -ttp229_bsf_ns = cg.esphome_ns.namespace('ttp229_bsf') +CONF_TTP229_ID = "ttp229_id" +ttp229_bsf_ns = cg.esphome_ns.namespace("ttp229_bsf") -TTP229BSFComponent = ttp229_bsf_ns.class_('TTP229BSFComponent', cg.Component) +TTP229BSFComponent = ttp229_bsf_ns.class_("TTP229BSFComponent", cg.Component) MULTI_CONF = True -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(TTP229BSFComponent), - cv.Required(CONF_SDO_PIN): pins.gpio_input_pullup_pin_schema, - cv.Required(CONF_SCL_PIN): pins.gpio_output_pin_schema, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(TTP229BSFComponent), + cv.Required(CONF_SDO_PIN): pins.gpio_input_pullup_pin_schema, + cv.Required(CONF_SCL_PIN): pins.gpio_output_pin_schema, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/ttp229_bsf/binary_sensor.py b/esphome/components/ttp229_bsf/binary_sensor.py index 7a1ab3dc9..7351e73d8 100644 --- a/esphome/components/ttp229_bsf/binary_sensor.py +++ b/esphome/components/ttp229_bsf/binary_sensor.py @@ -4,14 +4,16 @@ from esphome.components import binary_sensor from esphome.const import CONF_CHANNEL, CONF_ID from . import ttp229_bsf_ns, TTP229BSFComponent, CONF_TTP229_ID -DEPENDENCIES = ['ttp229_bsf'] -TTP229BSFChannel = ttp229_bsf_ns.class_('TTP229BSFChannel', binary_sensor.BinarySensor) +DEPENDENCIES = ["ttp229_bsf"] +TTP229BSFChannel = ttp229_bsf_ns.class_("TTP229BSFChannel", binary_sensor.BinarySensor) -CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(TTP229BSFChannel), - cv.GenerateID(CONF_TTP229_ID): cv.use_id(TTP229BSFComponent), - cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=15), -}) +CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(TTP229BSFChannel), + cv.GenerateID(CONF_TTP229_ID): cv.use_id(TTP229BSFComponent), + cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=15), + } +) def to_code(config): diff --git a/esphome/components/ttp229_lsf/__init__.py b/esphome/components/ttp229_lsf/__init__.py index 6faca970f..1d7efea20 100644 --- a/esphome/components/ttp229_lsf/__init__.py +++ b/esphome/components/ttp229_lsf/__init__.py @@ -3,18 +3,26 @@ import esphome.config_validation as cv from esphome.components import i2c from esphome.const import CONF_ID -DEPENDENCIES = ['i2c'] -AUTO_LOAD = ['binary_sensor'] +DEPENDENCIES = ["i2c"] +AUTO_LOAD = ["binary_sensor"] -CONF_TTP229_ID = 'ttp229_id' -ttp229_lsf_ns = cg.esphome_ns.namespace('ttp229_lsf') +CONF_TTP229_ID = "ttp229_id" +ttp229_lsf_ns = cg.esphome_ns.namespace("ttp229_lsf") -TTP229LSFComponent = ttp229_lsf_ns.class_('TTP229LSFComponent', cg.Component, i2c.I2CDevice) +TTP229LSFComponent = ttp229_lsf_ns.class_( + "TTP229LSFComponent", cg.Component, i2c.I2CDevice +) MULTI_CONF = True -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(TTP229LSFComponent), -}).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x57)) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(TTP229LSFComponent), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(i2c.i2c_device_schema(0x57)) +) def to_code(config): diff --git a/esphome/components/ttp229_lsf/binary_sensor.py b/esphome/components/ttp229_lsf/binary_sensor.py index 870bf1628..09a8a1e20 100644 --- a/esphome/components/ttp229_lsf/binary_sensor.py +++ b/esphome/components/ttp229_lsf/binary_sensor.py @@ -4,14 +4,16 @@ from esphome.components import binary_sensor from esphome.const import CONF_CHANNEL, CONF_ID from . import ttp229_lsf_ns, TTP229LSFComponent, CONF_TTP229_ID -DEPENDENCIES = ['ttp229_lsf'] -TTP229Channel = ttp229_lsf_ns.class_('TTP229Channel', binary_sensor.BinarySensor) +DEPENDENCIES = ["ttp229_lsf"] +TTP229Channel = ttp229_lsf_ns.class_("TTP229Channel", binary_sensor.BinarySensor) -CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(TTP229Channel), - cv.GenerateID(CONF_TTP229_ID): cv.use_id(TTP229LSFComponent), - cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=15), -}) +CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(TTP229Channel), + cv.GenerateID(CONF_TTP229_ID): cv.use_id(TTP229LSFComponent), + cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=15), + } +) def to_code(config): diff --git a/esphome/components/tuya/__init__.py b/esphome/components/tuya/__init__.py index 83a4f733c..58dad1325 100644 --- a/esphome/components/tuya/__init__.py +++ b/esphome/components/tuya/__init__.py @@ -4,19 +4,27 @@ import esphome.config_validation as cv from esphome.components import uart from esphome.const import CONF_ID, CONF_TIME_ID -DEPENDENCIES = ['uart'] +DEPENDENCIES = ["uart"] CONF_IGNORE_MCU_UPDATE_ON_DATAPOINTS = "ignore_mcu_update_on_datapoints" -tuya_ns = cg.esphome_ns.namespace('tuya') -Tuya = tuya_ns.class_('Tuya', cg.Component, uart.UARTDevice) +tuya_ns = cg.esphome_ns.namespace("tuya") +Tuya = tuya_ns.class_("Tuya", cg.Component, uart.UARTDevice) -CONF_TUYA_ID = 'tuya_id' -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(Tuya), - cv.Optional(CONF_TIME_ID): cv.use_id(time.RealTimeClock), - cv.Optional(CONF_IGNORE_MCU_UPDATE_ON_DATAPOINTS): cv.ensure_list(cv.uint8_t), -}).extend(cv.COMPONENT_SCHEMA).extend(uart.UART_DEVICE_SCHEMA) +CONF_TUYA_ID = "tuya_id" +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(Tuya), + cv.Optional(CONF_TIME_ID): cv.use_id(time.RealTimeClock), + cv.Optional(CONF_IGNORE_MCU_UPDATE_ON_DATAPOINTS): cv.ensure_list( + cv.uint8_t + ), + } + ) + .extend(cv.COMPONENT_SCHEMA) + .extend(uart.UART_DEVICE_SCHEMA) +) def to_code(config): diff --git a/esphome/components/tuya/binary_sensor/__init__.py b/esphome/components/tuya/binary_sensor/__init__.py index b63638b4c..45f918ff2 100644 --- a/esphome/components/tuya/binary_sensor/__init__.py +++ b/esphome/components/tuya/binary_sensor/__init__.py @@ -4,18 +4,22 @@ import esphome.codegen as cg from esphome.const import CONF_ID from .. import tuya_ns, CONF_TUYA_ID, Tuya -DEPENDENCIES = ['tuya'] -CODEOWNERS = ['@jesserockz'] +DEPENDENCIES = ["tuya"] +CODEOWNERS = ["@jesserockz"] CONF_SENSOR_DATAPOINT = "sensor_datapoint" -TuyaBinarySensor = tuya_ns.class_('TuyaBinarySensor', binary_sensor.BinarySensor, cg.Component) +TuyaBinarySensor = tuya_ns.class_( + "TuyaBinarySensor", binary_sensor.BinarySensor, cg.Component +) -CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(TuyaBinarySensor), - cv.GenerateID(CONF_TUYA_ID): cv.use_id(Tuya), - cv.Required(CONF_SENSOR_DATAPOINT): cv.uint8_t, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(TuyaBinarySensor), + cv.GenerateID(CONF_TUYA_ID): cv.use_id(Tuya), + cv.Required(CONF_SENSOR_DATAPOINT): cv.uint8_t, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/tuya/climate/__init__.py b/esphome/components/tuya/climate/__init__.py index f0219de97..8ac42f7c8 100644 --- a/esphome/components/tuya/climate/__init__.py +++ b/esphome/components/tuya/climate/__init__.py @@ -4,60 +4,77 @@ import esphome.codegen as cg from esphome.const import CONF_ID, CONF_SWITCH_DATAPOINT from .. import tuya_ns, CONF_TUYA_ID, Tuya -DEPENDENCIES = ['tuya'] -CODEOWNERS = ['@jesserockz'] +DEPENDENCIES = ["tuya"] +CODEOWNERS = ["@jesserockz"] -CONF_TARGET_TEMPERATURE_DATAPOINT = 'target_temperature_datapoint' -CONF_CURRENT_TEMPERATURE_DATAPOINT = 'current_temperature_datapoint' -CONF_TEMPERATURE_MULTIPLIER = 'temperature_multiplier' -CONF_CURRENT_TEMPERATURE_MULTIPLIER = 'current_temperature_multiplier' -CONF_TARGET_TEMPERATURE_MULTIPLIER = 'target_temperature_multiplier' +CONF_TARGET_TEMPERATURE_DATAPOINT = "target_temperature_datapoint" +CONF_CURRENT_TEMPERATURE_DATAPOINT = "current_temperature_datapoint" +CONF_TEMPERATURE_MULTIPLIER = "temperature_multiplier" +CONF_CURRENT_TEMPERATURE_MULTIPLIER = "current_temperature_multiplier" +CONF_TARGET_TEMPERATURE_MULTIPLIER = "target_temperature_multiplier" -TuyaClimate = tuya_ns.class_('TuyaClimate', climate.Climate, cg.Component) +TuyaClimate = tuya_ns.class_("TuyaClimate", climate.Climate, cg.Component) def validate_temperature_multipliers(value): if CONF_TEMPERATURE_MULTIPLIER in value: if ( - CONF_CURRENT_TEMPERATURE_MULTIPLIER in value - or CONF_TARGET_TEMPERATURE_MULTIPLIER in value - ): - raise cv.Invalid((f"Cannot have {CONF_TEMPERATURE_MULTIPLIER} at the same time as " - f"{CONF_CURRENT_TEMPERATURE_MULTIPLIER} and " - f"{CONF_TARGET_TEMPERATURE_MULTIPLIER}")) - if ( CONF_CURRENT_TEMPERATURE_MULTIPLIER in value - and CONF_TARGET_TEMPERATURE_MULTIPLIER not in value - ): - raise cv.Invalid((f"{CONF_TARGET_TEMPERATURE_MULTIPLIER} required if using " - f"{CONF_CURRENT_TEMPERATURE_MULTIPLIER}")) + or CONF_TARGET_TEMPERATURE_MULTIPLIER in value + ): + raise cv.Invalid( + ( + f"Cannot have {CONF_TEMPERATURE_MULTIPLIER} at the same time as " + f"{CONF_CURRENT_TEMPERATURE_MULTIPLIER} and " + f"{CONF_TARGET_TEMPERATURE_MULTIPLIER}" + ) + ) if ( - CONF_TARGET_TEMPERATURE_MULTIPLIER in value - and CONF_CURRENT_TEMPERATURE_MULTIPLIER not in value + CONF_CURRENT_TEMPERATURE_MULTIPLIER in value + and CONF_TARGET_TEMPERATURE_MULTIPLIER not in value ): - raise cv.Invalid((f"{CONF_CURRENT_TEMPERATURE_MULTIPLIER} required if using " - f"{CONF_TARGET_TEMPERATURE_MULTIPLIER}")) + raise cv.Invalid( + ( + f"{CONF_TARGET_TEMPERATURE_MULTIPLIER} required if using " + f"{CONF_CURRENT_TEMPERATURE_MULTIPLIER}" + ) + ) + if ( + CONF_TARGET_TEMPERATURE_MULTIPLIER in value + and CONF_CURRENT_TEMPERATURE_MULTIPLIER not in value + ): + raise cv.Invalid( + ( + f"{CONF_CURRENT_TEMPERATURE_MULTIPLIER} required if using " + f"{CONF_TARGET_TEMPERATURE_MULTIPLIER}" + ) + ) keys = ( CONF_TEMPERATURE_MULTIPLIER, CONF_CURRENT_TEMPERATURE_MULTIPLIER, - CONF_TARGET_TEMPERATURE_MULTIPLIER + CONF_TARGET_TEMPERATURE_MULTIPLIER, ) if all(multiplier not in value for multiplier in keys): value[CONF_TEMPERATURE_MULTIPLIER] = 1.0 return value -CONFIG_SCHEMA = cv.All(climate.CLIMATE_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(TuyaClimate), - cv.GenerateID(CONF_TUYA_ID): cv.use_id(Tuya), - cv.Optional(CONF_SWITCH_DATAPOINT): cv.uint8_t, - cv.Optional(CONF_TARGET_TEMPERATURE_DATAPOINT): cv.uint8_t, - cv.Optional(CONF_CURRENT_TEMPERATURE_DATAPOINT): cv.uint8_t, - cv.Optional(CONF_TEMPERATURE_MULTIPLIER): cv.positive_float, - cv.Optional(CONF_CURRENT_TEMPERATURE_MULTIPLIER): cv.positive_float, - cv.Optional(CONF_TARGET_TEMPERATURE_MULTIPLIER): cv.positive_float, -}).extend(cv.COMPONENT_SCHEMA), cv.has_at_least_one_key( - CONF_TARGET_TEMPERATURE_DATAPOINT, CONF_SWITCH_DATAPOINT), validate_temperature_multipliers) +CONFIG_SCHEMA = cv.All( + climate.CLIMATE_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(TuyaClimate), + cv.GenerateID(CONF_TUYA_ID): cv.use_id(Tuya), + cv.Optional(CONF_SWITCH_DATAPOINT): cv.uint8_t, + cv.Optional(CONF_TARGET_TEMPERATURE_DATAPOINT): cv.uint8_t, + cv.Optional(CONF_CURRENT_TEMPERATURE_DATAPOINT): cv.uint8_t, + cv.Optional(CONF_TEMPERATURE_MULTIPLIER): cv.positive_float, + cv.Optional(CONF_CURRENT_TEMPERATURE_MULTIPLIER): cv.positive_float, + cv.Optional(CONF_TARGET_TEMPERATURE_MULTIPLIER): cv.positive_float, + } + ).extend(cv.COMPONENT_SCHEMA), + cv.has_at_least_one_key(CONF_TARGET_TEMPERATURE_DATAPOINT, CONF_SWITCH_DATAPOINT), + validate_temperature_multipliers, +) def to_code(config): @@ -73,10 +90,24 @@ def to_code(config): if CONF_TARGET_TEMPERATURE_DATAPOINT in config: cg.add(var.set_target_temperature_id(config[CONF_TARGET_TEMPERATURE_DATAPOINT])) if CONF_CURRENT_TEMPERATURE_DATAPOINT in config: - cg.add(var.set_current_temperature_id(config[CONF_CURRENT_TEMPERATURE_DATAPOINT])) + cg.add( + var.set_current_temperature_id(config[CONF_CURRENT_TEMPERATURE_DATAPOINT]) + ) if CONF_TEMPERATURE_MULTIPLIER in config: - cg.add(var.set_target_temperature_multiplier(config[CONF_TEMPERATURE_MULTIPLIER])) - cg.add(var.set_current_temperature_multiplier(config[CONF_TEMPERATURE_MULTIPLIER])) + cg.add( + var.set_target_temperature_multiplier(config[CONF_TEMPERATURE_MULTIPLIER]) + ) + cg.add( + var.set_current_temperature_multiplier(config[CONF_TEMPERATURE_MULTIPLIER]) + ) else: - cg.add(var.set_current_temperature_multiplier(config[CONF_CURRENT_TEMPERATURE_MULTIPLIER])) - cg.add(var.set_target_temperature_multiplier(config[CONF_TARGET_TEMPERATURE_MULTIPLIER])) + cg.add( + var.set_current_temperature_multiplier( + config[CONF_CURRENT_TEMPERATURE_MULTIPLIER] + ) + ) + cg.add( + var.set_target_temperature_multiplier( + config[CONF_TARGET_TEMPERATURE_MULTIPLIER] + ) + ) diff --git a/esphome/components/tuya/fan/__init__.py b/esphome/components/tuya/fan/__init__.py index e8492fd71..8615f3ae8 100644 --- a/esphome/components/tuya/fan/__init__.py +++ b/esphome/components/tuya/fan/__init__.py @@ -4,21 +4,25 @@ import esphome.codegen as cg from esphome.const import CONF_OUTPUT_ID, CONF_SWITCH_DATAPOINT from .. import tuya_ns, CONF_TUYA_ID, Tuya -DEPENDENCIES = ['tuya'] +DEPENDENCIES = ["tuya"] CONF_SPEED_DATAPOINT = "speed_datapoint" CONF_OSCILLATION_DATAPOINT = "oscillation_datapoint" -TuyaFan = tuya_ns.class_('TuyaFan', cg.Component) +TuyaFan = tuya_ns.class_("TuyaFan", cg.Component) -CONFIG_SCHEMA = cv.All(fan.FAN_SCHEMA.extend({ - cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(TuyaFan), - cv.GenerateID(CONF_TUYA_ID): cv.use_id(Tuya), - cv.Optional(CONF_OSCILLATION_DATAPOINT): cv.uint8_t, - cv.Optional(CONF_SPEED_DATAPOINT): cv.uint8_t, - cv.Optional(CONF_SWITCH_DATAPOINT): cv.uint8_t, -}).extend(cv.COMPONENT_SCHEMA), cv.has_at_least_one_key( - CONF_SPEED_DATAPOINT, CONF_SWITCH_DATAPOINT)) +CONFIG_SCHEMA = cv.All( + fan.FAN_SCHEMA.extend( + { + cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(TuyaFan), + cv.GenerateID(CONF_TUYA_ID): cv.use_id(Tuya), + cv.Optional(CONF_OSCILLATION_DATAPOINT): cv.uint8_t, + cv.Optional(CONF_SPEED_DATAPOINT): cv.uint8_t, + cv.Optional(CONF_SWITCH_DATAPOINT): cv.uint8_t, + } + ).extend(cv.COMPONENT_SCHEMA), + cv.has_at_least_one_key(CONF_SPEED_DATAPOINT, CONF_SWITCH_DATAPOINT), +) def to_code(config): diff --git a/esphome/components/tuya/light/__init__.py b/esphome/components/tuya/light/__init__.py index 05605822c..f8026e47e 100644 --- a/esphome/components/tuya/light/__init__.py +++ b/esphome/components/tuya/light/__init__.py @@ -1,32 +1,43 @@ from esphome.components import light import esphome.config_validation as cv import esphome.codegen as cg -from esphome.const import CONF_OUTPUT_ID, CONF_MIN_VALUE, CONF_MAX_VALUE, CONF_GAMMA_CORRECT, \ - CONF_DEFAULT_TRANSITION_LENGTH, CONF_SWITCH_DATAPOINT +from esphome.const import ( + CONF_OUTPUT_ID, + CONF_MIN_VALUE, + CONF_MAX_VALUE, + CONF_GAMMA_CORRECT, + CONF_DEFAULT_TRANSITION_LENGTH, + CONF_SWITCH_DATAPOINT, +) from .. import tuya_ns, CONF_TUYA_ID, Tuya -DEPENDENCIES = ['tuya'] +DEPENDENCIES = ["tuya"] CONF_DIMMER_DATAPOINT = "dimmer_datapoint" CONF_MIN_VALUE_DATAPOINT = "min_value_datapoint" -TuyaLight = tuya_ns.class_('TuyaLight', light.LightOutput, cg.Component) +TuyaLight = tuya_ns.class_("TuyaLight", light.LightOutput, cg.Component) -CONFIG_SCHEMA = cv.All(light.BRIGHTNESS_ONLY_LIGHT_SCHEMA.extend({ - cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(TuyaLight), - cv.GenerateID(CONF_TUYA_ID): cv.use_id(Tuya), - cv.Optional(CONF_DIMMER_DATAPOINT): cv.uint8_t, - cv.Optional(CONF_MIN_VALUE_DATAPOINT): cv.uint8_t, - cv.Optional(CONF_SWITCH_DATAPOINT): cv.uint8_t, - cv.Optional(CONF_MIN_VALUE): cv.int_, - cv.Optional(CONF_MAX_VALUE): cv.int_, - - # Change the default gamma_correct and default transition length settings. - # The Tuya MCU handles transitions and gamma correction on its own. - cv.Optional(CONF_GAMMA_CORRECT, default=1.0): cv.positive_float, - cv.Optional(CONF_DEFAULT_TRANSITION_LENGTH, default='0s'): cv.positive_time_period_milliseconds, -}).extend(cv.COMPONENT_SCHEMA), cv.has_at_least_one_key(CONF_DIMMER_DATAPOINT, - CONF_SWITCH_DATAPOINT)) +CONFIG_SCHEMA = cv.All( + light.BRIGHTNESS_ONLY_LIGHT_SCHEMA.extend( + { + cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(TuyaLight), + cv.GenerateID(CONF_TUYA_ID): cv.use_id(Tuya), + cv.Optional(CONF_DIMMER_DATAPOINT): cv.uint8_t, + cv.Optional(CONF_MIN_VALUE_DATAPOINT): cv.uint8_t, + cv.Optional(CONF_SWITCH_DATAPOINT): cv.uint8_t, + cv.Optional(CONF_MIN_VALUE): cv.int_, + cv.Optional(CONF_MAX_VALUE): cv.int_, + # Change the default gamma_correct and default transition length settings. + # The Tuya MCU handles transitions and gamma correction on its own. + cv.Optional(CONF_GAMMA_CORRECT, default=1.0): cv.positive_float, + cv.Optional( + CONF_DEFAULT_TRANSITION_LENGTH, default="0s" + ): cv.positive_time_period_milliseconds, + } + ).extend(cv.COMPONENT_SCHEMA), + cv.has_at_least_one_key(CONF_DIMMER_DATAPOINT, CONF_SWITCH_DATAPOINT), +) def to_code(config): diff --git a/esphome/components/tuya/sensor/__init__.py b/esphome/components/tuya/sensor/__init__.py index b3260bfe0..0a02fb77a 100644 --- a/esphome/components/tuya/sensor/__init__.py +++ b/esphome/components/tuya/sensor/__init__.py @@ -4,18 +4,20 @@ import esphome.codegen as cg from esphome.const import CONF_ID from .. import tuya_ns, CONF_TUYA_ID, Tuya -DEPENDENCIES = ['tuya'] -CODEOWNERS = ['@jesserockz'] +DEPENDENCIES = ["tuya"] +CODEOWNERS = ["@jesserockz"] CONF_SENSOR_DATAPOINT = "sensor_datapoint" -TuyaSensor = tuya_ns.class_('TuyaSensor', sensor.Sensor, cg.Component) +TuyaSensor = tuya_ns.class_("TuyaSensor", sensor.Sensor, cg.Component) -CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(TuyaSensor), - cv.GenerateID(CONF_TUYA_ID): cv.use_id(Tuya), - cv.Required(CONF_SENSOR_DATAPOINT): cv.uint8_t, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(TuyaSensor), + cv.GenerateID(CONF_TUYA_ID): cv.use_id(Tuya), + cv.Required(CONF_SENSOR_DATAPOINT): cv.uint8_t, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/tuya/switch/__init__.py b/esphome/components/tuya/switch/__init__.py index f68bbbcdb..4c4ccbf81 100644 --- a/esphome/components/tuya/switch/__init__.py +++ b/esphome/components/tuya/switch/__init__.py @@ -4,16 +4,18 @@ import esphome.codegen as cg from esphome.const import CONF_ID, CONF_SWITCH_DATAPOINT from .. import tuya_ns, CONF_TUYA_ID, Tuya -DEPENDENCIES = ['tuya'] -CODEOWNERS = ['@jesserockz'] +DEPENDENCIES = ["tuya"] +CODEOWNERS = ["@jesserockz"] -TuyaSwitch = tuya_ns.class_('TuyaSwitch', switch.Switch, cg.Component) +TuyaSwitch = tuya_ns.class_("TuyaSwitch", switch.Switch, cg.Component) -CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(TuyaSwitch), - cv.GenerateID(CONF_TUYA_ID): cv.use_id(Tuya), - cv.Required(CONF_SWITCH_DATAPOINT): cv.uint8_t, -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(TuyaSwitch), + cv.GenerateID(CONF_TUYA_ID): cv.use_id(Tuya), + cv.Required(CONF_SWITCH_DATAPOINT): cv.uint8_t, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/tx20/sensor.py b/esphome/components/tx20/sensor.py index 060bd233b..434257470 100644 --- a/esphome/components/tx20/sensor.py +++ b/esphome/components/tx20/sensor.py @@ -2,22 +2,35 @@ 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_WIND_SPEED, CONF_PIN, \ - CONF_WIND_DIRECTION_DEGREES, DEVICE_CLASS_EMPTY, UNIT_KILOMETER_PER_HOUR, \ - ICON_WEATHER_WINDY, ICON_SIGN_DIRECTION, UNIT_DEGREES +from esphome.const import ( + CONF_ID, + CONF_WIND_SPEED, + CONF_PIN, + CONF_WIND_DIRECTION_DEGREES, + DEVICE_CLASS_EMPTY, + UNIT_KILOMETER_PER_HOUR, + ICON_WEATHER_WINDY, + ICON_SIGN_DIRECTION, + UNIT_DEGREES, +) -tx20_ns = cg.esphome_ns.namespace('tx20') -Tx20Component = tx20_ns.class_('Tx20Component', cg.Component) +tx20_ns = cg.esphome_ns.namespace("tx20") +Tx20Component = tx20_ns.class_("Tx20Component", cg.Component) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(Tx20Component), - cv.Optional(CONF_WIND_SPEED): - sensor.sensor_schema(UNIT_KILOMETER_PER_HOUR, ICON_WEATHER_WINDY, 1, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_WIND_DIRECTION_DEGREES): - sensor.sensor_schema(UNIT_DEGREES, ICON_SIGN_DIRECTION, 1, DEVICE_CLASS_EMPTY), - cv.Required(CONF_PIN): cv.All(pins.internal_gpio_input_pin_schema, - pins.validate_has_interrupt), -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(Tx20Component), + cv.Optional(CONF_WIND_SPEED): sensor.sensor_schema( + UNIT_KILOMETER_PER_HOUR, ICON_WEATHER_WINDY, 1, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_WIND_DIRECTION_DEGREES): sensor.sensor_schema( + UNIT_DEGREES, ICON_SIGN_DIRECTION, 1, DEVICE_CLASS_EMPTY + ), + cv.Required(CONF_PIN): cv.All( + pins.internal_gpio_input_pin_schema, pins.validate_has_interrupt + ), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/uart/__init__.py b/esphome/components/uart/__init__.py index b3f94a471..a02ea58de 100644 --- a/esphome/components/uart/__init__.py +++ b/esphome/components/uart/__init__.py @@ -1,26 +1,36 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins, automation -from esphome.const import CONF_BAUD_RATE, CONF_ID, CONF_RX_PIN, CONF_TX_PIN, CONF_UART_ID, \ - CONF_DATA, CONF_RX_BUFFER_SIZE, CONF_INVERT +from esphome.const import ( + CONF_BAUD_RATE, + CONF_ID, + CONF_RX_PIN, + CONF_TX_PIN, + CONF_UART_ID, + CONF_DATA, + CONF_RX_BUFFER_SIZE, + CONF_INVERT, +) from esphome.core import CORE, coroutine -CODEOWNERS = ['@esphome/core'] -uart_ns = cg.esphome_ns.namespace('uart') -UARTComponent = uart_ns.class_('UARTComponent', cg.Component) -UARTDevice = uart_ns.class_('UARTDevice') -UARTWriteAction = uart_ns.class_('UARTWriteAction', automation.Action) +CODEOWNERS = ["@esphome/core"] +uart_ns = cg.esphome_ns.namespace("uart") +UARTComponent = uart_ns.class_("UARTComponent", cg.Component) +UARTDevice = uart_ns.class_("UARTDevice") +UARTWriteAction = uart_ns.class_("UARTWriteAction", automation.Action) MULTI_CONF = True def validate_raw_data(value): if isinstance(value, str): - return value.encode('utf-8') + return value.encode("utf-8") if isinstance(value, str): return value 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" + ) def validate_rx_pin(value): @@ -30,29 +40,37 @@ def validate_rx_pin(value): return value -UARTParityOptions = uart_ns.enum('UARTParityOptions') +UARTParityOptions = uart_ns.enum("UARTParityOptions") UART_PARITY_OPTIONS = { - 'NONE': UARTParityOptions.UART_CONFIG_PARITY_NONE, - 'EVEN': UARTParityOptions.UART_CONFIG_PARITY_EVEN, - 'ODD': UARTParityOptions.UART_CONFIG_PARITY_ODD, + "NONE": UARTParityOptions.UART_CONFIG_PARITY_NONE, + "EVEN": UARTParityOptions.UART_CONFIG_PARITY_EVEN, + "ODD": UARTParityOptions.UART_CONFIG_PARITY_ODD, } -CONF_STOP_BITS = 'stop_bits' -CONF_DATA_BITS = 'data_bits' -CONF_PARITY = 'parity' +CONF_STOP_BITS = "stop_bits" +CONF_DATA_BITS = "data_bits" +CONF_PARITY = "parity" -CONFIG_SCHEMA = cv.All(cv.Schema({ - cv.GenerateID(): cv.declare_id(UARTComponent), - cv.Required(CONF_BAUD_RATE): cv.int_range(min=1), - cv.Optional(CONF_TX_PIN): pins.output_pin, - cv.Optional(CONF_RX_PIN): validate_rx_pin, - cv.Optional(CONF_RX_BUFFER_SIZE, default=256): cv.validate_bytes, - cv.SplitDefault(CONF_INVERT, esp32=False): cv.All(cv.only_on_esp32, - cv.boolean), - cv.Optional(CONF_STOP_BITS, default=1): cv.one_of(1, 2, int=True), - cv.Optional(CONF_DATA_BITS, default=8): cv.int_range(min=5, max=8), - cv.Optional(CONF_PARITY, default="NONE"): cv.enum(UART_PARITY_OPTIONS, upper=True) -}).extend(cv.COMPONENT_SCHEMA), cv.has_at_least_one_key(CONF_TX_PIN, CONF_RX_PIN)) +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(UARTComponent), + cv.Required(CONF_BAUD_RATE): cv.int_range(min=1), + cv.Optional(CONF_TX_PIN): pins.output_pin, + cv.Optional(CONF_RX_PIN): validate_rx_pin, + cv.Optional(CONF_RX_BUFFER_SIZE, default=256): cv.validate_bytes, + cv.SplitDefault(CONF_INVERT, esp32=False): cv.All( + cv.only_on_esp32, cv.boolean + ), + cv.Optional(CONF_STOP_BITS, default=1): cv.one_of(1, 2, int=True), + cv.Optional(CONF_DATA_BITS, default=8): cv.int_range(min=5, max=8), + cv.Optional(CONF_PARITY, default="NONE"): cv.enum( + UART_PARITY_OPTIONS, upper=True + ), + } + ).extend(cv.COMPONENT_SCHEMA), + cv.has_at_least_one_key(CONF_TX_PIN, CONF_RX_PIN), +) def to_code(config): @@ -75,9 +93,11 @@ def to_code(config): # A schema to use for all UART devices, all UART integrations must extend this! -UART_DEVICE_SCHEMA = cv.Schema({ - cv.GenerateID(CONF_UART_ID): cv.use_id(UARTComponent), -}) +UART_DEVICE_SCHEMA = cv.Schema( + { + cv.GenerateID(CONF_UART_ID): cv.use_id(UARTComponent), + } +) @coroutine @@ -90,10 +110,17 @@ def register_uart_device(var, config): cg.add(var.set_uart_parent(parent)) -@automation.register_action('uart.write', UARTWriteAction, cv.maybe_simple_value({ - cv.GenerateID(): cv.use_id(UARTComponent), - cv.Required(CONF_DATA): cv.templatable(validate_raw_data), -}, key=CONF_DATA)) +@automation.register_action( + "uart.write", + UARTWriteAction, + cv.maybe_simple_value( + { + cv.GenerateID(): cv.use_id(UARTComponent), + cv.Required(CONF_DATA): cv.templatable(validate_raw_data), + }, + key=CONF_DATA, + ), +) def uart_write_to_code(config, action_id, template_arg, args): var = cg.new_Pvariable(action_id, template_arg) yield cg.register_parented(var, config[CONF_ID]) diff --git a/esphome/components/uart/switch/__init__.py b/esphome/components/uart/switch/__init__.py index 0c9ebe56f..e84035aa3 100644 --- a/esphome/components/uart/switch/__init__.py +++ b/esphome/components/uart/switch/__init__.py @@ -5,17 +5,25 @@ from esphome.const import CONF_DATA, CONF_ID, CONF_INVERTED, CONF_SEND_EVERY from esphome.core import HexInt from .. import uart_ns, validate_raw_data -DEPENDENCIES = ['uart'] +DEPENDENCIES = ["uart"] -UARTSwitch = uart_ns.class_('UARTSwitch', switch.Switch, uart.UARTDevice, cg.Component) +UARTSwitch = uart_ns.class_("UARTSwitch", switch.Switch, uart.UARTDevice, cg.Component) -CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(UARTSwitch), - cv.Required(CONF_DATA): validate_raw_data, - cv.Optional(CONF_INVERTED): cv.invalid("UART switches do not support inverted mode!"), - cv.Optional(CONF_SEND_EVERY): cv.positive_time_period_milliseconds, -}).extend(uart.UART_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + switch.SWITCH_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(UARTSwitch), + cv.Required(CONF_DATA): validate_raw_data, + cv.Optional(CONF_INVERTED): cv.invalid( + "UART switches do not support inverted mode!" + ), + cv.Optional(CONF_SEND_EVERY): cv.positive_time_period_milliseconds, + } + ) + .extend(uart.UART_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/uln2003/stepper.py b/esphome/components/uln2003/stepper.py index 278fcf67e..4d2e5ab51 100644 --- a/esphome/components/uln2003/stepper.py +++ b/esphome/components/uln2003/stepper.py @@ -2,29 +2,40 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.components import stepper -from esphome.const import CONF_ID, CONF_PIN_A, CONF_PIN_B, CONF_PIN_C, CONF_PIN_D, \ - CONF_SLEEP_WHEN_DONE, CONF_STEP_MODE +from esphome.const import ( + CONF_ID, + CONF_PIN_A, + CONF_PIN_B, + CONF_PIN_C, + CONF_PIN_D, + CONF_SLEEP_WHEN_DONE, + CONF_STEP_MODE, +) -uln2003_ns = cg.esphome_ns.namespace('uln2003') -ULN2003StepMode = uln2003_ns.enum('ULN2003StepMode') +uln2003_ns = cg.esphome_ns.namespace("uln2003") +ULN2003StepMode = uln2003_ns.enum("ULN2003StepMode") STEP_MODES = { - 'FULL_STEP': ULN2003StepMode.ULN2003_STEP_MODE_FULL_STEP, - 'HALF_STEP': ULN2003StepMode.ULN2003_STEP_MODE_HALF_STEP, - 'WAVE_DRIVE': ULN2003StepMode.ULN2003_STEP_MODE_WAVE_DRIVE, + "FULL_STEP": ULN2003StepMode.ULN2003_STEP_MODE_FULL_STEP, + "HALF_STEP": ULN2003StepMode.ULN2003_STEP_MODE_HALF_STEP, + "WAVE_DRIVE": ULN2003StepMode.ULN2003_STEP_MODE_WAVE_DRIVE, } -ULN2003 = uln2003_ns.class_('ULN2003', stepper.Stepper, cg.Component) +ULN2003 = uln2003_ns.class_("ULN2003", stepper.Stepper, cg.Component) -CONFIG_SCHEMA = stepper.STEPPER_SCHEMA.extend({ - cv.Required(CONF_ID): cv.declare_id(ULN2003), - cv.Required(CONF_PIN_A): pins.gpio_output_pin_schema, - cv.Required(CONF_PIN_B): pins.gpio_output_pin_schema, - cv.Required(CONF_PIN_C): pins.gpio_output_pin_schema, - cv.Required(CONF_PIN_D): pins.gpio_output_pin_schema, - cv.Optional(CONF_SLEEP_WHEN_DONE, default=False): cv.boolean, - cv.Optional(CONF_STEP_MODE, default='FULL_STEP'): cv.enum(STEP_MODES, upper=True, space='_') -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = stepper.STEPPER_SCHEMA.extend( + { + cv.Required(CONF_ID): cv.declare_id(ULN2003), + cv.Required(CONF_PIN_A): pins.gpio_output_pin_schema, + cv.Required(CONF_PIN_B): pins.gpio_output_pin_schema, + cv.Required(CONF_PIN_C): pins.gpio_output_pin_schema, + cv.Required(CONF_PIN_D): pins.gpio_output_pin_schema, + cv.Optional(CONF_SLEEP_WHEN_DONE, default=False): cv.boolean, + cv.Optional(CONF_STEP_MODE, default="FULL_STEP"): cv.enum( + STEP_MODES, upper=True, space="_" + ), + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/ultrasonic/__init__.py b/esphome/components/ultrasonic/__init__.py index 6f14e1003..71a87b6ae 100644 --- a/esphome/components/ultrasonic/__init__.py +++ b/esphome/components/ultrasonic/__init__.py @@ -1 +1 @@ -CODEOWNERS = ['@OttoWinter'] +CODEOWNERS = ["@OttoWinter"] diff --git a/esphome/components/ultrasonic/sensor.py b/esphome/components/ultrasonic/sensor.py index 889044fc7..d5d8dec6f 100644 --- a/esphome/components/ultrasonic/sensor.py +++ b/esphome/components/ultrasonic/sensor.py @@ -2,30 +2,45 @@ 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_ECHO_PIN, CONF_ID, CONF_TRIGGER_PIN, \ - CONF_TIMEOUT, DEVICE_CLASS_EMPTY, UNIT_METER, ICON_ARROW_EXPAND_VERTICAL +from esphome.const import ( + CONF_ECHO_PIN, + CONF_ID, + CONF_TRIGGER_PIN, + CONF_TIMEOUT, + DEVICE_CLASS_EMPTY, + UNIT_METER, + ICON_ARROW_EXPAND_VERTICAL, +) -CONF_PULSE_TIME = 'pulse_time' +CONF_PULSE_TIME = "pulse_time" -ultrasonic_ns = cg.esphome_ns.namespace('ultrasonic') -UltrasonicSensorComponent = ultrasonic_ns.class_('UltrasonicSensorComponent', - sensor.Sensor, cg.PollingComponent) +ultrasonic_ns = cg.esphome_ns.namespace("ultrasonic") +UltrasonicSensorComponent = ultrasonic_ns.class_( + "UltrasonicSensorComponent", sensor.Sensor, cg.PollingComponent +) -CONFIG_SCHEMA = sensor.sensor_schema( - UNIT_METER, ICON_ARROW_EXPAND_VERTICAL, 2, DEVICE_CLASS_EMPTY -).extend({ - cv.GenerateID(): cv.declare_id(UltrasonicSensorComponent), - cv.Required(CONF_TRIGGER_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_ECHO_PIN): pins.internal_gpio_input_pin_schema, - - cv.Optional(CONF_TIMEOUT, default='2m'): cv.distance, - cv.Optional(CONF_PULSE_TIME, default='10us'): cv.positive_time_period_microseconds, - - cv.Optional('timeout_meter'): cv.invalid("The timeout_meter option has been renamed " - "to 'timeout' in 1.12."), - cv.Optional('timeout_time'): cv.invalid("The timeout_time option has been removed. Please " - "use 'timeout' in 1.12."), -}).extend(cv.polling_component_schema('60s')) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_METER, ICON_ARROW_EXPAND_VERTICAL, 2, DEVICE_CLASS_EMPTY) + .extend( + { + cv.GenerateID(): cv.declare_id(UltrasonicSensorComponent), + cv.Required(CONF_TRIGGER_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_ECHO_PIN): pins.internal_gpio_input_pin_schema, + cv.Optional(CONF_TIMEOUT, default="2m"): cv.distance, + cv.Optional( + CONF_PULSE_TIME, default="10us" + ): cv.positive_time_period_microseconds, + cv.Optional("timeout_meter"): cv.invalid( + "The timeout_meter option has been renamed " "to 'timeout' in 1.12." + ), + cv.Optional("timeout_time"): cv.invalid( + "The timeout_time option has been removed. Please " + "use 'timeout' in 1.12." + ), + } + ) + .extend(cv.polling_component_schema("60s")) +) def to_code(config): diff --git a/esphome/components/uptime/sensor.py b/esphome/components/uptime/sensor.py index 94d259d4b..c2e35ddfe 100644 --- a/esphome/components/uptime/sensor.py +++ b/esphome/components/uptime/sensor.py @@ -3,12 +3,18 @@ import esphome.config_validation as cv from esphome.components import sensor from esphome.const import CONF_ID, DEVICE_CLASS_EMPTY, UNIT_SECOND, ICON_TIMER -uptime_ns = cg.esphome_ns.namespace('uptime') -UptimeSensor = uptime_ns.class_('UptimeSensor', sensor.Sensor, cg.PollingComponent) +uptime_ns = cg.esphome_ns.namespace("uptime") +UptimeSensor = uptime_ns.class_("UptimeSensor", sensor.Sensor, cg.PollingComponent) -CONFIG_SCHEMA = sensor.sensor_schema(UNIT_SECOND, ICON_TIMER, 0, DEVICE_CLASS_EMPTY).extend({ - cv.GenerateID(): cv.declare_id(UptimeSensor), -}).extend(cv.polling_component_schema('60s')) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_SECOND, ICON_TIMER, 0, DEVICE_CLASS_EMPTY) + .extend( + { + cv.GenerateID(): cv.declare_id(UptimeSensor), + } + ) + .extend(cv.polling_component_schema("60s")) +) def to_code(config): diff --git a/esphome/components/version/__init__.py b/esphome/components/version/__init__.py index 63db7aee2..f70ffa952 100644 --- a/esphome/components/version/__init__.py +++ b/esphome/components/version/__init__.py @@ -1 +1 @@ -CODEOWNERS = ['@esphome/core'] +CODEOWNERS = ["@esphome/core"] diff --git a/esphome/components/version/text_sensor.py b/esphome/components/version/text_sensor.py index 01cf8ba30..711800136 100644 --- a/esphome/components/version/text_sensor.py +++ b/esphome/components/version/text_sensor.py @@ -3,14 +3,18 @@ import esphome.config_validation as cv from esphome.components import text_sensor from esphome.const import CONF_ID, CONF_ICON, ICON_NEW_BOX, CONF_HIDE_TIMESTAMP -version_ns = cg.esphome_ns.namespace('version') -VersionTextSensor = version_ns.class_('VersionTextSensor', text_sensor.TextSensor, cg.Component) +version_ns = cg.esphome_ns.namespace("version") +VersionTextSensor = version_ns.class_( + "VersionTextSensor", text_sensor.TextSensor, cg.Component +) -CONFIG_SCHEMA = text_sensor.TEXT_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(VersionTextSensor), - cv.Optional(CONF_ICON, default=ICON_NEW_BOX): text_sensor.icon, - cv.Optional(CONF_HIDE_TIMESTAMP, default=False): cv.boolean -}).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = text_sensor.TEXT_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(VersionTextSensor), + cv.Optional(CONF_ICON, default=ICON_NEW_BOX): text_sensor.icon, + cv.Optional(CONF_HIDE_TIMESTAMP, default=False): cv.boolean, + } +).extend(cv.COMPONENT_SCHEMA) def to_code(config): diff --git a/esphome/components/vl53l0x/sensor.py b/esphome/components/vl53l0x/sensor.py index 8fc6a0d88..309d4cf8b 100644 --- a/esphome/components/vl53l0x/sensor.py +++ b/esphome/components/vl53l0x/sensor.py @@ -1,18 +1,26 @@ 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, UNIT_METER, ICON_ARROW_EXPAND_VERTICAL, - CONF_ADDRESS, CONF_TIMEOUT, CONF_ENABLE_PIN) +from esphome.const import ( + CONF_ID, + DEVICE_CLASS_EMPTY, + UNIT_METER, + ICON_ARROW_EXPAND_VERTICAL, + CONF_ADDRESS, + CONF_TIMEOUT, + CONF_ENABLE_PIN, +) from esphome import pins -DEPENDENCIES = ['i2c'] +DEPENDENCIES = ["i2c"] -vl53l0x_ns = cg.esphome_ns.namespace('vl53l0x') -VL53L0XSensor = vl53l0x_ns.class_('VL53L0XSensor', sensor.Sensor, cg.PollingComponent, - i2c.I2CDevice) +vl53l0x_ns = cg.esphome_ns.namespace("vl53l0x") +VL53L0XSensor = vl53l0x_ns.class_( + "VL53L0XSensor", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice +) -CONF_SIGNAL_RATE_LIMIT = 'signal_rate_limit' -CONF_LONG_RANGE = 'long_range' +CONF_SIGNAL_RATE_LIMIT = "signal_rate_limit" +CONF_LONG_RANGE = "long_range" def check_keys(obj): @@ -32,14 +40,22 @@ def check_timeout(value): CONFIG_SCHEMA = cv.All( - sensor.sensor_schema(UNIT_METER, ICON_ARROW_EXPAND_VERTICAL, 2, DEVICE_CLASS_EMPTY).extend({ - cv.GenerateID(): cv.declare_id(VL53L0XSensor), - cv.Optional(CONF_SIGNAL_RATE_LIMIT, default=0.25): cv.float_range( - min=0.0, max=512.0, min_included=False, max_included=False), - cv.Optional(CONF_LONG_RANGE, default=False): cv.boolean, - cv.Optional(CONF_TIMEOUT, default='10ms'): check_timeout, - cv.Optional(CONF_ENABLE_PIN): pins.gpio_output_pin_schema, - }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x29)), check_keys) + sensor.sensor_schema(UNIT_METER, ICON_ARROW_EXPAND_VERTICAL, 2, DEVICE_CLASS_EMPTY) + .extend( + { + cv.GenerateID(): cv.declare_id(VL53L0XSensor), + cv.Optional(CONF_SIGNAL_RATE_LIMIT, default=0.25): cv.float_range( + min=0.0, max=512.0, min_included=False, max_included=False + ), + cv.Optional(CONF_LONG_RANGE, default=False): cv.boolean, + cv.Optional(CONF_TIMEOUT, default="10ms"): check_timeout, + cv.Optional(CONF_ENABLE_PIN): pins.gpio_output_pin_schema, + } + ) + .extend(cv.polling_component_schema("60s")) + .extend(i2c.i2c_device_schema(0x29)), + check_keys, +) def to_code(config): diff --git a/esphome/components/voltage_sampler/__init__.py b/esphome/components/voltage_sampler/__init__.py index 64161205d..e60918096 100644 --- a/esphome/components/voltage_sampler/__init__.py +++ b/esphome/components/voltage_sampler/__init__.py @@ -1,4 +1,4 @@ import esphome.codegen as cg -voltage_sampler_ns = cg.esphome_ns.namespace('voltage_sampler') -VoltageSampler = voltage_sampler_ns.class_('VoltageSampler') +voltage_sampler_ns = cg.esphome_ns.namespace("voltage_sampler") +VoltageSampler = voltage_sampler_ns.class_("VoltageSampler") diff --git a/esphome/components/waveshare_epaper/display.py b/esphome/components/waveshare_epaper/display.py index fcbbc0a50..430022e54 100644 --- a/esphome/components/waveshare_epaper/display.py +++ b/esphome/components/waveshare_epaper/display.py @@ -2,68 +2,99 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome import pins from esphome.components import display, spi -from esphome.const import CONF_BUSY_PIN, CONF_DC_PIN, CONF_FULL_UPDATE_EVERY, \ - CONF_ID, CONF_LAMBDA, CONF_MODEL, CONF_PAGES, CONF_RESET_PIN +from esphome.const import ( + CONF_BUSY_PIN, + CONF_DC_PIN, + CONF_FULL_UPDATE_EVERY, + CONF_ID, + CONF_LAMBDA, + CONF_MODEL, + CONF_PAGES, + CONF_RESET_PIN, +) -DEPENDENCIES = ['spi'] +DEPENDENCIES = ["spi"] -waveshare_epaper_ns = cg.esphome_ns.namespace('waveshare_epaper') -WaveshareEPaper = waveshare_epaper_ns.class_('WaveshareEPaper', cg.PollingComponent, spi.SPIDevice, - display.DisplayBuffer) -WaveshareEPaperTypeA = waveshare_epaper_ns.class_('WaveshareEPaperTypeA', WaveshareEPaper) -WaveshareEPaper2P7In = waveshare_epaper_ns.class_('WaveshareEPaper2P7In', WaveshareEPaper) -WaveshareEPaper2P9InB = waveshare_epaper_ns.class_('WaveshareEPaper2P9InB', WaveshareEPaper) -WaveshareEPaper4P2In = waveshare_epaper_ns.class_('WaveshareEPaper4P2In', WaveshareEPaper) -WaveshareEPaper5P8In = waveshare_epaper_ns.class_('WaveshareEPaper5P8In', WaveshareEPaper) -WaveshareEPaper7P5In = waveshare_epaper_ns.class_('WaveshareEPaper7P5In', WaveshareEPaper) -WaveshareEPaper7P5InV2 = waveshare_epaper_ns.class_('WaveshareEPaper7P5InV2', WaveshareEPaper) +waveshare_epaper_ns = cg.esphome_ns.namespace("waveshare_epaper") +WaveshareEPaper = waveshare_epaper_ns.class_( + "WaveshareEPaper", cg.PollingComponent, spi.SPIDevice, display.DisplayBuffer +) +WaveshareEPaperTypeA = waveshare_epaper_ns.class_( + "WaveshareEPaperTypeA", WaveshareEPaper +) +WaveshareEPaper2P7In = waveshare_epaper_ns.class_( + "WaveshareEPaper2P7In", WaveshareEPaper +) +WaveshareEPaper2P9InB = waveshare_epaper_ns.class_( + "WaveshareEPaper2P9InB", WaveshareEPaper +) +WaveshareEPaper4P2In = waveshare_epaper_ns.class_( + "WaveshareEPaper4P2In", WaveshareEPaper +) +WaveshareEPaper5P8In = waveshare_epaper_ns.class_( + "WaveshareEPaper5P8In", WaveshareEPaper +) +WaveshareEPaper7P5In = waveshare_epaper_ns.class_( + "WaveshareEPaper7P5In", WaveshareEPaper +) +WaveshareEPaper7P5InV2 = waveshare_epaper_ns.class_( + "WaveshareEPaper7P5InV2", WaveshareEPaper +) -WaveshareEPaperTypeAModel = waveshare_epaper_ns.enum('WaveshareEPaperTypeAModel') -WaveshareEPaperTypeBModel = waveshare_epaper_ns.enum('WaveshareEPaperTypeBModel') +WaveshareEPaperTypeAModel = waveshare_epaper_ns.enum("WaveshareEPaperTypeAModel") +WaveshareEPaperTypeBModel = waveshare_epaper_ns.enum("WaveshareEPaperTypeBModel") MODELS = { - '1.54in': ('a', WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_1_54_IN), - '2.13in': ('a', WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_13_IN), - '2.13in-ttgo': ('a', WaveshareEPaperTypeAModel.TTGO_EPAPER_2_13_IN), - '2.13in-ttgo-b73': ('a', WaveshareEPaperTypeAModel.TTGO_EPAPER_2_13_IN_B73), - '2.90in': ('a', WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_9_IN), - '2.90inv2': ('a', WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_9_IN_V2), - '2.70in': ('b', WaveshareEPaper2P7In), - '2.90in-b': ('b', WaveshareEPaper2P9InB), - '4.20in': ('b', WaveshareEPaper4P2In), - '5.83in': ('b', WaveshareEPaper5P8In), - '7.50in': ('b', WaveshareEPaper7P5In), - '7.50inv2': ('b', WaveshareEPaper7P5InV2), + "1.54in": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_1_54_IN), + "2.13in": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_13_IN), + "2.13in-ttgo": ("a", WaveshareEPaperTypeAModel.TTGO_EPAPER_2_13_IN), + "2.13in-ttgo-b73": ("a", WaveshareEPaperTypeAModel.TTGO_EPAPER_2_13_IN_B73), + "2.90in": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_9_IN), + "2.90inv2": ("a", WaveshareEPaperTypeAModel.WAVESHARE_EPAPER_2_9_IN_V2), + "2.70in": ("b", WaveshareEPaper2P7In), + "2.90in-b": ("b", WaveshareEPaper2P9InB), + "4.20in": ("b", WaveshareEPaper4P2In), + "5.83in": ("b", WaveshareEPaper5P8In), + "7.50in": ("b", WaveshareEPaper7P5In), + "7.50inv2": ("b", WaveshareEPaper7P5InV2), } def validate_full_update_every_only_type_a(value): if CONF_FULL_UPDATE_EVERY not in value: return value - if MODELS[value[CONF_MODEL]][0] != 'a': - raise cv.Invalid("The 'full_update_every' option is only available for models " - "'1.54in', '2.13in', '2.90in', and '2.90inV2'.") + if MODELS[value[CONF_MODEL]][0] != "a": + raise cv.Invalid( + "The 'full_update_every' option is only available for models " + "'1.54in', '2.13in', '2.90in', and '2.90inV2'." + ) return value -CONFIG_SCHEMA = cv.All(display.FULL_DISPLAY_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(WaveshareEPaper), - cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, - cv.Required(CONF_MODEL): cv.one_of(*MODELS, lower=True), - cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, - cv.Optional(CONF_BUSY_PIN): pins.gpio_input_pin_schema, - cv.Optional(CONF_FULL_UPDATE_EVERY): cv.uint32_t, -}).extend(cv.polling_component_schema('1s')).extend(spi.spi_device_schema()), - validate_full_update_every_only_type_a, - cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA)) +CONFIG_SCHEMA = cv.All( + display.FULL_DISPLAY_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(WaveshareEPaper), + cv.Required(CONF_DC_PIN): pins.gpio_output_pin_schema, + cv.Required(CONF_MODEL): cv.one_of(*MODELS, lower=True), + cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, + cv.Optional(CONF_BUSY_PIN): pins.gpio_input_pin_schema, + cv.Optional(CONF_FULL_UPDATE_EVERY): cv.uint32_t, + } + ) + .extend(cv.polling_component_schema("1s")) + .extend(spi.spi_device_schema()), + validate_full_update_every_only_type_a, + cv.has_at_most_one_key(CONF_PAGES, CONF_LAMBDA), +) def to_code(config): model_type, model = MODELS[config[CONF_MODEL]] - if model_type == 'a': + if model_type == "a": rhs = WaveshareEPaperTypeA.new(model) var = cg.Pvariable(config[CONF_ID], rhs, WaveshareEPaperTypeA) - elif model_type == 'b': + elif model_type == "b": rhs = model.new() var = cg.Pvariable(config[CONF_ID], rhs, model) else: @@ -77,8 +108,9 @@ def to_code(config): cg.add(var.set_dc_pin(dc)) if CONF_LAMBDA in config: - lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], [(display.DisplayBufferRef, 'it')], - return_type=cg.void) + lambda_ = yield cg.process_lambda( + config[CONF_LAMBDA], [(display.DisplayBufferRef, "it")], return_type=cg.void + ) cg.add(var.set_writer(lambda_)) if CONF_RESET_PIN in config: reset = yield cg.gpio_pin_expression(config[CONF_RESET_PIN]) diff --git a/esphome/components/web_server/__init__.py b/esphome/components/web_server/__init__.py index 069b0a389..d04f2077f 100644 --- a/esphome/components/web_server/__init__.py +++ b/esphome/components/web_server/__init__.py @@ -3,29 +3,46 @@ import esphome.config_validation as cv from esphome.components import web_server_base from esphome.components.web_server_base import CONF_WEB_SERVER_BASE_ID from esphome.const import ( - CONF_CSS_INCLUDE, CONF_CSS_URL, CONF_ID, CONF_JS_INCLUDE, CONF_JS_URL, CONF_PORT, - CONF_AUTH, CONF_USERNAME, CONF_PASSWORD) + CONF_CSS_INCLUDE, + CONF_CSS_URL, + CONF_ID, + CONF_JS_INCLUDE, + CONF_JS_URL, + CONF_PORT, + CONF_AUTH, + CONF_USERNAME, + CONF_PASSWORD, +) from esphome.core import coroutine_with_priority -AUTO_LOAD = ['json', 'web_server_base'] +AUTO_LOAD = ["json", "web_server_base"] -web_server_ns = cg.esphome_ns.namespace('web_server') -WebServer = web_server_ns.class_('WebServer', cg.Component, cg.Controller) +web_server_ns = cg.esphome_ns.namespace("web_server") +WebServer = web_server_ns.class_("WebServer", cg.Component, cg.Controller) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(WebServer), - cv.Optional(CONF_PORT, default=80): cv.port, - cv.Optional(CONF_CSS_URL, default="https://esphome.io/_static/webserver-v1.min.css"): cv.string, - cv.Optional(CONF_CSS_INCLUDE): cv.file_, - cv.Optional(CONF_JS_URL, default="https://esphome.io/_static/webserver-v1.min.js"): cv.string, - cv.Optional(CONF_JS_INCLUDE): cv.file_, - cv.Optional(CONF_AUTH): cv.Schema({ - cv.Required(CONF_USERNAME): cv.string_strict, - cv.Required(CONF_PASSWORD): cv.string_strict, - }), - - 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(WebServer), + cv.Optional(CONF_PORT, default=80): cv.port, + cv.Optional( + CONF_CSS_URL, default="https://esphome.io/_static/webserver-v1.min.css" + ): cv.string, + cv.Optional(CONF_CSS_INCLUDE): cv.file_, + cv.Optional( + CONF_JS_URL, default="https://esphome.io/_static/webserver-v1.min.js" + ): cv.string, + cv.Optional(CONF_JS_INCLUDE): cv.file_, + cv.Optional(CONF_AUTH): cv.Schema( + { + cv.Required(CONF_USERNAME): cv.string_strict, + cv.Required(CONF_PASSWORD): cv.string_strict, + } + ), + cv.GenerateID(CONF_WEB_SERVER_BASE_ID): cv.use_id( + web_server_base.WebServerBase + ), + } +).extend(cv.COMPONENT_SCHEMA) @coroutine_with_priority(40.0) @@ -36,17 +53,17 @@ def to_code(config): yield cg.register_component(var, config) cg.add(paren.set_port(config[CONF_PORT])) - cg.add_define('WEBSERVER_PORT', config[CONF_PORT]) + cg.add_define("WEBSERVER_PORT", config[CONF_PORT]) cg.add(var.set_css_url(config[CONF_CSS_URL])) cg.add(var.set_js_url(config[CONF_JS_URL])) if CONF_AUTH in config: cg.add(var.set_username(config[CONF_AUTH][CONF_USERNAME])) cg.add(var.set_password(config[CONF_AUTH][CONF_PASSWORD])) if CONF_CSS_INCLUDE in config: - cg.add_define('WEBSERVER_CSS_INCLUDE') + cg.add_define("WEBSERVER_CSS_INCLUDE") with open(config[CONF_CSS_INCLUDE], "r") as myfile: cg.add(var.set_css_include(myfile.read())) if CONF_JS_INCLUDE in config: - cg.add_define('WEBSERVER_JS_INCLUDE') + cg.add_define("WEBSERVER_JS_INCLUDE") with open(config[CONF_JS_INCLUDE], "r") as myfile: cg.add(var.set_js_include(myfile.read())) diff --git a/esphome/components/web_server_base/__init__.py b/esphome/components/web_server_base/__init__.py index 05f4a4a4c..09f5dacd7 100644 --- a/esphome/components/web_server_base/__init__.py +++ b/esphome/components/web_server_base/__init__.py @@ -3,17 +3,19 @@ import esphome.codegen as cg from esphome.const import CONF_ID from esphome.core import coroutine_with_priority, CORE -CODEOWNERS = ['@OttoWinter'] -DEPENDENCIES = ['network'] -AUTO_LOAD = ['async_tcp'] +CODEOWNERS = ["@OttoWinter"] +DEPENDENCIES = ["network"] +AUTO_LOAD = ["async_tcp"] -web_server_base_ns = cg.esphome_ns.namespace('web_server_base') -WebServerBase = web_server_base_ns.class_('WebServerBase', cg.Component) +web_server_base_ns = cg.esphome_ns.namespace("web_server_base") +WebServerBase = web_server_base_ns.class_("WebServerBase", cg.Component) -CONF_WEB_SERVER_BASE_ID = 'web_server_base_id' -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(WebServerBase), -}) +CONF_WEB_SERVER_BASE_ID = "web_server_base_id" +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(WebServerBase), + } +) @coroutine_with_priority(65.0) @@ -22,6 +24,6 @@ def to_code(config): yield cg.register_component(var, config) if CORE.is_esp32: - cg.add_library('FS', None) + cg.add_library("FS", None) # https://github.com/OttoWinter/ESPAsyncWebServer/blob/master/library.json - cg.add_library('ESPAsyncWebServer-esphome', '1.2.7') + cg.add_library("ESPAsyncWebServer-esphome", "1.2.7") diff --git a/esphome/components/whirlpool/climate.py b/esphome/components/whirlpool/climate.py index 1fd62b411..d6d9f3e11 100644 --- a/esphome/components/whirlpool/climate.py +++ b/esphome/components/whirlpool/climate.py @@ -3,22 +3,24 @@ import esphome.config_validation as cv from esphome.components import climate_ir from esphome.const import CONF_ID, CONF_MODEL -AUTO_LOAD = ['climate_ir'] -CODEOWNERS = ['@glmnet'] +AUTO_LOAD = ["climate_ir"] +CODEOWNERS = ["@glmnet"] -whirlpool_ns = cg.esphome_ns.namespace('whirlpool') -WhirlpoolClimate = whirlpool_ns.class_('WhirlpoolClimate', climate_ir.ClimateIR) +whirlpool_ns = cg.esphome_ns.namespace("whirlpool") +WhirlpoolClimate = whirlpool_ns.class_("WhirlpoolClimate", climate_ir.ClimateIR) -Model = whirlpool_ns.enum('Model') +Model = whirlpool_ns.enum("Model") MODELS = { - 'DG11J1-3A': Model.MODEL_DG11J1_3A, - 'DG11J1-91': Model.MODEL_DG11J1_91, + "DG11J1-3A": Model.MODEL_DG11J1_3A, + "DG11J1-91": Model.MODEL_DG11J1_91, } -CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(WhirlpoolClimate), - cv.Optional(CONF_MODEL, default='DG11J1-3A'): cv.enum(MODELS, upper=True) -}) +CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(WhirlpoolClimate), + cv.Optional(CONF_MODEL, default="DG11J1-3A"): cv.enum(MODELS, upper=True), + } +) def to_code(config): diff --git a/esphome/components/wifi/__init__.py b/esphome/components/wifi/__init__.py index 4fe6929d7..f5b7340ad 100644 --- a/esphome/components/wifi/__init__.py +++ b/esphome/components/wifi/__init__.py @@ -2,31 +2,54 @@ 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_AP, CONF_BSSID, CONF_CHANNEL, CONF_DNS1, CONF_DNS2, CONF_DOMAIN, \ - CONF_FAST_CONNECT, CONF_GATEWAY, CONF_HIDDEN, CONF_ID, CONF_MANUAL_IP, CONF_NETWORKS, \ - CONF_PASSWORD, CONF_POWER_SAVE_MODE, CONF_REBOOT_TIMEOUT, CONF_SSID, CONF_STATIC_IP, \ - CONF_SUBNET, CONF_USE_ADDRESS, CONF_PRIORITY, CONF_IDENTITY, CONF_CERTIFICATE_AUTHORITY, \ - CONF_CERTIFICATE, CONF_KEY, CONF_USERNAME, CONF_EAP +from esphome.const import ( + CONF_AP, + CONF_BSSID, + CONF_CHANNEL, + CONF_DNS1, + CONF_DNS2, + CONF_DOMAIN, + CONF_FAST_CONNECT, + CONF_GATEWAY, + CONF_HIDDEN, + CONF_ID, + CONF_MANUAL_IP, + CONF_NETWORKS, + CONF_PASSWORD, + CONF_POWER_SAVE_MODE, + CONF_REBOOT_TIMEOUT, + CONF_SSID, + CONF_STATIC_IP, + CONF_SUBNET, + CONF_USE_ADDRESS, + CONF_PRIORITY, + CONF_IDENTITY, + CONF_CERTIFICATE_AUTHORITY, + CONF_CERTIFICATE, + CONF_KEY, + CONF_USERNAME, + CONF_EAP, +) from esphome.core import CORE, HexInt, coroutine_with_priority from . import wpa2_eap -AUTO_LOAD = ['network'] +AUTO_LOAD = ["network"] -wifi_ns = cg.esphome_ns.namespace('wifi') -EAPAuth = wifi_ns.struct('EAPAuth') -IPAddress = cg.global_ns.class_('IPAddress') -ManualIP = wifi_ns.struct('ManualIP') -WiFiComponent = wifi_ns.class_('WiFiComponent', cg.Component) -WiFiAP = wifi_ns.struct('WiFiAP') +wifi_ns = cg.esphome_ns.namespace("wifi") +EAPAuth = wifi_ns.struct("EAPAuth") +IPAddress = cg.global_ns.class_("IPAddress") +ManualIP = wifi_ns.struct("ManualIP") +WiFiComponent = wifi_ns.class_("WiFiComponent", cg.Component) +WiFiAP = wifi_ns.struct("WiFiAP") -WiFiPowerSaveMode = wifi_ns.enum('WiFiPowerSaveMode') +WiFiPowerSaveMode = wifi_ns.enum("WiFiPowerSaveMode") WIFI_POWER_SAVE_MODES = { - 'NONE': WiFiPowerSaveMode.WIFI_POWER_SAVE_NONE, - 'LIGHT': WiFiPowerSaveMode.WIFI_POWER_SAVE_LIGHT, - 'HIGH': WiFiPowerSaveMode.WIFI_POWER_SAVE_HIGH, + "NONE": WiFiPowerSaveMode.WIFI_POWER_SAVE_NONE, + "LIGHT": WiFiPowerSaveMode.WIFI_POWER_SAVE_LIGHT, + "HIGH": WiFiPowerSaveMode.WIFI_POWER_SAVE_HIGH, } -WiFiConnectedCondition = wifi_ns.class_('WiFiConnectedCondition', Condition) +WiFiConnectedCondition = wifi_ns.class_("WiFiConnectedCondition", Condition) def validate_password(value): @@ -49,47 +72,67 @@ def validate_channel(value): return value -AP_MANUAL_IP_SCHEMA = cv.Schema({ - cv.Required(CONF_STATIC_IP): cv.ipv4, - cv.Required(CONF_GATEWAY): cv.ipv4, - cv.Required(CONF_SUBNET): cv.ipv4, -}) +AP_MANUAL_IP_SCHEMA = cv.Schema( + { + cv.Required(CONF_STATIC_IP): cv.ipv4, + cv.Required(CONF_GATEWAY): cv.ipv4, + cv.Required(CONF_SUBNET): cv.ipv4, + } +) -STA_MANUAL_IP_SCHEMA = AP_MANUAL_IP_SCHEMA.extend({ - cv.Optional(CONF_DNS1, default="0.0.0.0"): cv.ipv4, - cv.Optional(CONF_DNS2, default="0.0.0.0"): cv.ipv4, -}) +STA_MANUAL_IP_SCHEMA = AP_MANUAL_IP_SCHEMA.extend( + { + cv.Optional(CONF_DNS1, default="0.0.0.0"): cv.ipv4, + cv.Optional(CONF_DNS2, default="0.0.0.0"): cv.ipv4, + } +) -EAP_AUTH_SCHEMA = cv.All(cv.Schema({ - cv.Optional(CONF_IDENTITY): cv.string_strict, - cv.Optional(CONF_USERNAME): cv.string_strict, - cv.Optional(CONF_PASSWORD): cv.string_strict, - cv.Optional(CONF_CERTIFICATE_AUTHORITY): wpa2_eap.validate_certificate, - cv.Inclusive(CONF_CERTIFICATE, 'certificate_and_key'): wpa2_eap.validate_certificate, - # Only validate as file first because we need the password to load it - # Actual validation happens in validate_eap. - cv.Inclusive(CONF_KEY, 'certificate_and_key'): cv.file_, -}), wpa2_eap.validate_eap, cv.has_at_least_one_key(CONF_IDENTITY, CONF_CERTIFICATE)) +EAP_AUTH_SCHEMA = cv.All( + cv.Schema( + { + cv.Optional(CONF_IDENTITY): cv.string_strict, + cv.Optional(CONF_USERNAME): cv.string_strict, + cv.Optional(CONF_PASSWORD): cv.string_strict, + cv.Optional(CONF_CERTIFICATE_AUTHORITY): wpa2_eap.validate_certificate, + cv.Inclusive( + CONF_CERTIFICATE, "certificate_and_key" + ): wpa2_eap.validate_certificate, + # Only validate as file first because we need the password to load it + # Actual validation happens in validate_eap. + cv.Inclusive(CONF_KEY, "certificate_and_key"): cv.file_, + } + ), + wpa2_eap.validate_eap, + cv.has_at_least_one_key(CONF_IDENTITY, CONF_CERTIFICATE), +) -WIFI_NETWORK_BASE = cv.Schema({ - cv.GenerateID(): cv.declare_id(WiFiAP), - cv.Optional(CONF_SSID): cv.ssid, - cv.Optional(CONF_PASSWORD): validate_password, - cv.Optional(CONF_CHANNEL): validate_channel, - cv.Optional(CONF_MANUAL_IP): STA_MANUAL_IP_SCHEMA, -}) +WIFI_NETWORK_BASE = cv.Schema( + { + cv.GenerateID(): cv.declare_id(WiFiAP), + cv.Optional(CONF_SSID): cv.ssid, + cv.Optional(CONF_PASSWORD): validate_password, + cv.Optional(CONF_CHANNEL): validate_channel, + cv.Optional(CONF_MANUAL_IP): STA_MANUAL_IP_SCHEMA, + } +) -CONF_AP_TIMEOUT = 'ap_timeout' -WIFI_NETWORK_AP = WIFI_NETWORK_BASE.extend({ - cv.Optional(CONF_AP_TIMEOUT, default='1min'): cv.positive_time_period_milliseconds, -}) +CONF_AP_TIMEOUT = "ap_timeout" +WIFI_NETWORK_AP = WIFI_NETWORK_BASE.extend( + { + cv.Optional( + CONF_AP_TIMEOUT, default="1min" + ): cv.positive_time_period_milliseconds, + } +) -WIFI_NETWORK_STA = WIFI_NETWORK_BASE.extend({ - cv.Optional(CONF_BSSID): cv.mac_address, - cv.Optional(CONF_HIDDEN): cv.boolean, - cv.Optional(CONF_PRIORITY, default=0.0): cv.float_, - cv.Optional(CONF_EAP): EAP_AUTH_SCHEMA, -}) +WIFI_NETWORK_STA = WIFI_NETWORK_BASE.extend( + { + cv.Optional(CONF_BSSID): cv.mac_address, + cv.Optional(CONF_HIDDEN): cv.boolean, + cv.Optional(CONF_PRIORITY, default=0.0): cv.float_, + cv.Optional(CONF_EAP): EAP_AUTH_SCHEMA, + } +) def validate(config): @@ -105,13 +148,16 @@ def validate(config): if CONF_EAP in config: network[CONF_EAP] = config.pop(CONF_EAP) if CONF_NETWORKS in config: - raise cv.Invalid("You cannot use the 'ssid:' option together with 'networks:'. Please " - "copy your network into the 'networks:' key") + raise cv.Invalid( + "You cannot use the 'ssid:' option together with 'networks:'. Please " + "copy your network into the 'networks:' key" + ) config[CONF_NETWORKS] = cv.ensure_list(WIFI_NETWORK_STA)(network) if (CONF_NETWORKS not in config) and (CONF_AP not in config): - raise cv.Invalid("Please specify at least an SSID or an Access Point " - "to create.") + raise cv.Invalid( + "Please specify at least an SSID or an Access Point " "to create." + ) if config.get(CONF_FAST_CONNECT, False): networks = config.get(CONF_NETWORKS, []) @@ -130,28 +176,36 @@ def validate(config): return config -CONF_OUTPUT_POWER = 'output_power' -CONFIG_SCHEMA = cv.All(cv.Schema({ - cv.GenerateID(): cv.declare_id(WiFiComponent), - cv.Optional(CONF_NETWORKS): cv.ensure_list(WIFI_NETWORK_STA), - - cv.Optional(CONF_SSID): cv.ssid, - cv.Optional(CONF_PASSWORD): validate_password, - cv.Optional(CONF_MANUAL_IP): STA_MANUAL_IP_SCHEMA, - cv.Optional(CONF_EAP): EAP_AUTH_SCHEMA, - - cv.Optional(CONF_AP): WIFI_NETWORK_AP, - cv.Optional(CONF_DOMAIN, default='.local'): cv.domain_name, - cv.Optional(CONF_REBOOT_TIMEOUT, default='15min'): cv.positive_time_period_milliseconds, - cv.SplitDefault(CONF_POWER_SAVE_MODE, esp8266='none', esp32='light'): - cv.enum(WIFI_POWER_SAVE_MODES, upper=True), - cv.Optional(CONF_FAST_CONNECT, default=False): cv.boolean, - cv.Optional(CONF_USE_ADDRESS): cv.string_strict, - cv.SplitDefault(CONF_OUTPUT_POWER, esp8266=20.0): cv.All( - cv.decibel, cv.float_range(min=10.0, max=20.5)), - - cv.Optional('hostname'): cv.invalid("The hostname option has been removed in 1.11.0"), -}), validate) +CONF_OUTPUT_POWER = "output_power" +CONFIG_SCHEMA = cv.All( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(WiFiComponent), + cv.Optional(CONF_NETWORKS): cv.ensure_list(WIFI_NETWORK_STA), + cv.Optional(CONF_SSID): cv.ssid, + cv.Optional(CONF_PASSWORD): validate_password, + cv.Optional(CONF_MANUAL_IP): STA_MANUAL_IP_SCHEMA, + cv.Optional(CONF_EAP): EAP_AUTH_SCHEMA, + cv.Optional(CONF_AP): WIFI_NETWORK_AP, + cv.Optional(CONF_DOMAIN, default=".local"): cv.domain_name, + cv.Optional( + CONF_REBOOT_TIMEOUT, default="15min" + ): cv.positive_time_period_milliseconds, + cv.SplitDefault( + CONF_POWER_SAVE_MODE, esp8266="none", esp32="light" + ): cv.enum(WIFI_POWER_SAVE_MODES, upper=True), + cv.Optional(CONF_FAST_CONNECT, default=False): cv.boolean, + cv.Optional(CONF_USE_ADDRESS): cv.string_strict, + cv.SplitDefault(CONF_OUTPUT_POWER, esp8266=20.0): cv.All( + cv.decibel, cv.float_range(min=10.0, max=20.5) + ), + cv.Optional("hostname"): cv.invalid( + "The hostname option has been removed in 1.11.0" + ), + } + ), + validate, +) def eap_auth(config): @@ -168,12 +222,12 @@ def eap_auth(config): key = wpa2_eap.read_relative_config_path(config[CONF_KEY]) return cg.StructInitializer( EAPAuth, - ('identity', config.get(CONF_IDENTITY, "")), - ('username', config.get(CONF_USERNAME, "")), - ('password', config.get(CONF_PASSWORD, "")), - ('ca_cert', ca_cert), - ('client_cert', client_cert), - ('client_key', key), + ("identity", config.get(CONF_IDENTITY, "")), + ("username", config.get(CONF_USERNAME, "")), + ("password", config.get(CONF_PASSWORD, "")), + ("ca_cert", ca_cert), + ("client_cert", client_cert), + ("client_key", key), ) @@ -188,11 +242,11 @@ def manual_ip(config): return None return cg.StructInitializer( ManualIP, - ('static_ip', safe_ip(config[CONF_STATIC_IP])), - ('gateway', safe_ip(config[CONF_GATEWAY])), - ('subnet', safe_ip(config[CONF_SUBNET])), - ('dns1', safe_ip(config.get(CONF_DNS1))), - ('dns2', safe_ip(config.get(CONF_DNS2))), + ("static_ip", safe_ip(config[CONF_STATIC_IP])), + ("gateway", safe_ip(config[CONF_GATEWAY])), + ("subnet", safe_ip(config[CONF_SUBNET])), + ("dns1", safe_ip(config.get(CONF_DNS1))), + ("dns2", safe_ip(config.get(CONF_DNS2))), ) @@ -204,7 +258,7 @@ def wifi_network(config, static_ip): cg.add(ap.set_password(config[CONF_PASSWORD])) if CONF_EAP in config: cg.add(ap.set_eap(eap_auth(config[CONF_EAP]))) - cg.add_define('ESPHOME_WIFI_WPA2_EAP') + cg.add_define("ESPHOME_WIFI_WPA2_EAP") if CONF_BSSID in config: cg.add(ap.set_bssid([HexInt(i) for i in config[CONF_BSSID].parts])) if CONF_HIDDEN in config: @@ -240,14 +294,14 @@ def to_code(config): cg.add(var.set_output_power(config[CONF_OUTPUT_POWER])) if CORE.is_esp8266: - cg.add_library('ESP8266WiFi', None) + cg.add_library("ESP8266WiFi", None) - cg.add_define('USE_WIFI') + cg.add_define("USE_WIFI") # Register at end for OTA safe mode yield cg.register_component(var, config) -@automation.register_condition('wifi.connected', WiFiConnectedCondition, cv.Schema({})) +@automation.register_condition("wifi.connected", WiFiConnectedCondition, cv.Schema({})) def wifi_connected_to_code(config, condition_id, template_arg, args): yield cg.new_Pvariable(condition_id, template_arg) diff --git a/esphome/components/wifi/wpa2_eap.py b/esphome/components/wifi/wpa2_eap.py index 54195c852..071737ccd 100644 --- a/esphome/components/wifi/wpa2_eap.py +++ b/esphome/components/wifi/wpa2_eap.py @@ -8,8 +8,13 @@ from pathlib import Path from esphome.core import CORE import esphome.config_validation as cv -from esphome.const import CONF_USERNAME, CONF_IDENTITY, CONF_PASSWORD, CONF_CERTIFICATE, \ - CONF_KEY +from esphome.const import ( + CONF_USERNAME, + CONF_IDENTITY, + CONF_PASSWORD, + CONF_CERTIFICATE, + CONF_KEY, +) _LOGGER = logging.getLogger(__name__) @@ -19,12 +24,16 @@ def validate_cryptography_installed(): try: import cryptography except ImportError as err: - raise cv.Invalid("This settings requires the cryptography python package. " - "Please install it with `pip install cryptography`") from err + raise cv.Invalid( + "This settings requires the cryptography python package. " + "Please install it with `pip install cryptography`" + ) from err - if cryptography.__version__[0] < '2': - raise cv.Invalid("Please update your python cryptography installation to least 2.x " - "(pip install -U cryptography)") + if cryptography.__version__[0] < "2": + raise cv.Invalid( + "Please update your python cryptography installation to least 2.x " + "(pip install -U cryptography)" + ) def wrapped_load_pem_x509_certificate(value): @@ -33,7 +42,7 @@ def wrapped_load_pem_x509_certificate(value): from cryptography import x509 from cryptography.hazmat.backends import default_backend - return x509.load_pem_x509_certificate(value.encode('UTF-8'), default_backend()) + return x509.load_pem_x509_certificate(value.encode("UTF-8"), default_backend()) def wrapped_load_pem_private_key(value, password): @@ -44,7 +53,7 @@ def wrapped_load_pem_private_key(value, password): if password: password = password.encode("UTF-8") - return load_pem_private_key(value.encode('UTF-8'), password, default_backend()) + return load_pem_private_key(value.encode("UTF-8"), password, default_backend()) def read_relative_config_path(value): @@ -72,7 +81,9 @@ def _validate_load_private_key(key, cert_pw): contents = read_relative_config_path(key) return wrapped_load_pem_private_key(contents, cert_pw) except ValueError as e: - raise cv.Invalid(f"There was an error with the EAP 'password:' provided for 'key' {e}") + raise cv.Invalid( + f"There was an error with the EAP 'password:' provided for 'key' {e}" + ) except TypeError as e: raise cv.Invalid(f"There was an error with the EAP 'key:' provided: {e}") @@ -95,10 +106,12 @@ def _check_private_key_cert_match(key, cert): # pylint: disable=no-name-in-module from cryptography.hazmat.primitives.asymmetric import ed448, ed25519 - private_key_types.update({ - ed448.Ed448PrivateKey: check_match_b, - ed25519.Ed25519PrivateKey: check_match_b, - }) + private_key_types.update( + { + ed448.Ed448PrivateKey: check_match_b, + ed25519.Ed25519PrivateKey: check_match_b, + } + ) except ImportError: # ed448, ed25519 not supported pass @@ -107,7 +120,7 @@ def _check_private_key_cert_match(key, cert): if key_type is None: _LOGGER.warning( "Unrecognised EAP 'certificate:' 'key:' pair format: %s. Proceed with caution!", - type(key) + type(key), ) elif not private_key_types[key_type](): raise cv.Invalid("The provided EAP 'key' is not valid for the 'certificate'.") @@ -120,8 +133,10 @@ def validate_eap(value): value = value.copy() value[CONF_IDENTITY] = value[CONF_USERNAME] if CONF_PASSWORD not in value: - raise cv.Invalid("You cannot use the EAP 'username:' option without a 'password:'. " - "Please provide the 'password:' key") + raise cv.Invalid( + "You cannot use the EAP 'username:' option without a 'password:'. " + "Please provide the 'password:' key" + ) if CONF_CERTIFICATE in value or CONF_KEY in value: # Check the key is valid and for this certificate, just to check the user hasn't pasted diff --git a/esphome/components/wifi_info/text_sensor.py b/esphome/components/wifi_info/text_sensor.py index 56670b417..07af63524 100644 --- a/esphome/components/wifi_info/text_sensor.py +++ b/esphome/components/wifi_info/text_sensor.py @@ -1,31 +1,53 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import text_sensor -from esphome.const import CONF_BSSID, CONF_ID, CONF_IP_ADDRESS, CONF_SSID, CONF_MAC_ADDRESS +from esphome.const import ( + CONF_BSSID, + CONF_ID, + CONF_IP_ADDRESS, + CONF_SSID, + CONF_MAC_ADDRESS, +) from esphome.core import coroutine -DEPENDENCIES = ['wifi'] +DEPENDENCIES = ["wifi"] -wifi_info_ns = cg.esphome_ns.namespace('wifi_info') -IPAddressWiFiInfo = wifi_info_ns.class_('IPAddressWiFiInfo', text_sensor.TextSensor, cg.Component) -SSIDWiFiInfo = wifi_info_ns.class_('SSIDWiFiInfo', text_sensor.TextSensor, cg.Component) -BSSIDWiFiInfo = wifi_info_ns.class_('BSSIDWiFiInfo', text_sensor.TextSensor, cg.Component) -MacAddressWifiInfo = wifi_info_ns.class_('MacAddressWifiInfo', text_sensor.TextSensor, cg.Component) +wifi_info_ns = cg.esphome_ns.namespace("wifi_info") +IPAddressWiFiInfo = wifi_info_ns.class_( + "IPAddressWiFiInfo", text_sensor.TextSensor, cg.Component +) +SSIDWiFiInfo = wifi_info_ns.class_("SSIDWiFiInfo", text_sensor.TextSensor, cg.Component) +BSSIDWiFiInfo = wifi_info_ns.class_( + "BSSIDWiFiInfo", text_sensor.TextSensor, cg.Component +) +MacAddressWifiInfo = wifi_info_ns.class_( + "MacAddressWifiInfo", text_sensor.TextSensor, cg.Component +) -CONFIG_SCHEMA = cv.Schema({ - cv.Optional(CONF_IP_ADDRESS): text_sensor.TEXT_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(IPAddressWiFiInfo), - }), - cv.Optional(CONF_SSID): text_sensor.TEXT_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(SSIDWiFiInfo), - }), - cv.Optional(CONF_BSSID): text_sensor.TEXT_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(BSSIDWiFiInfo), - }), - cv.Optional(CONF_MAC_ADDRESS): text_sensor.TEXT_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(MacAddressWifiInfo), - }) -}) +CONFIG_SCHEMA = cv.Schema( + { + cv.Optional(CONF_IP_ADDRESS): text_sensor.TEXT_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(IPAddressWiFiInfo), + } + ), + cv.Optional(CONF_SSID): text_sensor.TEXT_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(SSIDWiFiInfo), + } + ), + cv.Optional(CONF_BSSID): text_sensor.TEXT_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(BSSIDWiFiInfo), + } + ), + cv.Optional(CONF_MAC_ADDRESS): text_sensor.TEXT_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(MacAddressWifiInfo), + } + ), + } +) @coroutine diff --git a/esphome/components/wifi_signal/sensor.py b/esphome/components/wifi_signal/sensor.py index c1174fdec..f2a9f5408 100644 --- a/esphome/components/wifi_signal/sensor.py +++ b/esphome/components/wifi_signal/sensor.py @@ -1,17 +1,28 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor -from esphome.const import CONF_ID, DEVICE_CLASS_SIGNAL_STRENGTH, ICON_EMPTY, UNIT_DECIBEL +from esphome.const import ( + CONF_ID, + DEVICE_CLASS_SIGNAL_STRENGTH, + ICON_EMPTY, + UNIT_DECIBEL, +) -DEPENDENCIES = ['wifi'] -wifi_signal_ns = cg.esphome_ns.namespace('wifi_signal') -WiFiSignalSensor = wifi_signal_ns.class_('WiFiSignalSensor', sensor.Sensor, cg.PollingComponent) +DEPENDENCIES = ["wifi"] +wifi_signal_ns = cg.esphome_ns.namespace("wifi_signal") +WiFiSignalSensor = wifi_signal_ns.class_( + "WiFiSignalSensor", sensor.Sensor, cg.PollingComponent +) -CONFIG_SCHEMA = sensor.sensor_schema( - UNIT_DECIBEL, ICON_EMPTY, 0, DEVICE_CLASS_SIGNAL_STRENGTH -).extend({ - cv.GenerateID(): cv.declare_id(WiFiSignalSensor), -}).extend(cv.polling_component_schema('60s')) +CONFIG_SCHEMA = ( + sensor.sensor_schema(UNIT_DECIBEL, ICON_EMPTY, 0, DEVICE_CLASS_SIGNAL_STRENGTH) + .extend( + { + cv.GenerateID(): cv.declare_id(WiFiSignalSensor), + } + ) + .extend(cv.polling_component_schema("60s")) +) def to_code(config): diff --git a/esphome/components/wled/__init__.py b/esphome/components/wled/__init__.py index 1a248e530..31ec31828 100644 --- a/esphome/components/wled/__init__.py +++ b/esphome/components/wled/__init__.py @@ -4,15 +4,20 @@ from esphome.components.light.types import AddressableLightEffect from esphome.components.light.effects import register_addressable_effect from esphome.const import CONF_NAME, CONF_PORT -wled_ns = cg.esphome_ns.namespace('wled') -WLEDLightEffect = wled_ns.class_('WLEDLightEffect', AddressableLightEffect) +wled_ns = cg.esphome_ns.namespace("wled") +WLEDLightEffect = wled_ns.class_("WLEDLightEffect", AddressableLightEffect) CONFIG_SCHEMA = cv.Schema({}) -@register_addressable_effect('wled', WLEDLightEffect, "WLED", { - cv.Optional(CONF_PORT, default=21324): cv.port, -}) +@register_addressable_effect( + "wled", + WLEDLightEffect, + "WLED", + { + cv.Optional(CONF_PORT, default=21324): cv.port, + }, +) def wled_light_effect_to_code(config, effect_id): effect = cg.new_Pvariable(effect_id, config[CONF_NAME]) cg.add(effect.set_port(config[CONF_PORT])) diff --git a/esphome/components/xiaomi_ble/__init__.py b/esphome/components/xiaomi_ble/__init__.py index 2b3609029..3d11ea812 100644 --- a/esphome/components/xiaomi_ble/__init__.py +++ b/esphome/components/xiaomi_ble/__init__.py @@ -3,14 +3,18 @@ import esphome.config_validation as cv from esphome.components import esp32_ble_tracker from esphome.const import CONF_ID -DEPENDENCIES = ['esp32_ble_tracker'] +DEPENDENCIES = ["esp32_ble_tracker"] -xiaomi_ble_ns = cg.esphome_ns.namespace('xiaomi_ble') -XiaomiListener = xiaomi_ble_ns.class_('XiaomiListener', esp32_ble_tracker.ESPBTDeviceListener) +xiaomi_ble_ns = cg.esphome_ns.namespace("xiaomi_ble") +XiaomiListener = xiaomi_ble_ns.class_( + "XiaomiListener", esp32_ble_tracker.ESPBTDeviceListener +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(XiaomiListener), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(XiaomiListener), + } +).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) def to_code(config): diff --git a/esphome/components/xiaomi_cgd1/sensor.py b/esphome/components/xiaomi_cgd1/sensor.py index c84c99650..25d1f9367 100644 --- a/esphome/components/xiaomi_cgd1/sensor.py +++ b/esphome/components/xiaomi_cgd1/sensor.py @@ -1,28 +1,49 @@ 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_HUMIDITY, CONF_MAC_ADDRESS, CONF_TEMPERATURE, \ - CONF_ID, DEVICE_CLASS_BATTERY, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, \ - UNIT_CELSIUS, UNIT_PERCENT, CONF_BINDKEY +from esphome.const import ( + CONF_BATTERY_LEVEL, + CONF_HUMIDITY, + CONF_MAC_ADDRESS, + CONF_TEMPERATURE, + CONF_ID, + DEVICE_CLASS_BATTERY, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_TEMPERATURE, + ICON_EMPTY, + UNIT_CELSIUS, + UNIT_PERCENT, + CONF_BINDKEY, +) -DEPENDENCIES = ['esp32_ble_tracker'] -AUTO_LOAD = ['xiaomi_ble'] +DEPENDENCIES = ["esp32_ble_tracker"] +AUTO_LOAD = ["xiaomi_ble"] -xiaomi_cgd1_ns = cg.esphome_ns.namespace('xiaomi_cgd1') -XiaomiCGD1 = xiaomi_cgd1_ns.class_('XiaomiCGD1', esp32_ble_tracker.ESPBTDeviceListener, - cg.Component) +xiaomi_cgd1_ns = cg.esphome_ns.namespace("xiaomi_cgd1") +XiaomiCGD1 = xiaomi_cgd1_ns.class_( + "XiaomiCGD1", esp32_ble_tracker.ESPBTDeviceListener, cg.Component +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(XiaomiCGD1), - cv.Required(CONF_BINDKEY): cv.bind_key, - 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, 1, - DEVICE_CLASS_HUMIDITY), - cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 0, - DEVICE_CLASS_BATTERY), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(XiaomiCGD1), + cv.Required(CONF_BINDKEY): cv.bind_key, + 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, 1, DEVICE_CLASS_HUMIDITY + ), + cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema( + UNIT_PERCENT, ICON_EMPTY, 0, DEVICE_CLASS_BATTERY + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/xiaomi_cgg1/sensor.py b/esphome/components/xiaomi_cgg1/sensor.py index e78c503c9..6201df61b 100644 --- a/esphome/components/xiaomi_cgg1/sensor.py +++ b/esphome/components/xiaomi_cgg1/sensor.py @@ -1,27 +1,47 @@ 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_HUMIDITY, CONF_MAC_ADDRESS, CONF_TEMPERATURE, \ - CONF_ID, DEVICE_CLASS_BATTERY, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, \ - UNIT_CELSIUS, UNIT_PERCENT +from esphome.const import ( + CONF_BATTERY_LEVEL, + CONF_HUMIDITY, + CONF_MAC_ADDRESS, + CONF_TEMPERATURE, + CONF_ID, + DEVICE_CLASS_BATTERY, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_TEMPERATURE, + ICON_EMPTY, + UNIT_CELSIUS, + UNIT_PERCENT, +) -DEPENDENCIES = ['esp32_ble_tracker'] -AUTO_LOAD = ['xiaomi_ble'] +DEPENDENCIES = ["esp32_ble_tracker"] +AUTO_LOAD = ["xiaomi_ble"] -xiaomi_cgg1_ns = cg.esphome_ns.namespace('xiaomi_cgg1') +xiaomi_cgg1_ns = cg.esphome_ns.namespace("xiaomi_cgg1") XiaomiCGG1 = xiaomi_cgg1_ns.class_( - 'XiaomiCGG1', esp32_ble_tracker.ESPBTDeviceListener, cg.Component) + "XiaomiCGG1", esp32_ble_tracker.ESPBTDeviceListener, cg.Component +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(XiaomiCGG1), - 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, 1, - DEVICE_CLASS_HUMIDITY), - cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 0, - DEVICE_CLASS_BATTERY), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(XiaomiCGG1), + 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, 1, DEVICE_CLASS_HUMIDITY + ), + cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema( + UNIT_PERCENT, ICON_EMPTY, 0, DEVICE_CLASS_BATTERY + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/xiaomi_gcls002/sensor.py b/esphome/components/xiaomi_gcls002/sensor.py index 8f434b6a3..b83837115 100644 --- a/esphome/components/xiaomi_gcls002/sensor.py +++ b/esphome/components/xiaomi_gcls002/sensor.py @@ -1,30 +1,55 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, esp32_ble_tracker -from esphome.const import CONF_MAC_ADDRESS, CONF_TEMPERATURE, DEVICE_CLASS_EMPTY, \ - DEVICE_CLASS_ILLUMINANCE, DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, ICON_WATER_PERCENT, \ - UNIT_CELSIUS, UNIT_PERCENT, CONF_ID, CONF_MOISTURE, CONF_ILLUMINANCE, UNIT_LUX, \ - CONF_CONDUCTIVITY, UNIT_MICROSIEMENS_PER_CENTIMETER, ICON_FLOWER +from esphome.const import ( + CONF_MAC_ADDRESS, + CONF_TEMPERATURE, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_ILLUMINANCE, + DEVICE_CLASS_TEMPERATURE, + ICON_EMPTY, + ICON_WATER_PERCENT, + UNIT_CELSIUS, + UNIT_PERCENT, + CONF_ID, + CONF_MOISTURE, + CONF_ILLUMINANCE, + UNIT_LUX, + CONF_CONDUCTIVITY, + UNIT_MICROSIEMENS_PER_CENTIMETER, + ICON_FLOWER, +) -DEPENDENCIES = ['esp32_ble_tracker'] -AUTO_LOAD = ['xiaomi_ble'] +DEPENDENCIES = ["esp32_ble_tracker"] +AUTO_LOAD = ["xiaomi_ble"] -xiaomi_gcls002_ns = cg.esphome_ns.namespace('xiaomi_gcls002') -XiaomiGCLS002 = xiaomi_gcls002_ns.class_('XiaomiGCLS002', - esp32_ble_tracker.ESPBTDeviceListener, cg.Component) +xiaomi_gcls002_ns = cg.esphome_ns.namespace("xiaomi_gcls002") +XiaomiGCLS002 = xiaomi_gcls002_ns.class_( + "XiaomiGCLS002", esp32_ble_tracker.ESPBTDeviceListener, cg.Component +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(XiaomiGCLS002), - 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_MOISTURE): sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 0, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_ILLUMINANCE): sensor.sensor_schema(UNIT_LUX, ICON_EMPTY, 0, - DEVICE_CLASS_ILLUMINANCE), - cv.Optional(CONF_CONDUCTIVITY): - sensor.sensor_schema(UNIT_MICROSIEMENS_PER_CENTIMETER, ICON_FLOWER, 0, DEVICE_CLASS_EMPTY), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(XiaomiGCLS002), + 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_MOISTURE): sensor.sensor_schema( + UNIT_PERCENT, ICON_WATER_PERCENT, 0, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_ILLUMINANCE): sensor.sensor_schema( + UNIT_LUX, ICON_EMPTY, 0, DEVICE_CLASS_ILLUMINANCE + ), + cv.Optional(CONF_CONDUCTIVITY): sensor.sensor_schema( + UNIT_MICROSIEMENS_PER_CENTIMETER, ICON_FLOWER, 0, DEVICE_CLASS_EMPTY + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/xiaomi_hhccjcy01/sensor.py b/esphome/components/xiaomi_hhccjcy01/sensor.py index 960f652bb..f657ec937 100644 --- a/esphome/components/xiaomi_hhccjcy01/sensor.py +++ b/esphome/components/xiaomi_hhccjcy01/sensor.py @@ -1,33 +1,60 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, esp32_ble_tracker -from esphome.const import CONF_MAC_ADDRESS, CONF_TEMPERATURE, DEVICE_CLASS_EMPTY, \ - DEVICE_CLASS_ILLUMINANCE, DEVICE_CLASS_TEMPERATURE, ICON_EMPTY, ICON_WATER_PERCENT, \ - UNIT_CELSIUS, UNIT_PERCENT, CONF_ID, CONF_MOISTURE, CONF_ILLUMINANCE, UNIT_LUX, \ - CONF_CONDUCTIVITY, UNIT_MICROSIEMENS_PER_CENTIMETER, ICON_FLOWER, DEVICE_CLASS_BATTERY, \ - CONF_BATTERY_LEVEL +from esphome.const import ( + CONF_MAC_ADDRESS, + CONF_TEMPERATURE, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_ILLUMINANCE, + DEVICE_CLASS_TEMPERATURE, + ICON_EMPTY, + ICON_WATER_PERCENT, + UNIT_CELSIUS, + UNIT_PERCENT, + CONF_ID, + CONF_MOISTURE, + CONF_ILLUMINANCE, + UNIT_LUX, + CONF_CONDUCTIVITY, + UNIT_MICROSIEMENS_PER_CENTIMETER, + ICON_FLOWER, + DEVICE_CLASS_BATTERY, + CONF_BATTERY_LEVEL, +) -DEPENDENCIES = ['esp32_ble_tracker'] -AUTO_LOAD = ['xiaomi_ble'] +DEPENDENCIES = ["esp32_ble_tracker"] +AUTO_LOAD = ["xiaomi_ble"] -xiaomi_hhccjcy01_ns = cg.esphome_ns.namespace('xiaomi_hhccjcy01') -XiaomiHHCCJCY01 = xiaomi_hhccjcy01_ns.class_('XiaomiHHCCJCY01', - esp32_ble_tracker.ESPBTDeviceListener, cg.Component) +xiaomi_hhccjcy01_ns = cg.esphome_ns.namespace("xiaomi_hhccjcy01") +XiaomiHHCCJCY01 = xiaomi_hhccjcy01_ns.class_( + "XiaomiHHCCJCY01", esp32_ble_tracker.ESPBTDeviceListener, cg.Component +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(XiaomiHHCCJCY01), - 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_MOISTURE): sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 0, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_ILLUMINANCE): sensor.sensor_schema(UNIT_LUX, ICON_EMPTY, 0, - DEVICE_CLASS_ILLUMINANCE), - cv.Optional(CONF_CONDUCTIVITY): - sensor.sensor_schema(UNIT_MICROSIEMENS_PER_CENTIMETER, ICON_FLOWER, 0, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 0, - DEVICE_CLASS_BATTERY), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(XiaomiHHCCJCY01), + 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_MOISTURE): sensor.sensor_schema( + UNIT_PERCENT, ICON_WATER_PERCENT, 0, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_ILLUMINANCE): sensor.sensor_schema( + UNIT_LUX, ICON_EMPTY, 0, DEVICE_CLASS_ILLUMINANCE + ), + cv.Optional(CONF_CONDUCTIVITY): sensor.sensor_schema( + UNIT_MICROSIEMENS_PER_CENTIMETER, ICON_FLOWER, 0, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema( + UNIT_PERCENT, ICON_EMPTY, 0, DEVICE_CLASS_BATTERY + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/xiaomi_hhccpot002/sensor.py b/esphome/components/xiaomi_hhccpot002/sensor.py index ad8f2184b..820cda173 100644 --- a/esphome/components/xiaomi_hhccpot002/sensor.py +++ b/esphome/components/xiaomi_hhccpot002/sensor.py @@ -1,24 +1,42 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, esp32_ble_tracker -from esphome.const import CONF_MAC_ADDRESS, DEVICE_CLASS_EMPTY, UNIT_PERCENT, ICON_WATER_PERCENT, \ - CONF_ID, CONF_MOISTURE, CONF_CONDUCTIVITY, UNIT_MICROSIEMENS_PER_CENTIMETER, ICON_FLOWER +from esphome.const import ( + CONF_MAC_ADDRESS, + DEVICE_CLASS_EMPTY, + UNIT_PERCENT, + ICON_WATER_PERCENT, + CONF_ID, + CONF_MOISTURE, + CONF_CONDUCTIVITY, + UNIT_MICROSIEMENS_PER_CENTIMETER, + ICON_FLOWER, +) -DEPENDENCIES = ['esp32_ble_tracker'] -AUTO_LOAD = ['xiaomi_ble'] +DEPENDENCIES = ["esp32_ble_tracker"] +AUTO_LOAD = ["xiaomi_ble"] -xiaomi_hhccpot002_ns = cg.esphome_ns.namespace('xiaomi_hhccpot002') -XiaomiHHCCPOT002 = xiaomi_hhccpot002_ns.class_('XiaomiHHCCPOT002', - esp32_ble_tracker.ESPBTDeviceListener, cg.Component) +xiaomi_hhccpot002_ns = cg.esphome_ns.namespace("xiaomi_hhccpot002") +XiaomiHHCCPOT002 = xiaomi_hhccpot002_ns.class_( + "XiaomiHHCCPOT002", esp32_ble_tracker.ESPBTDeviceListener, cg.Component +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(XiaomiHHCCPOT002), - cv.Required(CONF_MAC_ADDRESS): cv.mac_address, - cv.Optional(CONF_MOISTURE): sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 0, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_CONDUCTIVITY): - sensor.sensor_schema(UNIT_MICROSIEMENS_PER_CENTIMETER, ICON_FLOWER, 0, DEVICE_CLASS_EMPTY), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(XiaomiHHCCPOT002), + cv.Required(CONF_MAC_ADDRESS): cv.mac_address, + cv.Optional(CONF_MOISTURE): sensor.sensor_schema( + UNIT_PERCENT, ICON_WATER_PERCENT, 0, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_CONDUCTIVITY): sensor.sensor_schema( + UNIT_MICROSIEMENS_PER_CENTIMETER, ICON_FLOWER, 0, DEVICE_CLASS_EMPTY + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/xiaomi_jqjcy01ym/sensor.py b/esphome/components/xiaomi_jqjcy01ym/sensor.py index c7451af5c..ce5e8e2b3 100644 --- a/esphome/components/xiaomi_jqjcy01ym/sensor.py +++ b/esphome/components/xiaomi_jqjcy01ym/sensor.py @@ -1,31 +1,57 @@ 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_MAC_ADDRESS, CONF_TEMPERATURE, CONF_ID, \ - DEVICE_CLASS_BATTERY, DEVICE_CLASS_EMPTY, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_TEMPERATURE, \ - ICON_EMPTY, UNIT_CELSIUS, UNIT_PERCENT, CONF_HUMIDITY, UNIT_MILLIGRAMS_PER_CUBIC_METER, \ - ICON_FLASK_OUTLINE, CONF_FORMALDEHYDE +from esphome.const import ( + CONF_BATTERY_LEVEL, + CONF_MAC_ADDRESS, + CONF_TEMPERATURE, + CONF_ID, + DEVICE_CLASS_BATTERY, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_TEMPERATURE, + ICON_EMPTY, + UNIT_CELSIUS, + UNIT_PERCENT, + CONF_HUMIDITY, + UNIT_MILLIGRAMS_PER_CUBIC_METER, + ICON_FLASK_OUTLINE, + CONF_FORMALDEHYDE, +) -DEPENDENCIES = ['esp32_ble_tracker'] -AUTO_LOAD = ['xiaomi_ble'] +DEPENDENCIES = ["esp32_ble_tracker"] +AUTO_LOAD = ["xiaomi_ble"] -xiaomi_jqjcy01ym_ns = cg.esphome_ns.namespace('xiaomi_jqjcy01ym') -XiaomiJQJCY01YM = xiaomi_jqjcy01ym_ns.class_('XiaomiJQJCY01YM', - esp32_ble_tracker.ESPBTDeviceListener, cg.Component) +xiaomi_jqjcy01ym_ns = cg.esphome_ns.namespace("xiaomi_jqjcy01ym") +XiaomiJQJCY01YM = xiaomi_jqjcy01ym_ns.class_( + "XiaomiJQJCY01YM", esp32_ble_tracker.ESPBTDeviceListener, cg.Component +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(XiaomiJQJCY01YM), - 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_FORMALDEHYDE): - sensor.sensor_schema(UNIT_MILLIGRAMS_PER_CUBIC_METER, ICON_FLASK_OUTLINE, 2, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 0, - DEVICE_CLASS_BATTERY), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(XiaomiJQJCY01YM), + 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_FORMALDEHYDE): sensor.sensor_schema( + UNIT_MILLIGRAMS_PER_CUBIC_METER, + ICON_FLASK_OUTLINE, + 2, + DEVICE_CLASS_EMPTY, + ), + cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema( + UNIT_PERCENT, ICON_EMPTY, 0, DEVICE_CLASS_BATTERY + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/xiaomi_lywsd02/sensor.py b/esphome/components/xiaomi_lywsd02/sensor.py index ced9875b5..c17eb17a5 100644 --- a/esphome/components/xiaomi_lywsd02/sensor.py +++ b/esphome/components/xiaomi_lywsd02/sensor.py @@ -1,27 +1,47 @@ 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_HUMIDITY, CONF_MAC_ADDRESS, CONF_TEMPERATURE, \ - DEVICE_CLASS_TEMPERATURE, UNIT_CELSIUS, ICON_EMPTY, UNIT_PERCENT, DEVICE_CLASS_HUMIDITY, \ - DEVICE_CLASS_BATTERY, CONF_ID +from esphome.const import ( + CONF_BATTERY_LEVEL, + CONF_HUMIDITY, + CONF_MAC_ADDRESS, + CONF_TEMPERATURE, + DEVICE_CLASS_TEMPERATURE, + UNIT_CELSIUS, + ICON_EMPTY, + UNIT_PERCENT, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_BATTERY, + CONF_ID, +) -DEPENDENCIES = ['esp32_ble_tracker'] -AUTO_LOAD = ['xiaomi_ble'] +DEPENDENCIES = ["esp32_ble_tracker"] +AUTO_LOAD = ["xiaomi_ble"] -xiaomi_lywsd02_ns = cg.esphome_ns.namespace('xiaomi_lywsd02') -XiaomiLYWSD02 = xiaomi_lywsd02_ns.class_('XiaomiLYWSD02', esp32_ble_tracker.ESPBTDeviceListener, - cg.Component) +xiaomi_lywsd02_ns = cg.esphome_ns.namespace("xiaomi_lywsd02") +XiaomiLYWSD02 = xiaomi_lywsd02_ns.class_( + "XiaomiLYWSD02", esp32_ble_tracker.ESPBTDeviceListener, cg.Component +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(XiaomiLYWSD02), - 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, 1, - DEVICE_CLASS_HUMIDITY), - cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 0, - DEVICE_CLASS_BATTERY), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(XiaomiLYWSD02), + 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, 1, DEVICE_CLASS_HUMIDITY + ), + cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema( + UNIT_PERCENT, ICON_EMPTY, 0, DEVICE_CLASS_BATTERY + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/xiaomi_lywsd03mmc/sensor.py b/esphome/components/xiaomi_lywsd03mmc/sensor.py index de3b4a4f9..b9de3f0bc 100644 --- a/esphome/components/xiaomi_lywsd03mmc/sensor.py +++ b/esphome/components/xiaomi_lywsd03mmc/sensor.py @@ -1,31 +1,51 @@ 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_HUMIDITY, CONF_MAC_ADDRESS, CONF_TEMPERATURE, \ - UNIT_CELSIUS, ICON_EMPTY, UNIT_PERCENT, DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_HUMIDITY, \ - CONF_ID, CONF_BINDKEY, DEVICE_CLASS_BATTERY +from esphome.const import ( + CONF_BATTERY_LEVEL, + CONF_HUMIDITY, + CONF_MAC_ADDRESS, + CONF_TEMPERATURE, + UNIT_CELSIUS, + ICON_EMPTY, + UNIT_PERCENT, + DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_HUMIDITY, + CONF_ID, + CONF_BINDKEY, + DEVICE_CLASS_BATTERY, +) -CODEOWNERS = ['@ahpohl'] +CODEOWNERS = ["@ahpohl"] -DEPENDENCIES = ['esp32_ble_tracker'] -AUTO_LOAD = ['xiaomi_ble'] +DEPENDENCIES = ["esp32_ble_tracker"] +AUTO_LOAD = ["xiaomi_ble"] -xiaomi_lywsd03mmc_ns = cg.esphome_ns.namespace('xiaomi_lywsd03mmc') -XiaomiLYWSD03MMC = xiaomi_lywsd03mmc_ns.class_('XiaomiLYWSD03MMC', - esp32_ble_tracker.ESPBTDeviceListener, - cg.Component) +xiaomi_lywsd03mmc_ns = cg.esphome_ns.namespace("xiaomi_lywsd03mmc") +XiaomiLYWSD03MMC = xiaomi_lywsd03mmc_ns.class_( + "XiaomiLYWSD03MMC", esp32_ble_tracker.ESPBTDeviceListener, cg.Component +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(XiaomiLYWSD03MMC), - cv.Required(CONF_BINDKEY): cv.bind_key, - 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), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(XiaomiLYWSD03MMC), + cv.Required(CONF_BINDKEY): cv.bind_key, + 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 + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/xiaomi_lywsdcgq/sensor.py b/esphome/components/xiaomi_lywsdcgq/sensor.py index 3bff2fca7..a4a03a3fb 100644 --- a/esphome/components/xiaomi_lywsdcgq/sensor.py +++ b/esphome/components/xiaomi_lywsdcgq/sensor.py @@ -1,27 +1,47 @@ 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_HUMIDITY, CONF_MAC_ADDRESS, CONF_TEMPERATURE, \ - UNIT_CELSIUS, ICON_EMPTY, UNIT_PERCENT, DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_HUMIDITY, \ - DEVICE_CLASS_BATTERY, CONF_ID +from esphome.const import ( + CONF_BATTERY_LEVEL, + CONF_HUMIDITY, + CONF_MAC_ADDRESS, + CONF_TEMPERATURE, + UNIT_CELSIUS, + ICON_EMPTY, + UNIT_PERCENT, + DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_BATTERY, + CONF_ID, +) -DEPENDENCIES = ['esp32_ble_tracker'] -AUTO_LOAD = ['xiaomi_ble'] +DEPENDENCIES = ["esp32_ble_tracker"] +AUTO_LOAD = ["xiaomi_ble"] -xiaomi_lywsdcgq_ns = cg.esphome_ns.namespace('xiaomi_lywsdcgq') -XiaomiLYWSDCGQ = xiaomi_lywsdcgq_ns.class_('XiaomiLYWSDCGQ', esp32_ble_tracker.ESPBTDeviceListener, - cg.Component) +xiaomi_lywsdcgq_ns = cg.esphome_ns.namespace("xiaomi_lywsdcgq") +XiaomiLYWSDCGQ = xiaomi_lywsdcgq_ns.class_( + "XiaomiLYWSDCGQ", esp32_ble_tracker.ESPBTDeviceListener, cg.Component +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(XiaomiLYWSDCGQ), - 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, 1, - DEVICE_CLASS_HUMIDITY), - cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 0, - DEVICE_CLASS_BATTERY), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(XiaomiLYWSDCGQ), + 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, 1, DEVICE_CLASS_HUMIDITY + ), + cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema( + UNIT_PERCENT, ICON_EMPTY, 0, DEVICE_CLASS_BATTERY + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/xiaomi_mhoc401/sensor.py b/esphome/components/xiaomi_mhoc401/sensor.py index 301c8914a..ee0e06b3a 100644 --- a/esphome/components/xiaomi_mhoc401/sensor.py +++ b/esphome/components/xiaomi_mhoc401/sensor.py @@ -1,30 +1,50 @@ 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_HUMIDITY, CONF_MAC_ADDRESS, CONF_TEMPERATURE, \ - UNIT_CELSIUS, ICON_EMPTY, UNIT_PERCENT, DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_HUMIDITY, \ - CONF_ID, CONF_BINDKEY, DEVICE_CLASS_BATTERY +from esphome.const import ( + CONF_BATTERY_LEVEL, + CONF_HUMIDITY, + CONF_MAC_ADDRESS, + CONF_TEMPERATURE, + UNIT_CELSIUS, + ICON_EMPTY, + UNIT_PERCENT, + DEVICE_CLASS_TEMPERATURE, + DEVICE_CLASS_HUMIDITY, + CONF_ID, + CONF_BINDKEY, + DEVICE_CLASS_BATTERY, +) -CODEOWNERS = ['@vevsvevs'] -DEPENDENCIES = ['esp32_ble_tracker'] -AUTO_LOAD = ['xiaomi_ble'] +CODEOWNERS = ["@vevsvevs"] +DEPENDENCIES = ["esp32_ble_tracker"] +AUTO_LOAD = ["xiaomi_ble"] -xiaomi_mhoc401_ns = cg.esphome_ns.namespace('xiaomi_mhoc401') -XiaomiMHOC401 = xiaomi_mhoc401_ns.class_('XiaomiMHOC401', - esp32_ble_tracker.ESPBTDeviceListener, - cg.Component) +xiaomi_mhoc401_ns = cg.esphome_ns.namespace("xiaomi_mhoc401") +XiaomiMHOC401 = xiaomi_mhoc401_ns.class_( + "XiaomiMHOC401", esp32_ble_tracker.ESPBTDeviceListener, cg.Component +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(XiaomiMHOC401), - cv.Required(CONF_BINDKEY): cv.bind_key, - 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), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(XiaomiMHOC401), + cv.Required(CONF_BINDKEY): cv.bind_key, + 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 + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/xiaomi_miscale/sensor.py b/esphome/components/xiaomi_miscale/sensor.py index 8fcdad96a..cd225e485 100644 --- a/esphome/components/xiaomi_miscale/sensor.py +++ b/esphome/components/xiaomi_miscale/sensor.py @@ -1,22 +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_MAC_ADDRESS, CONF_ID, CONF_WEIGHT, UNIT_KILOGRAM, \ - ICON_SCALE_BATHROOM, DEVICE_CLASS_EMPTY +from esphome.const import ( + CONF_MAC_ADDRESS, + CONF_ID, + CONF_WEIGHT, + UNIT_KILOGRAM, + ICON_SCALE_BATHROOM, + DEVICE_CLASS_EMPTY, +) -DEPENDENCIES = ['esp32_ble_tracker'] +DEPENDENCIES = ["esp32_ble_tracker"] -xiaomi_miscale_ns = cg.esphome_ns.namespace('xiaomi_miscale') -XiaomiMiscale = xiaomi_miscale_ns.class_('XiaomiMiscale', - esp32_ble_tracker.ESPBTDeviceListener, - cg.Component) +xiaomi_miscale_ns = cg.esphome_ns.namespace("xiaomi_miscale") +XiaomiMiscale = xiaomi_miscale_ns.class_( + "XiaomiMiscale", esp32_ble_tracker.ESPBTDeviceListener, cg.Component +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(XiaomiMiscale), - cv.Required(CONF_MAC_ADDRESS): cv.mac_address, - cv.Optional(CONF_WEIGHT): sensor.sensor_schema( - UNIT_KILOGRAM, ICON_SCALE_BATHROOM, 2, DEVICE_CLASS_EMPTY), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(XiaomiMiscale), + cv.Required(CONF_MAC_ADDRESS): cv.mac_address, + cv.Optional(CONF_WEIGHT): sensor.sensor_schema( + UNIT_KILOGRAM, ICON_SCALE_BATHROOM, 2, DEVICE_CLASS_EMPTY + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/xiaomi_miscale2/sensor.py b/esphome/components/xiaomi_miscale2/sensor.py index 84244cfc5..fa124e886 100644 --- a/esphome/components/xiaomi_miscale2/sensor.py +++ b/esphome/components/xiaomi_miscale2/sensor.py @@ -1,24 +1,41 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, esp32_ble_tracker -from esphome.const import CONF_MAC_ADDRESS, CONF_ID, CONF_WEIGHT, UNIT_KILOGRAM, \ - ICON_SCALE_BATHROOM, UNIT_OHM, CONF_IMPEDANCE, ICON_OMEGA, DEVICE_CLASS_EMPTY +from esphome.const import ( + CONF_MAC_ADDRESS, + CONF_ID, + CONF_WEIGHT, + UNIT_KILOGRAM, + ICON_SCALE_BATHROOM, + UNIT_OHM, + CONF_IMPEDANCE, + ICON_OMEGA, + DEVICE_CLASS_EMPTY, +) -DEPENDENCIES = ['esp32_ble_tracker'] +DEPENDENCIES = ["esp32_ble_tracker"] -xiaomi_miscale2_ns = cg.esphome_ns.namespace('xiaomi_miscale2') -XiaomiMiscale2 = xiaomi_miscale2_ns.class_('XiaomiMiscale2', - esp32_ble_tracker.ESPBTDeviceListener, - cg.Component) +xiaomi_miscale2_ns = cg.esphome_ns.namespace("xiaomi_miscale2") +XiaomiMiscale2 = xiaomi_miscale2_ns.class_( + "XiaomiMiscale2", esp32_ble_tracker.ESPBTDeviceListener, cg.Component +) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(XiaomiMiscale2), - cv.Required(CONF_MAC_ADDRESS): cv.mac_address, - cv.Optional(CONF_WEIGHT): sensor.sensor_schema( - UNIT_KILOGRAM, ICON_SCALE_BATHROOM, 2, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_IMPEDANCE): sensor.sensor_schema( - UNIT_OHM, ICON_OMEGA, 0, DEVICE_CLASS_EMPTY), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) +CONFIG_SCHEMA = ( + cv.Schema( + { + cv.GenerateID(): cv.declare_id(XiaomiMiscale2), + cv.Required(CONF_MAC_ADDRESS): cv.mac_address, + cv.Optional(CONF_WEIGHT): sensor.sensor_schema( + UNIT_KILOGRAM, ICON_SCALE_BATHROOM, 2, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_IMPEDANCE): sensor.sensor_schema( + UNIT_OHM, ICON_OMEGA, 0, DEVICE_CLASS_EMPTY + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/xiaomi_mjyd02yla/binary_sensor.py b/esphome/components/xiaomi_mjyd02yla/binary_sensor.py index a50f507b4..1b0ad03f1 100644 --- a/esphome/components/xiaomi_mjyd02yla/binary_sensor.py +++ b/esphome/components/xiaomi_mjyd02yla/binary_sensor.py @@ -1,33 +1,66 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, binary_sensor, esp32_ble_tracker -from esphome.const import CONF_MAC_ADDRESS, CONF_ID, CONF_BINDKEY, CONF_DEVICE_CLASS, CONF_LIGHT, \ - CONF_BATTERY_LEVEL, DEVICE_CLASS_BATTERY, DEVICE_CLASS_EMPTY, DEVICE_CLASS_ILLUMINANCE, \ - ICON_EMPTY, UNIT_PERCENT, CONF_IDLE_TIME, CONF_ILLUMINANCE, UNIT_MINUTE, UNIT_LUX, \ - ICON_TIMELAPSE +from esphome.const import ( + CONF_MAC_ADDRESS, + CONF_ID, + CONF_BINDKEY, + CONF_DEVICE_CLASS, + CONF_LIGHT, + CONF_BATTERY_LEVEL, + DEVICE_CLASS_BATTERY, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_ILLUMINANCE, + ICON_EMPTY, + UNIT_PERCENT, + CONF_IDLE_TIME, + CONF_ILLUMINANCE, + UNIT_MINUTE, + UNIT_LUX, + ICON_TIMELAPSE, +) -DEPENDENCIES = ['esp32_ble_tracker'] -AUTO_LOAD = ['xiaomi_ble'] +DEPENDENCIES = ["esp32_ble_tracker"] +AUTO_LOAD = ["xiaomi_ble"] -xiaomi_mjyd02yla_ns = cg.esphome_ns.namespace('xiaomi_mjyd02yla') -XiaomiMJYD02YLA = xiaomi_mjyd02yla_ns.class_('XiaomiMJYD02YLA', binary_sensor.BinarySensor, - cg.Component, esp32_ble_tracker.ESPBTDeviceListener) +xiaomi_mjyd02yla_ns = cg.esphome_ns.namespace("xiaomi_mjyd02yla") +XiaomiMJYD02YLA = xiaomi_mjyd02yla_ns.class_( + "XiaomiMJYD02YLA", + binary_sensor.BinarySensor, + cg.Component, + esp32_ble_tracker.ESPBTDeviceListener, +) -CONFIG_SCHEMA = cv.All(binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(XiaomiMJYD02YLA), - cv.Required(CONF_MAC_ADDRESS): cv.mac_address, - cv.Required(CONF_BINDKEY): cv.bind_key, - cv.Optional(CONF_DEVICE_CLASS, default='motion'): binary_sensor.device_class, - cv.Optional(CONF_IDLE_TIME): sensor.sensor_schema(UNIT_MINUTE, ICON_TIMELAPSE, 0, - DEVICE_CLASS_EMPTY), - cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 0, - DEVICE_CLASS_BATTERY), - cv.Optional(CONF_ILLUMINANCE): sensor.sensor_schema(UNIT_LUX, ICON_EMPTY, 0, - DEVICE_CLASS_ILLUMINANCE), - cv.Optional(CONF_LIGHT): binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.Optional(CONF_DEVICE_CLASS, default='light'): binary_sensor.device_class, - }), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA)) +CONFIG_SCHEMA = cv.All( + binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(XiaomiMJYD02YLA), + cv.Required(CONF_MAC_ADDRESS): cv.mac_address, + cv.Required(CONF_BINDKEY): cv.bind_key, + cv.Optional( + CONF_DEVICE_CLASS, default="motion" + ): binary_sensor.device_class, + cv.Optional(CONF_IDLE_TIME): sensor.sensor_schema( + UNIT_MINUTE, ICON_TIMELAPSE, 0, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema( + UNIT_PERCENT, ICON_EMPTY, 0, DEVICE_CLASS_BATTERY + ), + cv.Optional(CONF_ILLUMINANCE): sensor.sensor_schema( + UNIT_LUX, ICON_EMPTY, 0, DEVICE_CLASS_ILLUMINANCE + ), + cv.Optional(CONF_LIGHT): binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.Optional( + CONF_DEVICE_CLASS, default="light" + ): binary_sensor.device_class, + } + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/xiaomi_mue4094rt/binary_sensor.py b/esphome/components/xiaomi_mue4094rt/binary_sensor.py index 946b1694c..353e9aa3a 100644 --- a/esphome/components/xiaomi_mue4094rt/binary_sensor.py +++ b/esphome/components/xiaomi_mue4094rt/binary_sensor.py @@ -4,19 +4,33 @@ from esphome.components import binary_sensor, esp32_ble_tracker from esphome.const import CONF_MAC_ADDRESS, CONF_DEVICE_CLASS, CONF_TIMEOUT, CONF_ID -DEPENDENCIES = ['esp32_ble_tracker'] -AUTO_LOAD = ['xiaomi_ble'] +DEPENDENCIES = ["esp32_ble_tracker"] +AUTO_LOAD = ["xiaomi_ble"] -xiaomi_mue4094rt_ns = cg.esphome_ns.namespace('xiaomi_mue4094rt') -XiaomiMUE4094RT = xiaomi_mue4094rt_ns.class_('XiaomiMUE4094RT', binary_sensor.BinarySensor, - cg.Component, esp32_ble_tracker.ESPBTDeviceListener) +xiaomi_mue4094rt_ns = cg.esphome_ns.namespace("xiaomi_mue4094rt") +XiaomiMUE4094RT = xiaomi_mue4094rt_ns.class_( + "XiaomiMUE4094RT", + binary_sensor.BinarySensor, + cg.Component, + esp32_ble_tracker.ESPBTDeviceListener, +) -CONFIG_SCHEMA = cv.All(binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(XiaomiMUE4094RT), - cv.Required(CONF_MAC_ADDRESS): cv.mac_address, - cv.Optional(CONF_DEVICE_CLASS, default='motion'): binary_sensor.device_class, - cv.Optional(CONF_TIMEOUT, default='5s'): cv.positive_time_period_milliseconds, -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA)) +CONFIG_SCHEMA = cv.All( + binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(XiaomiMUE4094RT), + cv.Required(CONF_MAC_ADDRESS): cv.mac_address, + cv.Optional( + CONF_DEVICE_CLASS, default="motion" + ): binary_sensor.device_class, + cv.Optional( + CONF_TIMEOUT, default="5s" + ): cv.positive_time_period_milliseconds, + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/xiaomi_wx08zm/binary_sensor.py b/esphome/components/xiaomi_wx08zm/binary_sensor.py index becdce05c..c13085b5e 100644 --- a/esphome/components/xiaomi_wx08zm/binary_sensor.py +++ b/esphome/components/xiaomi_wx08zm/binary_sensor.py @@ -1,24 +1,46 @@ import esphome.codegen as cg import esphome.config_validation as cv from esphome.components import sensor, binary_sensor, esp32_ble_tracker -from esphome.const import CONF_BATTERY_LEVEL, CONF_MAC_ADDRESS, CONF_TABLET, DEVICE_CLASS_BATTERY, \ - DEVICE_CLASS_EMPTY, ICON_EMPTY, UNIT_PERCENT, ICON_BUG, CONF_ID +from esphome.const import ( + CONF_BATTERY_LEVEL, + CONF_MAC_ADDRESS, + CONF_TABLET, + DEVICE_CLASS_BATTERY, + DEVICE_CLASS_EMPTY, + ICON_EMPTY, + UNIT_PERCENT, + ICON_BUG, + CONF_ID, +) -DEPENDENCIES = ['esp32_ble_tracker'] -AUTO_LOAD = ['xiaomi_ble'] +DEPENDENCIES = ["esp32_ble_tracker"] +AUTO_LOAD = ["xiaomi_ble"] -xiaomi_wx08zm_ns = cg.esphome_ns.namespace('xiaomi_wx08zm') -XiaomiWX08ZM = xiaomi_wx08zm_ns.class_('XiaomiWX08ZM', binary_sensor.BinarySensor, - esp32_ble_tracker.ESPBTDeviceListener, cg.Component) +xiaomi_wx08zm_ns = cg.esphome_ns.namespace("xiaomi_wx08zm") +XiaomiWX08ZM = xiaomi_wx08zm_ns.class_( + "XiaomiWX08ZM", + binary_sensor.BinarySensor, + esp32_ble_tracker.ESPBTDeviceListener, + cg.Component, +) -CONFIG_SCHEMA = cv.All(binary_sensor.BINARY_SENSOR_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(XiaomiWX08ZM), - cv.Required(CONF_MAC_ADDRESS): cv.mac_address, - cv.Optional(CONF_TABLET): sensor.sensor_schema(UNIT_PERCENT, ICON_BUG, 0, DEVICE_CLASS_EMPTY), - cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema(UNIT_PERCENT, ICON_EMPTY, 0, - DEVICE_CLASS_BATTERY), -}).extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA)) +CONFIG_SCHEMA = cv.All( + binary_sensor.BINARY_SENSOR_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(XiaomiWX08ZM), + cv.Required(CONF_MAC_ADDRESS): cv.mac_address, + cv.Optional(CONF_TABLET): sensor.sensor_schema( + UNIT_PERCENT, ICON_BUG, 0, DEVICE_CLASS_EMPTY + ), + cv.Optional(CONF_BATTERY_LEVEL): sensor.sensor_schema( + UNIT_PERCENT, ICON_EMPTY, 0, DEVICE_CLASS_BATTERY + ), + } + ) + .extend(esp32_ble_tracker.ESP_BLE_DEVICE_SCHEMA) + .extend(cv.COMPONENT_SCHEMA) +) def to_code(config): diff --git a/esphome/components/yashima/climate.py b/esphome/components/yashima/climate.py index 4c4b98d9e..2965d4cdb 100644 --- a/esphome/components/yashima/climate.py +++ b/esphome/components/yashima/climate.py @@ -4,18 +4,24 @@ from esphome.components import climate, remote_transmitter, sensor from esphome.components.remote_base import CONF_TRANSMITTER_ID from esphome.const import CONF_ID, CONF_SENSOR, CONF_SUPPORTS_COOL, CONF_SUPPORTS_HEAT -AUTO_LOAD = ['sensor'] +AUTO_LOAD = ["sensor"] -yashima_ns = cg.esphome_ns.namespace('yashima') -YashimaClimate = yashima_ns.class_('YashimaClimate', climate.Climate, cg.Component) +yashima_ns = cg.esphome_ns.namespace("yashima") +YashimaClimate = yashima_ns.class_("YashimaClimate", climate.Climate, cg.Component) -CONFIG_SCHEMA = cv.All(climate.CLIMATE_SCHEMA.extend({ - cv.GenerateID(): cv.declare_id(YashimaClimate), - 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)) +CONFIG_SCHEMA = cv.All( + climate.CLIMATE_SCHEMA.extend( + { + cv.GenerateID(): cv.declare_id(YashimaClimate), + 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) +) def to_code(config): diff --git a/esphome/components/zyaura/sensor.py b/esphome/components/zyaura/sensor.py index 4517ed9b2..e9035ce10 100644 --- a/esphome/components/zyaura/sensor.py +++ b/esphome/components/zyaura/sensor.py @@ -2,27 +2,47 @@ 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_CLOCK_PIN, CONF_DATA_PIN, CONF_CO2, CONF_TEMPERATURE, \ - CONF_HUMIDITY, DEVICE_CLASS_EMPTY, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_TEMPERATURE, \ - ICON_EMPTY, UNIT_PARTS_PER_MILLION, UNIT_CELSIUS, UNIT_PERCENT, ICON_MOLECULE_CO2 +from esphome.const import ( + CONF_ID, + CONF_CLOCK_PIN, + CONF_DATA_PIN, + CONF_CO2, + CONF_TEMPERATURE, + CONF_HUMIDITY, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_HUMIDITY, + DEVICE_CLASS_TEMPERATURE, + ICON_EMPTY, + UNIT_PARTS_PER_MILLION, + UNIT_CELSIUS, + UNIT_PERCENT, + ICON_MOLECULE_CO2, +) from esphome.cpp_helpers import gpio_pin_expression -zyaura_ns = cg.esphome_ns.namespace('zyaura') -ZyAuraSensor = zyaura_ns.class_('ZyAuraSensor', cg.PollingComponent) +zyaura_ns = cg.esphome_ns.namespace("zyaura") +ZyAuraSensor = zyaura_ns.class_("ZyAuraSensor", cg.PollingComponent) -CONFIG_SCHEMA = cv.Schema({ - cv.GenerateID(): cv.declare_id(ZyAuraSensor), - cv.Required(CONF_CLOCK_PIN): cv.All(pins.internal_gpio_input_pin_schema, - pins.validate_has_interrupt), - cv.Required(CONF_DATA_PIN): cv.All(pins.internal_gpio_input_pin_schema, - pins.validate_has_interrupt), - cv.Optional(CONF_CO2): sensor.sensor_schema(UNIT_PARTS_PER_MILLION, ICON_MOLECULE_CO2, 0, - DEVICE_CLASS_EMPTY), - 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')) +CONFIG_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(ZyAuraSensor), + cv.Required(CONF_CLOCK_PIN): cv.All( + pins.internal_gpio_input_pin_schema, pins.validate_has_interrupt + ), + cv.Required(CONF_DATA_PIN): cv.All( + pins.internal_gpio_input_pin_schema, pins.validate_has_interrupt + ), + cv.Optional(CONF_CO2): sensor.sensor_schema( + UNIT_PARTS_PER_MILLION, ICON_MOLECULE_CO2, 0, DEVICE_CLASS_EMPTY + ), + 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")) def to_code(config): diff --git a/esphome/config.py b/esphome/config.py index 957494cea..995861fa6 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -11,8 +11,13 @@ from contextlib import contextmanager import voluptuous as vol from esphome import core, core_config, yaml_util -from esphome.const import CONF_ESPHOME, CONF_PLATFORM, ESP_PLATFORMS, CONF_PACKAGES, \ - CONF_SUBSTITUTIONS +from esphome.const import ( + CONF_ESPHOME, + CONF_PLATFORM, + ESP_PLATFORMS, + CONF_PACKAGES, + CONF_SUBSTITUTIONS, +) from esphome.core import CORE, EsphomeError # noqa from esphome.helpers import color, indent from esphome.util import safe_print, OrderedDict @@ -36,39 +41,39 @@ class ComponentManifest: @property def is_platform_component(self): - return getattr(self.module, 'IS_PLATFORM_COMPONENT', False) + return getattr(self.module, "IS_PLATFORM_COMPONENT", False) @property def config_schema(self): - return getattr(self.module, 'CONFIG_SCHEMA', None) + return getattr(self.module, "CONFIG_SCHEMA", None) @property def is_multi_conf(self): - return getattr(self.module, 'MULTI_CONF', False) + return getattr(self.module, "MULTI_CONF", False) @property def to_code(self): - return getattr(self.module, 'to_code', None) + return getattr(self.module, "to_code", None) @property def esp_platforms(self): - return getattr(self.module, 'ESP_PLATFORMS', ESP_PLATFORMS) + return getattr(self.module, "ESP_PLATFORMS", ESP_PLATFORMS) @property def dependencies(self): - return getattr(self.module, 'DEPENDENCIES', []) + return getattr(self.module, "DEPENDENCIES", []) @property def conflicts_with(self): - return getattr(self.module, 'CONFLICTS_WITH', []) + return getattr(self.module, "CONFLICTS_WITH", []) @property def auto_load(self): - return getattr(self.module, 'AUTO_LOAD', []) + return getattr(self.module, "AUTO_LOAD", []) @property def codeowners(self) -> List[str]: - return getattr(self.module, 'CODEOWNERS', []) + return getattr(self.module, "CODEOWNERS", []) def _get_flags_set(self, name, config): if not hasattr(self.module, name): @@ -85,11 +90,11 @@ class ComponentManifest: @property def source_files(self): if self._is_core: - core_p = os.path.abspath(os.path.join(os.path.dirname(__file__), 'core')) - source_files = core.find_source_files(os.path.join(core_p, 'dummy')) + core_p = os.path.abspath(os.path.join(os.path.dirname(__file__), "core")) + source_files = core.find_source_files(os.path.join(core_p, "dummy")) ret = {} for f in source_files: - ret[f'esphome/core/{f}'] = os.path.join(core_p, f) + ret[f"esphome/core/{f}"] = os.path.join(core_p, f) return ret source_files = core.find_source_files(self.module.__file__) @@ -100,13 +105,15 @@ class ComponentManifest: full_file = os.path.join(directory, x) rel = os.path.relpath(full_file, self.base_components_path) # Always use / for C++ include names - rel = rel.replace(os.sep, '/') - target_file = f'esphome/components/{rel}' + rel = rel.replace(os.sep, "/") + target_file = f"esphome/components/{rel}" ret[target_file] = full_file return ret -CORE_COMPONENTS_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), 'components')) +CORE_COMPONENTS_PATH = os.path.abspath( + os.path.join(os.path.dirname(__file__), "components") +) _UNDEF = object() CUSTOM_COMPONENTS_PATH = _UNDEF @@ -115,7 +122,7 @@ def _mount_config_dir(): global CUSTOM_COMPONENTS_PATH if CUSTOM_COMPONENTS_PATH is not _UNDEF: return - custom_path = os.path.abspath(os.path.join(CORE.config_dir, 'custom_components')) + custom_path = os.path.abspath(os.path.join(CORE.config_dir, "custom_components")) if not os.path.isdir(custom_path): CUSTOM_COMPONENTS_PATH = None return @@ -131,25 +138,29 @@ def _lookup_module(domain, is_platform): _mount_config_dir() # First look for custom_components try: - module = importlib.import_module(f'custom_components.{domain}') + module = importlib.import_module(f"custom_components.{domain}") except ImportError as e: # ImportError when no such module - if 'No module named' not in str(e): - _LOGGER.warning("Unable to import custom component %s:", domain, exc_info=True) + if "No module named" not in str(e): + _LOGGER.warning( + "Unable to import custom component %s:", domain, exc_info=True + ) except Exception: # pylint: disable=broad-except # Other error means component has an issue _LOGGER.error("Unable to load custom component %s:", domain, exc_info=True) return None else: # Found in custom components - manif = ComponentManifest(module, CUSTOM_COMPONENTS_PATH, is_platform=is_platform) + manif = ComponentManifest( + module, CUSTOM_COMPONENTS_PATH, is_platform=is_platform + ) _COMPONENT_CACHE[domain] = manif return manif try: - module = importlib.import_module(f'esphome.components.{domain}') + module = importlib.import_module(f"esphome.components.{domain}") except ImportError as e: - if 'No module named' not in str(e): + if "No module named" not in str(e): _LOGGER.error("Unable to import component %s:", domain, exc_info=True) return None except Exception: # pylint: disable=broad-except @@ -162,17 +173,20 @@ def _lookup_module(domain, is_platform): def get_component(domain): - assert '.' not in domain + assert "." not in domain return _lookup_module(domain, False) def get_platform(domain, platform): - full = f'{platform}.{domain}' + full = f"{platform}.{domain}" return _lookup_module(full, True) -_COMPONENT_CACHE['esphome'] = ComponentManifest( - core_config, CORE_COMPONENTS_PATH, is_core=True, is_platform=False, +_COMPONENT_CACHE["esphome"] = ComponentManifest( + core_config, + CORE_COMPONENTS_PATH, + is_core=True, + is_platform=False, ) @@ -197,7 +211,7 @@ ConfigPath = List[Union[str, int]] def _path_begins_with(path, other): # type: (ConfigPath, ConfigPath) -> bool if len(path) < len(other): return False - return path[:len(other)] == other + return path[: len(other)] == other class Config(OrderedDict): @@ -328,7 +342,7 @@ def do_id_pass(result): # type: (Config) -> None # Look for duplicate definitions match = next((v for v in declare_ids if v[0].id == id.id), None) if match is not None: - opath = '->'.join(str(v) for v in match[1]) + opath = "->".join(str(v) for v in match[1]) result.add_str_error(f"ID {id.id} redefined! Check {opath}", path) continue declare_ids.append((id, path)) @@ -348,21 +362,31 @@ def do_id_pass(result): # type: (Config) -> None if match is None: # No declared ID with this name import difflib - error = ("Couldn't find ID '{}'. Please check you have defined " - "an ID with that name in your configuration.".format(id.id)) + + error = ( + "Couldn't find ID '{}'. Please check you have defined " + "an ID with that name in your configuration.".format(id.id) + ) # Find candidates - matches = difflib.get_close_matches(id.id, [v[0].id for v in declare_ids]) + matches = difflib.get_close_matches( + id.id, [v[0].id for v in declare_ids] + ) if matches: - matches_s = ', '.join(f'"{x}"' for x in matches) + matches_s = ", ".join(f'"{x}"' for x in matches) error += f" These IDs look similar: {matches_s}." result.add_str_error(error, path) continue - if not isinstance(match.type, MockObjClass) or not isinstance(id.type, MockObjClass): + if not isinstance(match.type, MockObjClass) or not isinstance( + id.type, MockObjClass + ): continue if not match.type.inherits_from(id.type): - result.add_str_error("ID '{}' of type {} doesn't inherit from {}. Please " - "double check your ID is pointing to the correct value" - "".format(id.id, match.type, id.type), path) + result.add_str_error( + "ID '{}' of type {} doesn't inherit from {}. Please " + "double check your ID is pointing to the correct value" + "".format(id.id, match.type, id.type), + path, + ) if id.id is None and id.type is not None: for v in declare_ids: @@ -385,12 +409,14 @@ def recursive_check_replaceme(value): return cv.Schema({cv.valid: recursive_check_replaceme})(value) if isinstance(value, ESPForceValue): pass - if isinstance(value, str) and value == 'REPLACEME': - raise cv.Invalid("Found 'REPLACEME' in configuration, this is most likely an error. " - "Please make sure you have replaced all fields from the sample " - "configuration.\n" - "If you want to use the literal REPLACEME string, " - "please use \"!force REPLACEME\"") + if isinstance(value, str) and value == "REPLACEME": + raise cv.Invalid( + "Found 'REPLACEME' in configuration, this is most likely an error. " + "Please make sure you have replaced all fields from the sample " + "configuration.\n" + "If you want to use the literal REPLACEME string, " + 'please use "!force REPLACEME"' + ) return value @@ -400,6 +426,7 @@ def validate_config(config, command_line_substitutions): # 0. Load packages if CONF_PACKAGES in config: from esphome.components.packages import do_packages_pass + result.add_output_path([CONF_PACKAGES], CONF_PACKAGES) try: config = do_packages_pass(config) @@ -411,7 +438,11 @@ def validate_config(config, command_line_substitutions): # 1. Load substitutions if CONF_SUBSTITUTIONS in config: from esphome.components import substitutions - result[CONF_SUBSTITUTIONS] = {**config[CONF_SUBSTITUTIONS], **command_line_substitutions} + + result[CONF_SUBSTITUTIONS] = { + **config[CONF_SUBSTITUTIONS], + **command_line_substitutions, + } result.add_output_path([CONF_SUBSTITUTIONS], CONF_SUBSTITUTIONS) try: substitutions.do_substitution_pass(config, command_line_substitutions) @@ -425,14 +456,19 @@ def validate_config(config, command_line_substitutions): except vol.Invalid as err: result.add_error(err) - if 'esphomeyaml' in config: - _LOGGER.warning("The esphomeyaml section has been renamed to esphome in 1.11.0. " - "Please replace 'esphomeyaml:' in your configuration with 'esphome:'.") - config[CONF_ESPHOME] = config.pop('esphomeyaml') + if "esphomeyaml" in config: + _LOGGER.warning( + "The esphomeyaml section has been renamed to esphome in 1.11.0. " + "Please replace 'esphomeyaml:' in your configuration with 'esphome:'." + ) + config[CONF_ESPHOME] = config.pop("esphomeyaml") if CONF_ESPHOME not in config: - result.add_str_error("'esphome' section missing from configuration. Please make sure " - "your configuration has an 'esphome:' line in it.", []) + result.add_str_error( + "'esphome' section missing from configuration. Please make sure " + "your configuration has an 'esphome:' line in it.", + [], + ) return result # 2. Load partial core config @@ -454,7 +490,9 @@ def validate_config(config, command_line_substitutions): load_queue.append((domain, conf)) # List of items to enter next stage - check_queue = [] # type: List[Tuple[ConfigPath, str, ConfigType, ComponentManifest]] + check_queue = ( + [] + ) # type: List[Tuple[ConfigPath, str, ConfigType, ComponentManifest]] # This step handles: # - Adding output path @@ -463,7 +501,7 @@ def validate_config(config, command_line_substitutions): while load_queue: domain, conf = load_queue.popleft() - if domain.startswith('.'): + if domain.startswith("."): # Ignore top-level keys starting with a dot continue result.add_output_path([domain], domain) @@ -499,19 +537,19 @@ def validate_config(config, command_line_substitutions): for i, p_config in enumerate(conf): path = [domain, i] # Construct temporary unknown output path - p_domain = f'{domain}.unknown' + p_domain = f"{domain}.unknown" result.add_output_path(path, p_domain) result[domain][i] = p_config if not isinstance(p_config, dict): result.add_str_error("Platform schemas must be key-value pairs.", path) continue - p_name = p_config.get('platform') + p_name = p_config.get("platform") if p_name is None: result.add_str_error("No platform specified! See 'platform' key.", path) continue # Remove temp output path and construct new one result.remove_output_path(path, p_domain) - p_domain = f'{domain}.{p_name}' + p_domain = f"{domain}.{p_name}" result.add_output_path(path, p_domain) # Try Load platform platform = get_platform(domain, p_name) @@ -544,8 +582,10 @@ def validate_config(config, command_line_substitutions): success = True for dependency in comp.dependencies: if dependency not in config: - result.add_str_error("Component {} requires component {}" - "".format(domain, dependency), path) + result.add_str_error( + "Component {} requires component {}" "".format(domain, dependency), + path, + ) success = False if not success: continue @@ -553,22 +593,32 @@ def validate_config(config, command_line_substitutions): success = True for conflict in comp.conflicts_with: if conflict in config: - result.add_str_error("Component {} cannot be used together with component {}" - "".format(domain, conflict), path) + result.add_str_error( + "Component {} cannot be used together with component {}" + "".format(domain, conflict), + path, + ) success = False if not success: continue if CORE.esp_platform not in comp.esp_platforms: - result.add_str_error("Component {} doesn't support {}.".format(domain, - CORE.esp_platform), - path) + result.add_str_error( + "Component {} doesn't support {}.".format(domain, CORE.esp_platform), + path, + ) continue - if not comp.is_platform_component and comp.config_schema is None and \ - not isinstance(conf, core.AutoLoad): - result.add_str_error("Component {} cannot be loaded via YAML " - "(no CONFIG_SCHEMA).".format(domain), path) + if ( + not comp.is_platform_component + and comp.config_schema is None + and not isinstance(conf, core.AutoLoad) + ): + result.add_str_error( + "Component {} cannot be loaded via YAML " + "(no CONFIG_SCHEMA).".format(domain), + path, + ) continue if comp.is_multi_conf: @@ -588,13 +638,13 @@ def validate_config(config, command_line_substitutions): if comp.is_platform: # Remove 'platform' key for validation input_conf = OrderedDict(conf) - platform_val = input_conf.pop('platform') + platform_val = input_conf.pop("platform") validated = comp.config_schema(input_conf) # Ensure result is OrderedDict so we can call move_to_end if not isinstance(validated, OrderedDict): validated = OrderedDict(validated) - validated['platform'] = platform_val - validated.move_to_end('platform', last=False) + validated["platform"] = platform_val + validated.move_to_end("platform", last=False) result.set_by_path(path, validated) else: validated = comp.config_schema(conf) @@ -619,18 +669,20 @@ def _nested_getitem(data, path): def humanize_error(config, validation_error): validation_error = str(validation_error) - m = re.match(r'^(.*?)\s*(?:for dictionary value )?@ data\[.*$', validation_error, re.DOTALL) + m = re.match( + r"^(.*?)\s*(?:for dictionary value )?@ data\[.*$", validation_error, re.DOTALL + ) if m is not None: validation_error = m.group(1) validation_error = validation_error.strip() - if not validation_error.endswith('.'): - validation_error += '.' + if not validation_error.endswith("."): + validation_error += "." return validation_error def _get_parent_name(path, config): if not path: - return '' + return "" for domain_path, domain in config.output_paths: if _path_begins_with(path, domain_path): if len(path) > len(domain_path): @@ -642,20 +694,22 @@ def _get_parent_name(path, config): def _format_vol_invalid(ex, config): # type: (vol.Invalid, Config) -> str - message = '' + message = "" paren = _get_parent_name(ex.path[:-1], config) if isinstance(ex, ExtraKeysInvalid): if ex.candidates: - message += '[{}] is an invalid option for [{}]. Did you mean {}?'.format( - ex.path[-1], paren, ', '.join(f'[{x}]' for x in ex.candidates)) + message += "[{}] is an invalid option for [{}]. Did you mean {}?".format( + ex.path[-1], paren, ", ".join(f"[{x}]" for x in ex.candidates) + ) else: - message += '[{}] is an invalid option for [{}]. Please check the indentation.'.format( - ex.path[-1], paren) - elif 'extra keys not allowed' in str(ex): - message += '[{}] is an invalid option for [{}].'.format(ex.path[-1], paren) - elif 'required key not provided' in str(ex): + message += "[{}] is an invalid option for [{}]. Please check the indentation.".format( + ex.path[-1], paren + ) + elif "extra keys not allowed" in str(ex): + message += "[{}] is an invalid option for [{}].".format(ex.path[-1], paren) + elif "required key not provided" in str(ex): message += "'{}' is a required option for [{}].".format(ex.path[-1], paren) else: message += humanize_error(config, ex) @@ -707,8 +761,8 @@ def line_info(config, path, highlight=True): if obj: mark = obj.start_mark source = "[source {}:{}]".format(mark.document, mark.line + 1) - return color('cyan', source) - return 'None' + return color("cyan", source) + return "None" def _print_on_next_line(obj): @@ -724,90 +778,94 @@ def _print_on_next_line(obj): def dump_dict(config, path, at_root=True): # type: (Config, ConfigPath, bool) -> Tuple[str, bool] conf = config.get_nested_item(path) - ret = '' + ret = "" multiline = False if at_root: error = config.get_error_for_path(path) if error is not None: - ret += '\n' + color('bold_red', _format_vol_invalid(error, config)) + '\n' + ret += "\n" + color("bold_red", _format_vol_invalid(error, config)) + "\n" if isinstance(conf, (list, tuple)): multiline = True if not conf: - ret += '[]' + ret += "[]" multiline = False for i in range(len(conf)): path_ = path + [i] error = config.get_error_for_path(path_) if error is not None: - ret += '\n' + color('bold_red', _format_vol_invalid(error, config)) + '\n' + ret += ( + "\n" + color("bold_red", _format_vol_invalid(error, config)) + "\n" + ) - sep = '- ' + sep = "- " if config.is_in_error_path(path_): - sep = color('red', sep) + sep = color("red", sep) msg, _ = dump_dict(config, path_, at_root=False) msg = indent(msg) inf = line_info(config, path_, highlight=config.is_in_error_path(path_)) if inf is not None: - msg = inf + '\n' + msg + msg = inf + "\n" + msg elif msg: msg = msg[2:] - ret += sep + msg + '\n' + ret += sep + msg + "\n" elif isinstance(conf, dict): multiline = True if not conf: - ret += '{}' + ret += "{}" multiline = False for k in conf.keys(): path_ = path + [k] error = config.get_error_for_path(path_) if error is not None: - ret += '\n' + color('bold_red', _format_vol_invalid(error, config)) + '\n' + ret += ( + "\n" + color("bold_red", _format_vol_invalid(error, config)) + "\n" + ) - st = f'{k}: ' + st = f"{k}: " if config.is_in_error_path(path_): - st = color('red', st) + st = color("red", st) msg, m = dump_dict(config, path_, at_root=False) inf = line_info(config, path_, highlight=config.is_in_error_path(path_)) if m: - msg = '\n' + indent(msg) + msg = "\n" + indent(msg) if inf is not None: if m: - msg = ' ' + inf + msg + msg = " " + inf + msg else: - msg = msg + ' ' + inf - ret += st + msg + '\n' + msg = msg + " " + inf + ret += st + msg + "\n" elif isinstance(conf, str): if is_secret(conf): - conf = '!secret {}'.format(is_secret(conf)) + conf = "!secret {}".format(is_secret(conf)) if not conf: conf += "''" if len(conf) > 80: - conf = '|-\n' + indent(conf) + conf = "|-\n" + indent(conf) error = config.get_error_for_path(path) - col = 'bold_red' if error else 'white' + col = "bold_red" if error else "white" ret += color(col, str(conf)) elif isinstance(conf, core.Lambda): if is_secret(conf): - conf = '!secret {}'.format(is_secret(conf)) + conf = "!secret {}".format(is_secret(conf)) - conf = '!lambda |-\n' + indent(str(conf.value)) + conf = "!lambda |-\n" + indent(str(conf.value)) error = config.get_error_for_path(path) - col = 'bold_red' if error else 'white' + col = "bold_red" if error else "white" ret += color(col, conf) elif conf is None: pass else: error = config.get_error_for_path(path) - col = 'bold_red' if error else 'white' + col = "bold_red" if error else "white" ret += color(col, str(conf)) - multiline = '\n' in ret + multiline = "\n" in ret return ret, multiline @@ -817,7 +875,9 @@ def strip_default_ids(config): to_remove = [] for i, x in enumerate(config): x = config[i] = strip_default_ids(x) - if (isinstance(x, core.ID) and not x.is_manual) or isinstance(x, core.AutoLoad): + if (isinstance(x, core.ID) and not x.is_manual) or isinstance( + x, core.AutoLoad + ): to_remove.append(x) for x in to_remove: config.remove(x) @@ -825,7 +885,9 @@ def strip_default_ids(config): to_remove = [] for k, v in config.items(): v = config[k] = strip_default_ids(v) - if (isinstance(v, core.ID) and not v.is_manual) or isinstance(v, core.AutoLoad): + if (isinstance(v, core.ID) and not v.is_manual) or isinstance( + v, core.AutoLoad + ): to_remove.append(k) for k in to_remove: config.pop(k) @@ -843,16 +905,16 @@ def read_config(command_line_substitutions): if not CORE.verbose: res = strip_default_ids(res) - safe_print(color('bold_red', "Failed config")) - safe_print('') + safe_print(color("bold_red", "Failed config")) + safe_print("") for path, domain in res.output_paths: if not res.is_in_error_path(path): continue - errstr = color('bold_red', f'{domain}:') + errstr = color("bold_red", f"{domain}:") errline = line_info(res, path) if errline: - errstr += ' ' + errline + errstr += " " + errline safe_print(errstr) safe_print(indent(dump_dict(res, path)[0])) return None diff --git a/esphome/config_helpers.py b/esphome/config_helpers.py index dcbcb70ef..a88c5983b 100644 --- a/esphome/config_helpers.py +++ b/esphome/config_helpers.py @@ -7,14 +7,19 @@ from esphome.helpers import read_file def read_config_file(path): # type: (str) -> str - if CORE.vscode and (not CORE.ace or - os.path.abspath(path) == os.path.abspath(CORE.config_path)): - print(json.dumps({ - 'type': 'read_file', - 'path': path, - })) + if CORE.vscode and ( + not CORE.ace or os.path.abspath(path) == os.path.abspath(CORE.config_path) + ): + print( + json.dumps( + { + "type": "read_file", + "path": path, + } + ) + ) data = json.loads(input()) - assert data['type'] == 'file_response' - return data['content'] + assert data["type"] == "file_response" + return data["content"] return read_file(path) diff --git a/esphome/config_validation.py b/esphome/config_validation.py index 046e9af18..46cc1fad5 100644 --- a/esphome/config_validation.py +++ b/esphome/config_validation.py @@ -11,13 +11,40 @@ from string import ascii_letters, digits import voluptuous as vol from esphome import core -from esphome.const import ALLOWED_NAME_CHARS, CONF_AVAILABILITY, CONF_COMMAND_TOPIC, \ - CONF_DISCOVERY, CONF_ID, CONF_INTERNAL, CONF_NAME, CONF_PAYLOAD_AVAILABLE, \ - CONF_PAYLOAD_NOT_AVAILABLE, CONF_RETAIN, CONF_SETUP_PRIORITY, CONF_STATE_TOPIC, CONF_TOPIC, \ - CONF_HOUR, CONF_MINUTE, CONF_SECOND, CONF_VALUE, CONF_UPDATE_INTERVAL, CONF_TYPE_ID, \ - CONF_TYPE, CONF_PACKAGES -from esphome.core import CORE, HexInt, IPAddress, Lambda, TimePeriod, TimePeriodMicroseconds, \ - TimePeriodMilliseconds, TimePeriodSeconds, TimePeriodMinutes +from esphome.const import ( + ALLOWED_NAME_CHARS, + CONF_AVAILABILITY, + CONF_COMMAND_TOPIC, + CONF_DISCOVERY, + CONF_ID, + CONF_INTERNAL, + CONF_NAME, + CONF_PAYLOAD_AVAILABLE, + CONF_PAYLOAD_NOT_AVAILABLE, + CONF_RETAIN, + CONF_SETUP_PRIORITY, + CONF_STATE_TOPIC, + CONF_TOPIC, + CONF_HOUR, + CONF_MINUTE, + CONF_SECOND, + CONF_VALUE, + CONF_UPDATE_INTERVAL, + CONF_TYPE_ID, + CONF_TYPE, + CONF_PACKAGES, +) +from esphome.core import ( + CORE, + HexInt, + IPAddress, + Lambda, + TimePeriod, + TimePeriodMicroseconds, + TimePeriodMilliseconds, + TimePeriodSeconds, + TimePeriodMinutes, +) from esphome.helpers import list_starts_with, add_class_to_obj from esphome.voluptuous_schema import _Schema from esphome.yaml_util import make_data_base @@ -44,21 +71,115 @@ RequiredFieldInvalid = vol.RequiredFieldInvalid RESERVED_IDS = [ # C++ keywords http://en.cppreference.com/w/cpp/keyword - 'alignas', 'alignof', 'and', 'and_eq', 'asm', 'auto', 'bitand', 'bitor', 'bool', 'break', - 'case', 'catch', 'char', 'char16_t', 'char32_t', 'class', 'compl', 'concept', 'const', - 'constexpr', 'const_cast', 'continue', 'decltype', 'default', 'delete', 'do', 'double', - 'dynamic_cast', 'else', 'enum', 'explicit', 'export', 'export', 'extern', 'false', 'float', - 'for', 'friend', 'goto', 'if', 'inline', 'int', 'long', 'mutable', 'namespace', 'new', - 'noexcept', 'not', 'not_eq', 'nullptr', 'operator', 'or', 'or_eq', 'private', 'protected', - 'public', 'register', 'reinterpret_cast', 'requires', 'return', 'short', 'signed', 'sizeof', - 'static', 'static_assert', 'static_cast', 'struct', 'switch', 'template', 'this', - 'thread_local', 'throw', 'true', 'try', 'typedef', 'typeid', 'typename', 'union', 'unsigned', - 'using', 'virtual', 'void', 'volatile', 'wchar_t', 'while', 'xor', 'xor_eq', - - 'App', 'pinMode', 'delay', 'delayMicroseconds', 'digitalRead', 'digitalWrite', 'INPUT', - 'OUTPUT', - 'uint8_t', 'uint16_t', 'uint32_t', 'uint64_t', 'int8_t', 'int16_t', 'int32_t', 'int64_t', - 'close', 'pause', 'sleep', 'open', 'setup', 'loop', + "alignas", + "alignof", + "and", + "and_eq", + "asm", + "auto", + "bitand", + "bitor", + "bool", + "break", + "case", + "catch", + "char", + "char16_t", + "char32_t", + "class", + "compl", + "concept", + "const", + "constexpr", + "const_cast", + "continue", + "decltype", + "default", + "delete", + "do", + "double", + "dynamic_cast", + "else", + "enum", + "explicit", + "export", + "export", + "extern", + "false", + "float", + "for", + "friend", + "goto", + "if", + "inline", + "int", + "long", + "mutable", + "namespace", + "new", + "noexcept", + "not", + "not_eq", + "nullptr", + "operator", + "or", + "or_eq", + "private", + "protected", + "public", + "register", + "reinterpret_cast", + "requires", + "return", + "short", + "signed", + "sizeof", + "static", + "static_assert", + "static_cast", + "struct", + "switch", + "template", + "this", + "thread_local", + "throw", + "true", + "try", + "typedef", + "typeid", + "typename", + "union", + "unsigned", + "using", + "virtual", + "void", + "volatile", + "wchar_t", + "while", + "xor", + "xor_eq", + "App", + "pinMode", + "delay", + "delayMicroseconds", + "digitalRead", + "digitalWrite", + "INPUT", + "OUTPUT", + "uint8_t", + "uint16_t", + "uint32_t", + "uint64_t", + "int8_t", + "int16_t", + "int32_t", + "int64_t", + "close", + "pause", + "sleep", + "open", + "setup", + "loop", ] @@ -112,8 +233,10 @@ def valid_name(value): value = string_strict(value) for c in value: if c not in ALLOWED_NAME_CHARS: - raise Invalid(f"'{c}' is an invalid character for names. Valid characters are: " - f"{ALLOWED_NAME_CHARS} (lowercase, no spaces)") + raise Invalid( + f"'{c}' is an invalid character for names. Valid characters are: " + f"{ALLOWED_NAME_CHARS} (lowercase, no spaces)" + ) return value @@ -127,7 +250,9 @@ def string(value): if isinstance(value, (dict, list)): raise Invalid("string value cannot be dictionary or list.") if isinstance(value, bool): - raise Invalid("Auto-converted this value to boolean, please wrap the value in quotes.") + raise Invalid( + "Auto-converted this value to boolean, please wrap the value in quotes." + ) if isinstance(value, str): return value if value is not None: @@ -141,8 +266,10 @@ def string_strict(value): check_not_templatable(value) if isinstance(value, str): return value - raise Invalid("Must be string, got {}. did you forget putting quotes " - "around the value?".format(type(value))) + raise Invalid( + "Must be string, got {}. did you forget putting quotes " + "around the value?".format(type(value)) + ) def icon(value): @@ -150,7 +277,7 @@ def icon(value): value = string_strict(value) if not value: return value - if value.startswith('mdi:'): + if value.startswith("mdi:"): return value raise Invalid('Icons should start with prefix "mdi:"') @@ -169,12 +296,14 @@ def boolean(value): return value if isinstance(value, str): value = value.lower() - if value in ('true', 'yes', 'on', 'enable'): + if value in ("true", "yes", "on", "enable"): return True - if value in ('false', 'no', 'off', 'disable'): + if value in ("false", "no", "off", "disable"): return False - raise Invalid("Expected boolean value, but cannot convert {} to a boolean. " - "Please use 'true' or 'false'".format(value)) + raise Invalid( + "Expected boolean value, but cannot convert {} to a boolean. " + "Please use 'true' or 'false'".format(value) + ) def ensure_list(*validators): @@ -217,11 +346,13 @@ def int_(value): if isinstance(value, float): if int(value) == value: return int(value) - raise Invalid("This option only accepts integers with no fractional part. Please remove " - "the fractional part from {}".format(value)) + raise Invalid( + "This option only accepts integers with no fractional part. Please remove " + "the fractional part from {}".format(value) + ) value = string_strict(value).lower() base = 10 - if value.startswith('0x'): + if value.startswith("0x"): base = 16 try: return int(value, base) @@ -236,13 +367,18 @@ def int_range(min=None, max=None, min_included=True, max_included=True): assert isinstance(min, int) if max is not None: assert isinstance(max, int) - return All(int_, Range(min=min, max=max, min_included=min_included, max_included=max_included)) + return All( + int_, + Range(min=min, max=max, min_included=min_included, max_included=max_included), + ) def hex_int_range(min=None, max=None, min_included=True, max_included=True): """Validate that the config option is an integer in the given range.""" - return All(hex_int, - Range(min=min, max=max, min_included=min_included, max_included=max_included)) + return All( + hex_int, + Range(min=min, max=max, min_included=min_included, max_included=max_included), + ) def float_range(min=None, max=None, min_included=True, max_included=True): @@ -251,8 +387,10 @@ def float_range(min=None, max=None, min_included=True, max_included=True): assert isinstance(min, (int, float)) if max is not None: assert isinstance(max, (int, float)) - return All(float_, Range(min=min, max=max, min_included=min_included, - max_included=max_included)) + return All( + float_, + Range(min=min, max=max, min_included=min_included, max_included=max_included), + ) port = int_range(min=1, max=65535) @@ -271,29 +409,40 @@ def validate_id_name(value): raise Invalid("ID must not be empty") if value[0].isdigit(): raise Invalid("First character in ID cannot be a digit.") - if '-' in value: - raise Invalid("Dashes are not supported in IDs, please use underscores instead.") - valid_chars = ascii_letters + digits + '_' + if "-" in value: + raise Invalid( + "Dashes are not supported in IDs, please use underscores instead." + ) + valid_chars = ascii_letters + digits + "_" for char in value: if char not in valid_chars: - raise Invalid("IDs must only consist of upper/lowercase characters, the underscore" - "character and numbers. The character '{}' cannot be used" - "".format(char)) + raise Invalid( + "IDs must only consist of upper/lowercase characters, the underscore" + "character and numbers. The character '{}' cannot be used" + "".format(char) + ) if value in RESERVED_IDS: raise Invalid(f"ID '{value}' is reserved internally and cannot be used") if value in CORE.loaded_integrations: - raise Invalid("ID '{}' conflicts with the name of an esphome integration, please use " - "another ID name.".format(value)) + raise Invalid( + "ID '{}' conflicts with the name of an esphome integration, please use " + "another ID name.".format(value) + ) return value def use_id(type): """Declare that this configuration option should point to an ID with the given type.""" + def validator(value): check_not_templatable(value) if value is None: return core.ID(None, is_declaration=False, type=type) - if isinstance(value, core.ID) and value.is_declaration is False and value.type is type: + if ( + isinstance(value, core.ID) + and value.is_declaration is False + and value.type is type + ): return value return core.ID(validate_id_name(value), is_declaration=False, type=type) @@ -307,6 +456,7 @@ def declare_id(type): If two IDs with the same name exist, a validation error is thrown. """ + def validator(value): check_not_templatable(value) if value is None: @@ -349,8 +499,8 @@ def only_on(platforms): return validator_ -only_on_esp32 = only_on('ESP32') -only_on_esp8266 = only_on('ESP8266') +only_on_esp32 = only_on("ESP32") +only_on_esp8266 = only_on("ESP8266") # Adapted from: @@ -361,10 +511,10 @@ def has_at_least_one_key(*keys): def validate(obj): """Test keys exist in dict.""" if not isinstance(obj, dict): - raise Invalid('expected dictionary') + raise Invalid("expected dictionary") if not any(k in keys for k in obj): - raise Invalid('Must contain at least one of {}.'.format(', '.join(keys))) + raise Invalid("Must contain at least one of {}.".format(", ".join(keys))) return obj return validate @@ -372,15 +522,16 @@ def has_at_least_one_key(*keys): def has_exactly_one_key(*keys): """Validate that exactly one of the given keys exist in the config.""" + def validate(obj): if not isinstance(obj, dict): - raise Invalid('expected dictionary') + raise Invalid("expected dictionary") number = sum(k in keys for k in obj) if number > 1: - raise Invalid("Cannot specify more than one of {}.".format(', '.join(keys))) + raise Invalid("Cannot specify more than one of {}.".format(", ".join(keys))) if number < 1: - raise Invalid('Must contain exactly one of {}.'.format(', '.join(keys))) + raise Invalid("Must contain exactly one of {}.".format(", ".join(keys))) return obj return validate @@ -388,43 +539,50 @@ def has_exactly_one_key(*keys): def has_at_most_one_key(*keys): """Validate that at most one of the given keys exist in the config.""" + def validate(obj): if not isinstance(obj, dict): - raise Invalid('expected dictionary') + raise Invalid("expected dictionary") number = sum(k in keys for k in obj) if number > 1: - raise Invalid("Cannot specify more than one of {}.".format(', '.join(keys))) + raise Invalid("Cannot specify more than one of {}.".format(", ".join(keys))) return obj return validate -TIME_PERIOD_ERROR = "Time period {} should be format number + unit, for example 5ms, 5s, 5min, 5h" +TIME_PERIOD_ERROR = ( + "Time period {} should be format number + unit, for example 5ms, 5s, 5min, 5h" +) time_period_dict = All( - Schema({ - Optional('days'): float_, - Optional('hours'): float_, - Optional('minutes'): float_, - Optional('seconds'): float_, - Optional('milliseconds'): float_, - Optional('microseconds'): float_, - }), - has_at_least_one_key('days', 'hours', 'minutes', 'seconds', 'milliseconds', 'microseconds'), - lambda value: TimePeriod(**value) + Schema( + { + Optional("days"): float_, + Optional("hours"): float_, + Optional("minutes"): float_, + Optional("seconds"): float_, + Optional("milliseconds"): float_, + Optional("microseconds"): float_, + } + ), + has_at_least_one_key( + "days", "hours", "minutes", "seconds", "milliseconds", "microseconds" + ), + lambda value: TimePeriod(**value), ) def time_period_str_colon(value): """Validate and transform time offset with format HH:MM[:SS].""" if isinstance(value, int): - raise Invalid('Make sure you wrap time values in quotes') + raise Invalid("Make sure you wrap time values in quotes") if not isinstance(value, str): raise Invalid(TIME_PERIOD_ERROR.format(value)) try: - parsed = [int(x) for x in value.split(':')] + parsed = [int(x) for x in value.split(":")] except ValueError: # pylint: disable=raise-missing-from raise Invalid(TIME_PERIOD_ERROR.format(value)) @@ -445,34 +603,35 @@ def time_period_str_unit(value): check_not_templatable(value) if isinstance(value, int): - raise Invalid("Don't know what '{0}' means as it has no time *unit*! Did you mean " - "'{0}s'?".format(value)) + raise Invalid( + "Don't know what '{0}' means as it has no time *unit*! Did you mean " + "'{0}s'?".format(value) + ) if isinstance(value, TimePeriod): value = str(value) if not isinstance(value, str): raise Invalid("Expected string for time period with unit.") unit_to_kwarg = { - 'us': 'microseconds', - 'microseconds': 'microseconds', - 'ms': 'milliseconds', - 'milliseconds': 'milliseconds', - 's': 'seconds', - 'sec': 'seconds', - 'seconds': 'seconds', - 'min': 'minutes', - 'minutes': 'minutes', - 'h': 'hours', - 'hours': 'hours', - 'd': 'days', - 'days': 'days', + "us": "microseconds", + "microseconds": "microseconds", + "ms": "milliseconds", + "milliseconds": "milliseconds", + "s": "seconds", + "sec": "seconds", + "seconds": "seconds", + "min": "minutes", + "minutes": "minutes", + "h": "hours", + "hours": "hours", + "d": "days", + "days": "days", } match = re.match(r"^([-+]?[0-9]*\.?[0-9]*)\s*(\w*)$", value) if match is None: - raise Invalid("Expected time period with unit, " - "got {}".format(value)) + raise Invalid("Expected time period with unit, " "got {}".format(value)) kwarg = unit_to_kwarg[one_of(*unit_to_kwarg)(match.group(2))] return TimePeriod(**{kwarg: float(match.group(1))}) @@ -507,29 +666,34 @@ def time_period_in_minutes_(value): def update_interval(value): - if value == 'never': + if value == "never": return 4294967295 # uint32_t max return positive_time_period_milliseconds(value) time_period = Any(time_period_str_unit, time_period_str_colon, time_period_dict) positive_time_period = All(time_period, Range(min=TimePeriod())) -positive_time_period_milliseconds = All(positive_time_period, time_period_in_milliseconds_) +positive_time_period_milliseconds = All( + positive_time_period, time_period_in_milliseconds_ +) positive_time_period_seconds = All(positive_time_period, time_period_in_seconds_) positive_time_period_minutes = All(positive_time_period, time_period_in_minutes_) time_period_microseconds = All(time_period, time_period_in_microseconds_) -positive_time_period_microseconds = All(positive_time_period, time_period_in_microseconds_) -positive_not_null_time_period = All(time_period, - Range(min=TimePeriod(), min_included=False)) +positive_time_period_microseconds = All( + positive_time_period, time_period_in_microseconds_ +) +positive_not_null_time_period = All( + time_period, Range(min=TimePeriod(), min_included=False) +) def time_of_day(value): value = string(value) try: - date = datetime.strptime(value, '%H:%M:%S') + date = datetime.strptime(value, "%H:%M:%S") except ValueError as err: try: - date = datetime.strptime(value, '%H:%M:%S %p') + date = datetime.strptime(value, "%H:%M:%S %p") except ValueError: # pylint: disable=raise-missing-from raise Invalid(f"Invalid time of day: {err}") @@ -543,7 +707,7 @@ def time_of_day(value): def mac_address(value): value = string_strict(value) - parts = value.split(':') + parts = value.split(":") if len(parts) != 6: raise Invalid("MAC Address must consist of 6 : (colon) separated parts") parts_int = [] @@ -561,7 +725,7 @@ def mac_address(value): def bind_key(value): value = string_strict(value) - parts = [value[i:i+2] for i in range(0, len(value), 2)] + parts = [value[i : i + 2] for i in range(0, len(value), 2)] if len(parts) != 16: raise Invalid("Bind key must consist of 16 hexadecimal numbers") parts_int = [] @@ -574,7 +738,7 @@ def bind_key(value): # pylint: disable=raise-missing-from raise Invalid("Bind key must be hex values from 00 to FF") - return ''.join(f'{part:02X}' for part in parts_int) + return "".join(f"{part:02X}" for part in parts_int) def uuid(value): @@ -582,14 +746,30 @@ def uuid(value): METRIC_SUFFIXES = { - 'E': 1e18, 'P': 1e15, 'T': 1e12, 'G': 1e9, 'M': 1e6, 'k': 1e3, 'da': 10, 'd': 1e-1, - 'c': 1e-2, 'm': 0.001, 'µ': 1e-6, 'u': 1e-6, 'n': 1e-9, 'p': 1e-12, 'f': 1e-15, 'a': 1e-18, - '': 1 + "E": 1e18, + "P": 1e15, + "T": 1e12, + "G": 1e9, + "M": 1e6, + "k": 1e3, + "da": 10, + "d": 1e-1, + "c": 1e-2, + "m": 0.001, + "µ": 1e-6, + "u": 1e-6, + "n": 1e-9, + "p": 1e-12, + "f": 1e-15, + "a": 1e-18, + "": 1, } def float_with_unit(quantity, regex_suffix, optional_unit=False): - pattern = re.compile(r"^([-+]?[0-9]*\.?[0-9]*)\s*(\w*?)" + regex_suffix + r"$", re.UNICODE) + pattern = re.compile( + r"^([-+]?[0-9]*\.?[0-9]*)\s*(\w*?)" + regex_suffix + r"$", re.UNICODE + ) def validator(value): if optional_unit: @@ -647,8 +827,8 @@ def temperature(value): raise orig_err # noqa -_color_temperature_mireds = float_with_unit('Color Temperature', r'(mireds|Mireds)') -_color_temperature_kelvin = float_with_unit('Color Temperature', r'(K|Kelvin)') +_color_temperature_mireds = float_with_unit("Color Temperature", r"(mireds|Mireds)") +_color_temperature_kelvin = float_with_unit("Color Temperature", r"(K|Kelvin)") def color_temperature(value): @@ -673,8 +853,10 @@ def validate_bytes(value): raise Invalid("Invalid metric suffix {}".format(match.group(2))) multiplier = METRIC_SUFFIXES[match.group(2)] if multiplier < 1: - raise Invalid("Only suffixes with positive exponents are supported. " - "Got {}".format(match.group(2))) + raise Invalid( + "Only suffixes with positive exponents are supported. " + "Got {}".format(match.group(2)) + ) return int(mantissa * multiplier) @@ -683,7 +865,7 @@ def hostname(value): if len(value) > 63: raise Invalid("Hostnames can only be 63 characters long") for c in value: - if not (c.isalnum() or c in '_-'): + if not (c.isalnum() or c in "_-"): raise Invalid("Hostname can only have alphanumeric characters and _ or -") return value @@ -702,13 +884,15 @@ def domain_name(value): value = string_strict(value) if not value: return value - if not value.startswith('.'): + if not value.startswith("."): raise Invalid("Domain name must start with .") - if value.startswith('..'): + if value.startswith(".."): raise Invalid("Domain name must start with single .") for c in value: - if not (c.isalnum() or c in '._-'): - raise Invalid("Domain name can only have alphanumeric characters and _ or -") + if not (c.isalnum() or c in "._-"): + raise Invalid( + "Domain name can only have alphanumeric characters and _ or -" + ) return value @@ -725,15 +909,13 @@ def ipv4(value): if isinstance(value, list): parts = value elif isinstance(value, str): - parts = value.split('.') + parts = value.split(".") elif isinstance(value, IPAddress): return value else: - raise Invalid("IPv4 address must consist of either string or " - "integer list") + raise Invalid("IPv4 address must consist of either string or " "integer list") if len(parts) != 4: - raise Invalid("IPv4 address must consist of four point-separated " - "integers") + raise Invalid("IPv4 address must consist of four point-separated " "integers") parts_ = list(map(int, parts)) if not all(0 <= x < 256 for x in parts_): raise Invalid("IPv4 address parts must be in range from 0 to 255") @@ -746,38 +928,43 @@ def _valid_topic(value): raise Invalid("Can't use dictionary with topic") value = string(value) try: - raw_value = value.encode('utf-8') + raw_value = value.encode("utf-8") except UnicodeError as err: raise Invalid("MQTT topic name/filter must be valid UTF-8 string.") from err if not raw_value: raise Invalid("MQTT topic name/filter must not be empty.") if len(raw_value) > 65535: - raise Invalid("MQTT topic name/filter must not be longer than " - "65535 encoded bytes.") - if '\0' in value: - raise Invalid("MQTT topic name/filter must not contain null " - "character.") + raise Invalid( + "MQTT topic name/filter must not be longer than " "65535 encoded bytes." + ) + if "\0" in value: + raise Invalid("MQTT topic name/filter must not contain null " "character.") return value def subscribe_topic(value): """Validate that we can subscribe using this MQTT topic.""" value = _valid_topic(value) - for i in (i for i, c in enumerate(value) if c == '+'): - if (i > 0 and value[i - 1] != '/') or \ - (i < len(value) - 1 and value[i + 1] != '/'): - raise Invalid("Single-level wildcard must occupy an entire " - "level of the filter") + for i in (i for i, c in enumerate(value) if c == "+"): + if (i > 0 and value[i - 1] != "/") or ( + i < len(value) - 1 and value[i + 1] != "/" + ): + raise Invalid( + "Single-level wildcard must occupy an entire " "level of the filter" + ) - index = value.find('#') + index = value.find("#") if index != -1: if index != len(value) - 1: # If there are multiple wildcards, this will also trigger - raise Invalid("Multi-level wildcard must be the last " - "character in the topic filter.") - if len(value) > 1 and value[index - 1] != '/': - raise Invalid("Multi-level wildcard must be after a topic " - "level separator.") + raise Invalid( + "Multi-level wildcard must be the last " + "character in the topic filter." + ) + if len(value) > 1 and value[index - 1] != "/": + raise Invalid( + "Multi-level wildcard must be after a topic " "level separator." + ) return value @@ -785,14 +972,14 @@ def subscribe_topic(value): def publish_topic(value): """Validate that we can publish using this MQTT topic.""" value = _valid_topic(value) - if '+' in value or '#' in value: + if "+" in value or "#" in value: raise Invalid("Wildcards can not be used in topic names") return value def mqtt_payload(value): if value is None: - return '' + return "" return string(value) @@ -839,7 +1026,7 @@ def possibly_negative_percentage(value): has_percent_sign = False if isinstance(value, str): try: - if value.endswith('%'): + if value.endswith("%"): has_percent_sign = False value = float(value[:-1].rstrip()) / 100.0 else: @@ -861,7 +1048,7 @@ def possibly_negative_percentage(value): def percentage_int(value): - if isinstance(value, str) and value.endswith('%'): + if isinstance(value, str) and value.endswith("%"): value = int(value[:-1].rstrip()) return value @@ -870,6 +1057,7 @@ def invalid(message): """Mark this value as invalid. Each time *any* value is passed here it will result in a validation error with the given message. """ + def validator(value): raise Invalid(message) @@ -921,20 +1109,20 @@ def one_of(*values, **kwargs): - *float* (``bool``, default=False): Whether to convert the incoming values to floats. - *space* (``str``, default=' '): What to convert spaces in the input string to. """ - options = ', '.join(f"'{x}'" for x in values) - lower = kwargs.pop('lower', False) - upper = kwargs.pop('upper', False) - string_ = kwargs.pop('string', False) or lower or upper - to_int = kwargs.pop('int', False) - to_float = kwargs.pop('float', False) - space = kwargs.pop('space', ' ') + options = ", ".join(f"'{x}'" for x in values) + lower = kwargs.pop("lower", False) + upper = kwargs.pop("upper", False) + string_ = kwargs.pop("string", False) or lower or upper + to_int = kwargs.pop("int", False) + to_float = kwargs.pop("float", False) + space = kwargs.pop("space", " ") if kwargs: raise ValueError def validator(value): if string_: value = string(value) - value = value.replace(' ', space) + value = value.replace(" ", space) if to_int: value = int_(value) if to_float: @@ -945,12 +1133,15 @@ def one_of(*values, **kwargs): value = Upper(value) if value not in values: import difflib + options_ = [str(x) for x in values] option = str(value) matches = difflib.get_close_matches(option, options_) if matches: - raise Invalid("Unknown value '{}', did you mean {}?" - "".format(value, ", ".join(f"'{x}'" for x in matches))) + raise Invalid( + "Unknown value '{}', did you mean {}?" + "".format(value, ", ".join(f"'{x}'" for x in matches)) + ) raise Invalid(f"Unknown value '{value}', valid options are {options}.") return value @@ -977,7 +1168,7 @@ def enum(mapping, **kwargs): return validator -LAMBDA_ENTITY_ID_PROG = re.compile(r'id\(\s*([a-zA-Z0-9_]+\.[.a-zA-Z0-9_]+)\s*\)') +LAMBDA_ENTITY_ID_PROG = re.compile(r"id\(\s*([a-zA-Z0-9_]+\.[.a-zA-Z0-9_]+)\s*\)") def lambda_(value): @@ -986,12 +1177,15 @@ def lambda_(value): value = make_data_base(Lambda(string_strict(value)), value) entity_id_parts = re.split(LAMBDA_ENTITY_ID_PROG, value.value) if len(entity_id_parts) != 1: - entity_ids = ' '.join("'{}'".format(entity_id_parts[i]) - for i in range(1, len(entity_id_parts), 2)) - raise Invalid("Lambda contains reference to entity-id-style ID {}. " - "The id() wrapper only works for ESPHome-internal types. For importing " - "states from Home Assistant use the 'homeassistant' sensor platforms." - "".format(entity_ids)) + entity_ids = " ".join( + "'{}'".format(entity_id_parts[i]) for i in range(1, len(entity_id_parts), 2) + ) + raise Invalid( + "Lambda contains reference to entity-id-style ID {}. " + "The id() wrapper only works for ESPHome-internal types. For importing " + "states from Home Assistant use the 'homeassistant' sensor platforms." + "".format(entity_ids) + ) return value @@ -1001,18 +1195,22 @@ def returning_lambda(value): Additionally, make sure the lambda returns something. """ value = lambda_(value) - if 'return' not in value.value: - raise Invalid("Lambda doesn't contain a 'return' statement, but the lambda " - "is expected to return a value. \n" - "Please make sure the lambda contains at least one " - "return statement.") + if "return" not in value.value: + raise Invalid( + "Lambda doesn't contain a 'return' statement, but the lambda " + "is expected to return a value. \n" + "Please make sure the lambda contains at least one " + "return statement." + ) return value def dimensions(value): if isinstance(value, list): if len(value) != 2: - raise Invalid("Dimensions must have a length of two, not {}".format(len(value))) + raise Invalid( + "Dimensions must have a length of two, not {}".format(len(value)) + ) try: width, height = int(value[0]), int(value[1]) except ValueError: @@ -1024,65 +1222,91 @@ def dimensions(value): value = string(value) match = re.match(r"\s*([0-9]+)\s*[xX]\s*([0-9]+)\s*", value) if not match: - raise Invalid("Invalid value '{}' for dimensions. Only WIDTHxHEIGHT is allowed.") + raise Invalid( + "Invalid value '{}' for dimensions. Only WIDTHxHEIGHT is allowed." + ) return dimensions([match.group(1), match.group(2)]) def directory(value): import json + value = string(value) path = CORE.relative_config_path(value) - if CORE.vscode and (not CORE.ace or - os.path.abspath(path) == os.path.abspath(CORE.config_path)): - print(json.dumps({ - 'type': 'check_directory_exists', - 'path': path, - })) + if CORE.vscode and ( + not CORE.ace or os.path.abspath(path) == os.path.abspath(CORE.config_path) + ): + print( + json.dumps( + { + "type": "check_directory_exists", + "path": path, + } + ) + ) data = json.loads(input()) - assert data['type'] == 'directory_exists_response' - if data['content']: + assert data["type"] == "directory_exists_response" + if data["content"]: return value - raise Invalid("Could not find directory '{}'. Please make sure it exists (full path: {})." - "".format(path, os.path.abspath(path))) + raise Invalid( + "Could not find directory '{}'. Please make sure it exists (full path: {})." + "".format(path, os.path.abspath(path)) + ) if not os.path.exists(path): - raise Invalid("Could not find directory '{}'. Please make sure it exists (full path: {})." - "".format(path, os.path.abspath(path))) + raise Invalid( + "Could not find directory '{}'. Please make sure it exists (full path: {})." + "".format(path, os.path.abspath(path)) + ) if not os.path.isdir(path): - raise Invalid("Path '{}' is not a directory (full path: {})." - "".format(path, os.path.abspath(path))) + raise Invalid( + "Path '{}' is not a directory (full path: {})." + "".format(path, os.path.abspath(path)) + ) return value def file_(value): import json + value = string(value) path = CORE.relative_config_path(value) - if CORE.vscode and (not CORE.ace or - os.path.abspath(path) == os.path.abspath(CORE.config_path)): - print(json.dumps({ - 'type': 'check_file_exists', - 'path': path, - })) + if CORE.vscode and ( + not CORE.ace or os.path.abspath(path) == os.path.abspath(CORE.config_path) + ): + print( + json.dumps( + { + "type": "check_file_exists", + "path": path, + } + ) + ) data = json.loads(input()) - assert data['type'] == 'file_exists_response' - if data['content']: + assert data["type"] == "file_exists_response" + if data["content"]: return value - raise Invalid("Could not find file '{}'. Please make sure it exists (full path: {})." - "".format(path, os.path.abspath(path))) + raise Invalid( + "Could not find file '{}'. Please make sure it exists (full path: {})." + "".format(path, os.path.abspath(path)) + ) if not os.path.exists(path): - raise Invalid("Could not find file '{}'. Please make sure it exists (full path: {})." - "".format(path, os.path.abspath(path))) + raise Invalid( + "Could not find file '{}'. Please make sure it exists (full path: {})." + "".format(path, os.path.abspath(path)) + ) if not os.path.isfile(path): - raise Invalid("Path '{}' is not a file (full path: {})." - "".format(path, os.path.abspath(path))) + raise Invalid( + "Path '{}' is not a file (full path: {})." + "".format(path, os.path.abspath(path)) + ) return value -ENTITY_ID_CHARACTERS = 'abcdefghijklmnopqrstuvwxyz0123456789_' +ENTITY_ID_CHARACTERS = "abcdefghijklmnopqrstuvwxyz0123456789_" def entity_id(value): @@ -1091,9 +1315,9 @@ def entity_id(value): Should only be used for 'homeassistant' platforms. """ value = string_strict(value).lower() - if value.count('.') != 1: + if value.count(".") != 1: raise Invalid("Entity ID must have exactly one dot in it") - for x in value.split('.'): + for x in value.split("."): for c in x: if c not in ENTITY_ID_CHARACTERS: raise Invalid(f"Invalid character for entity ID: {c}") @@ -1119,7 +1343,7 @@ def extract_keys(schema): def typed_schema(schemas, **kwargs): """Create a schema that has a key to distinguish between schemas""" - key = kwargs.pop('key', CONF_TYPE) + key = kwargs.pop("key", CONF_TYPE) key_validator = one_of(*schemas, **kwargs) def validator(value): @@ -1176,10 +1400,11 @@ class OnlyWith(Optional): @property def default(self): # pylint: disable=unsupported-membership-test - if (self._component in CORE.raw_config or - (CONF_PACKAGES in CORE.raw_config and - self._component in - {list(x.keys())[0] for x in CORE.raw_config[CONF_PACKAGES].values()})): + if self._component in CORE.raw_config or ( + CONF_PACKAGES in CORE.raw_config + and self._component + in {list(x.keys())[0] for x in CORE.raw_config[CONF_PACKAGES].values()} + ): return self._default return vol.UNDEFINED @@ -1209,17 +1434,22 @@ def ensure_schema(schema): def validate_registry_entry(name, registry): - base_schema = ensure_schema(registry.base_schema).extend({ - Optional(CONF_TYPE_ID): valid, - }, extra=ALLOW_EXTRA) + base_schema = ensure_schema(registry.base_schema).extend( + { + Optional(CONF_TYPE_ID): valid, + }, + extra=ALLOW_EXTRA, + ) ignore_keys = extract_keys(base_schema) def validator(value): if isinstance(value, str): value = {value: {}} if not isinstance(value, dict): - raise Invalid("{} must consist of key-value mapping! Got {}" - "".format(name.title(), value)) + raise Invalid( + "{} must consist of key-value mapping! Got {}" + "".format(name.title(), value) + ) key = next((x for x in value if x not in ignore_keys), None) if key is None: raise Invalid(f"Key missing from {name}! Got {value}") @@ -1227,9 +1457,11 @@ def validate_registry_entry(name, registry): raise Invalid(f"Unable to find {name} with the name '{key}'", [key]) key2 = next((x for x in value if x != key and x not in ignore_keys), None) if key2 is not None: - raise Invalid("Cannot have two {0}s in one item. Key '{1}' overrides '{2}'! " - "Did you forget to indent the block inside the {0}?" - "".format(name, key, key2)) + raise Invalid( + "Cannot have two {0}s in one item. Key '{1}' overrides '{2}'! " + "Did you forget to indent the block inside the {0}?" + "".format(name, key, key2) + ) if value[key] is None: value[key] = {} @@ -1242,9 +1474,9 @@ def validate_registry_entry(name, registry): value[key] = registry_entry.schema(value[key]) if registry_entry.type_id is not None: - my_base_schema = base_schema.extend({ - GenerateID(CONF_TYPE_ID): declare_id(registry_entry.type_id) - }) + my_base_schema = base_schema.extend( + {GenerateID(CONF_TYPE_ID): declare_id(registry_entry.type_id)} + ) value = my_base_schema(value) return value @@ -1257,7 +1489,7 @@ def validate_registry(name, registry): def maybe_simple_value(*validators, **kwargs): - key = kwargs.pop('key', CONF_VALUE) + key = kwargs.pop("key", CONF_VALUE) validator = All(*validators) def validate(value): @@ -1268,30 +1500,35 @@ def maybe_simple_value(*validators, **kwargs): return validate -MQTT_COMPONENT_AVAILABILITY_SCHEMA = Schema({ - Required(CONF_TOPIC): subscribe_topic, - Optional(CONF_PAYLOAD_AVAILABLE, default='online'): mqtt_payload, - Optional(CONF_PAYLOAD_NOT_AVAILABLE, default='offline'): mqtt_payload, -}) +MQTT_COMPONENT_AVAILABILITY_SCHEMA = Schema( + { + Required(CONF_TOPIC): subscribe_topic, + Optional(CONF_PAYLOAD_AVAILABLE, default="online"): mqtt_payload, + Optional(CONF_PAYLOAD_NOT_AVAILABLE, default="offline"): mqtt_payload, + } +) -MQTT_COMPONENT_SCHEMA = Schema({ - Optional(CONF_NAME): string, - Optional(CONF_RETAIN): All(requires_component('mqtt'), boolean), - Optional(CONF_DISCOVERY): All(requires_component('mqtt'), boolean), - Optional(CONF_STATE_TOPIC): All(requires_component('mqtt'), publish_topic), - Optional(CONF_AVAILABILITY): All(requires_component('mqtt'), - Any(None, MQTT_COMPONENT_AVAILABILITY_SCHEMA)), - Optional(CONF_INTERNAL): boolean, -}) +MQTT_COMPONENT_SCHEMA = Schema( + { + Optional(CONF_NAME): string, + Optional(CONF_RETAIN): All(requires_component("mqtt"), boolean), + Optional(CONF_DISCOVERY): All(requires_component("mqtt"), boolean), + Optional(CONF_STATE_TOPIC): All(requires_component("mqtt"), publish_topic), + Optional(CONF_AVAILABILITY): All( + requires_component("mqtt"), Any(None, MQTT_COMPONENT_AVAILABILITY_SCHEMA) + ), + Optional(CONF_INTERNAL): boolean, + } +) MQTT_COMPONENT_SCHEMA.add_extra(_nameable_validator) -MQTT_COMMAND_COMPONENT_SCHEMA = MQTT_COMPONENT_SCHEMA.extend({ - Optional(CONF_COMMAND_TOPIC): All(requires_component('mqtt'), subscribe_topic), -}) +MQTT_COMMAND_COMPONENT_SCHEMA = MQTT_COMPONENT_SCHEMA.extend( + { + Optional(CONF_COMMAND_TOPIC): All(requires_component("mqtt"), subscribe_topic), + } +) -COMPONENT_SCHEMA = Schema({ - Optional(CONF_SETUP_PRIORITY): float_ -}) +COMPONENT_SCHEMA = Schema({Optional(CONF_SETUP_PRIORITY): float_}) def polling_component_schema(default_update_interval): @@ -1301,10 +1538,16 @@ def polling_component_schema(default_update_interval): :param default_update_interval: The default update interval to set for the integration. """ if default_update_interval is None: - return COMPONENT_SCHEMA.extend({ - Required(CONF_UPDATE_INTERVAL): default_update_interval, - }) + return COMPONENT_SCHEMA.extend( + { + Required(CONF_UPDATE_INTERVAL): default_update_interval, + } + ) assert isinstance(default_update_interval, str) - return COMPONENT_SCHEMA.extend({ - Optional(CONF_UPDATE_INTERVAL, default=default_update_interval): update_interval, - }) + return COMPONENT_SCHEMA.extend( + { + Optional( + CONF_UPDATE_INTERVAL, default=default_update_interval + ): update_interval, + } + ) diff --git a/esphome/const.py b/esphome/const.py index e43178498..6bb842c22 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -2,708 +2,708 @@ MAJOR_VERSION = 1 MINOR_VERSION = 17 -PATCH_VERSION = '0-dev' -__short_version__ = f'{MAJOR_VERSION}.{MINOR_VERSION}' -__version__ = f'{__short_version__}.{PATCH_VERSION}' +PATCH_VERSION = "0-dev" +__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" +__version__ = f"{__short_version__}.{PATCH_VERSION}" -ESP_PLATFORM_ESP32 = 'ESP32' -ESP_PLATFORM_ESP8266 = 'ESP8266' +ESP_PLATFORM_ESP32 = "ESP32" +ESP_PLATFORM_ESP8266 = "ESP8266" ESP_PLATFORMS = [ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266] -ALLOWED_NAME_CHARS = 'abcdefghijklmnopqrstuvwxyz0123456789_-' +ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789_-" # Lookup table from ESP32 arduino framework version to latest platformio # package with that version # See also https://github.com/platformio/platform-espressif32/releases ARDUINO_VERSION_ESP32 = { - 'dev': 'https://github.com/platformio/platform-espressif32.git', - '1.0.4': 'espressif32@1.12.4', - '1.0.3': 'espressif32@1.10.0', - '1.0.2': 'espressif32@1.9.0', - '1.0.1': 'espressif32@1.7.0', - '1.0.0': 'espressif32@1.5.0', + "dev": "https://github.com/platformio/platform-espressif32.git", + "1.0.4": "espressif32@1.12.4", + "1.0.3": "espressif32@1.10.0", + "1.0.2": "espressif32@1.9.0", + "1.0.1": "espressif32@1.7.0", + "1.0.0": "espressif32@1.5.0", } # See also https://github.com/platformio/platform-espressif8266/releases ARDUINO_VERSION_ESP8266 = { - 'dev': 'https://github.com/platformio/platform-espressif8266.git', - '2.7.4': 'espressif8266@2.6.2', - '2.7.3': 'espressif8266@2.6.1', - '2.7.2': 'espressif8266@2.6.0', - '2.7.1': 'espressif8266@2.5.3', - '2.7.0': 'espressif8266@2.5.0', - '2.6.3': 'espressif8266@2.4.0', - '2.6.2': 'espressif8266@2.3.1', - '2.6.1': 'espressif8266@2.3.0', - '2.5.2': 'espressif8266@2.2.3', - '2.5.1': 'espressif8266@2.1.1', - '2.5.0': 'espressif8266@2.0.4', - '2.4.2': 'espressif8266@1.8.0', - '2.4.1': 'espressif8266@1.7.3', - '2.4.0': 'espressif8266@1.6.0', - '2.3.0': 'espressif8266@1.5.0', + "dev": "https://github.com/platformio/platform-espressif8266.git", + "2.7.4": "espressif8266@2.6.2", + "2.7.3": "espressif8266@2.6.1", + "2.7.2": "espressif8266@2.6.0", + "2.7.1": "espressif8266@2.5.3", + "2.7.0": "espressif8266@2.5.0", + "2.6.3": "espressif8266@2.4.0", + "2.6.2": "espressif8266@2.3.1", + "2.6.1": "espressif8266@2.3.0", + "2.5.2": "espressif8266@2.2.3", + "2.5.1": "espressif8266@2.1.1", + "2.5.0": "espressif8266@2.0.4", + "2.4.2": "espressif8266@1.8.0", + "2.4.1": "espressif8266@1.7.3", + "2.4.0": "espressif8266@1.6.0", + "2.3.0": "espressif8266@1.5.0", } -SOURCE_FILE_EXTENSIONS = {'.cpp', '.hpp', '.h', '.c', '.tcc', '.ino'} -HEADER_FILE_EXTENSIONS = {'.h', '.hpp', '.tcc'} +SOURCE_FILE_EXTENSIONS = {".cpp", ".hpp", ".h", ".c", ".tcc", ".ino"} +HEADER_FILE_EXTENSIONS = {".h", ".hpp", ".tcc"} -CONF_ABOVE = 'above' -CONF_ACCELERATION = 'acceleration' -CONF_ACCELERATION_X = 'acceleration_x' -CONF_ACCELERATION_Y = 'acceleration_y' -CONF_ACCELERATION_Z = 'acceleration_z' -CONF_ACCURACY = 'accuracy' -CONF_ACCURACY_DECIMALS = 'accuracy_decimals' -CONF_ACTION_ID = 'action_id' -CONF_ADDRESS = 'address' -CONF_ALPHA = 'alpha' -CONF_AND = 'and' -CONF_AP = 'ap' -CONF_ARDUINO_VERSION = 'arduino_version' -CONF_ARGS = 'args' -CONF_ASSUMED_STATE = 'assumed_state' -CONF_AT = 'at' -CONF_ATTENUATION = 'attenuation' -CONF_AUTH = 'auth' -CONF_AUTO_MODE = 'auto_mode' -CONF_AUTOMATION_ID = 'automation_id' -CONF_AVAILABILITY = 'availability' -CONF_AWAY = 'away' -CONF_AWAY_CONFIG = 'away_config' -CONF_BACKLIGHT_PIN = 'backlight_pin' -CONF_BATTERY_LEVEL = 'battery_level' -CONF_BATTERY_VOLTAGE = 'battery_voltage' -CONF_BAUD_RATE = 'baud_rate' -CONF_BELOW = 'below' -CONF_BINARY = 'binary' -CONF_BINARY_SENSOR = 'binary_sensor' -CONF_BINARY_SENSORS = 'binary_sensors' -CONF_BINDKEY = 'bindkey' -CONF_BIRTH_MESSAGE = 'birth_message' -CONF_BIT_DEPTH = 'bit_depth' -CONF_BLUE = 'blue' -CONF_BOARD = 'board' -CONF_BOARD_FLASH_MODE = 'board_flash_mode' -CONF_BRANCH = 'branch' -CONF_BRIGHTNESS = 'brightness' -CONF_BROKER = 'broker' -CONF_BSSID = 'bssid' -CONF_BUFFER_SIZE = 'buffer_size' -CONF_BUILD_PATH = 'build_path' -CONF_BUS_VOLTAGE = 'bus_voltage' -CONF_BUSY_PIN = 'busy_pin' -CONF_CALIBRATE_LINEAR = 'calibrate_linear' -CONF_CALIBRATION = 'calibration' -CONF_CAPACITANCE = 'capacitance' -CONF_CARRIER_DUTY_PERCENT = 'carrier_duty_percent' -CONF_CARRIER_FREQUENCY = 'carrier_frequency' +CONF_ABOVE = "above" +CONF_ACCELERATION = "acceleration" +CONF_ACCELERATION_X = "acceleration_x" +CONF_ACCELERATION_Y = "acceleration_y" +CONF_ACCELERATION_Z = "acceleration_z" +CONF_ACCURACY = "accuracy" +CONF_ACCURACY_DECIMALS = "accuracy_decimals" +CONF_ACTION_ID = "action_id" +CONF_ADDRESS = "address" +CONF_ALPHA = "alpha" +CONF_AND = "and" +CONF_AP = "ap" +CONF_ARDUINO_VERSION = "arduino_version" +CONF_ARGS = "args" +CONF_ASSUMED_STATE = "assumed_state" +CONF_AT = "at" +CONF_ATTENUATION = "attenuation" +CONF_AUTH = "auth" +CONF_AUTO_MODE = "auto_mode" +CONF_AUTOMATION_ID = "automation_id" +CONF_AVAILABILITY = "availability" +CONF_AWAY = "away" +CONF_AWAY_CONFIG = "away_config" +CONF_BACKLIGHT_PIN = "backlight_pin" +CONF_BATTERY_LEVEL = "battery_level" +CONF_BATTERY_VOLTAGE = "battery_voltage" +CONF_BAUD_RATE = "baud_rate" +CONF_BELOW = "below" +CONF_BINARY = "binary" +CONF_BINARY_SENSOR = "binary_sensor" +CONF_BINARY_SENSORS = "binary_sensors" +CONF_BINDKEY = "bindkey" +CONF_BIRTH_MESSAGE = "birth_message" +CONF_BIT_DEPTH = "bit_depth" +CONF_BLUE = "blue" +CONF_BOARD = "board" +CONF_BOARD_FLASH_MODE = "board_flash_mode" +CONF_BRANCH = "branch" +CONF_BRIGHTNESS = "brightness" +CONF_BROKER = "broker" +CONF_BSSID = "bssid" +CONF_BUFFER_SIZE = "buffer_size" +CONF_BUILD_PATH = "build_path" +CONF_BUS_VOLTAGE = "bus_voltage" +CONF_BUSY_PIN = "busy_pin" +CONF_CALIBRATE_LINEAR = "calibrate_linear" +CONF_CALIBRATION = "calibration" +CONF_CAPACITANCE = "capacitance" +CONF_CARRIER_DUTY_PERCENT = "carrier_duty_percent" +CONF_CARRIER_FREQUENCY = "carrier_frequency" CONF_CERTIFICATE = "certificate" CONF_CERTIFICATE_AUTHORITY = "certificate_authority" -CONF_CHANGE_MODE_EVERY = 'change_mode_every' -CONF_CHANNEL = 'channel' -CONF_CHANNELS = 'channels' -CONF_CHIPSET = 'chipset' -CONF_CLIENT_ID = 'client_id' -CONF_CLK_PIN = 'clk_pin' -CONF_CLOCK_PIN = 'clock_pin' -CONF_CLOSE_ACTION = 'close_action' -CONF_CLOSE_DURATION = 'close_duration' -CONF_CLOSE_ENDSTOP = 'close_endstop' -CONF_CO2 = 'co2' -CONF_CODE = 'code' -CONF_COLD_WHITE = 'cold_white' -CONF_COLD_WHITE_COLOR_TEMPERATURE = 'cold_white_color_temperature' -CONF_COLOR_CORRECT = 'color_correct' -CONF_COLOR_TEMPERATURE = 'color_temperature' -CONF_COLORS = 'colors' -CONF_COMMAND = 'command' -CONF_COMMAND_TOPIC = 'command_topic' -CONF_COMMENT = 'comment' -CONF_COMMIT = 'commit' -CONF_COMPONENT_ID = 'component_id' -CONF_COMPONENTS = 'components' -CONF_CONDITION = 'condition' -CONF_CONDITION_ID = 'condition_id' -CONF_CONDUCTIVITY = 'conductivity' -CONF_CONTRAST = 'contrast' -CONF_COOL_ACTION = 'cool_action' -CONF_COOL_MODE = 'cool_mode' -CONF_COUNT_MODE = 'count_mode' -CONF_CRON = 'cron' -CONF_CS_PIN = 'cs_pin' -CONF_CSS_INCLUDE = 'css_include' -CONF_CSS_URL = 'css_url' -CONF_CURRENT = 'current' -CONF_CURRENT_OPERATION = 'current_operation' -CONF_CURRENT_RESISTOR = 'current_resistor' -CONF_DALLAS_ID = 'dallas_id' -CONF_DATA = 'data' -CONF_DATA_PIN = 'data_pin' -CONF_DATA_PINS = 'data_pins' -CONF_DATA_RATE = 'data_rate' -CONF_DATA_TEMPLATE = 'data_template' -CONF_DAYS_OF_MONTH = 'days_of_month' -CONF_DAYS_OF_WEEK = 'days_of_week' -CONF_DC_PIN = 'dc_pin' -CONF_DEBOUNCE = 'debounce' -CONF_DECELERATION = 'deceleration' -CONF_DEFAULT_TARGET_TEMPERATURE_HIGH = 'default_target_temperature_high' -CONF_DEFAULT_TARGET_TEMPERATURE_LOW = 'default_target_temperature_low' -CONF_DEFAULT_TRANSITION_LENGTH = 'default_transition_length' -CONF_DELAY = 'delay' -CONF_DELTA = 'delta' -CONF_DEVICE = 'device' -CONF_DEVICE_CLASS = 'device_class' -CONF_DIMENSIONS = 'dimensions' -CONF_DIO_PIN = 'dio_pin' -CONF_DIR_PIN = 'dir_pin' -CONF_DIRECTION = 'direction' -CONF_DIRECTION_OUTPUT = 'direction_output' -CONF_DISCOVERY = 'discovery' -CONF_DISCOVERY_PREFIX = 'discovery_prefix' -CONF_DISCOVERY_RETAIN = 'discovery_retain' -CONF_DISTANCE = 'distance' -CONF_DITHER = 'dither' -CONF_DIV_RATIO = 'div_ratio' -CONF_DNS1 = 'dns1' -CONF_DNS2 = 'dns2' -CONF_DOMAIN = 'domain' -CONF_DRY_ACTION = 'dry_action' -CONF_DRY_MODE = 'dry_mode' -CONF_DUMP = 'dump' -CONF_DURATION = 'duration' -CONF_EAP = 'eap' -CONF_ECHO_PIN = 'echo_pin' -CONF_EFFECT = 'effect' -CONF_EFFECTS = 'effects' -CONF_ELSE = 'else' -CONF_ENABLE_PIN = 'enable_pin' -CONF_ENABLE_TIME = 'enable_time' -CONF_ENERGY = 'energy' -CONF_ENTITY_ID = 'entity_id' -CONF_ESP8266_RESTORE_FROM_FLASH = 'esp8266_restore_from_flash' -CONF_ESPHOME = 'esphome' -CONF_ESPHOME_CORE_VERSION = 'esphome_core_version' -CONF_EVENT = 'event' -CONF_EXPIRE_AFTER = 'expire_after' -CONF_EXTERNAL_VCC = 'external_vcc' -CONF_FALLING_EDGE = 'falling_edge' -CONF_FAMILY = 'family' -CONF_FAN_MODE = 'fan_mode' -CONF_FAN_MODE_AUTO_ACTION = 'fan_mode_auto_action' -CONF_FAN_MODE_DIFFUSE_ACTION = 'fan_mode_diffuse_action' -CONF_FAN_MODE_FOCUS_ACTION = 'fan_mode_focus_action' -CONF_FAN_MODE_HIGH_ACTION = 'fan_mode_high_action' -CONF_FAN_MODE_LOW_ACTION = 'fan_mode_low_action' -CONF_FAN_MODE_MEDIUM_ACTION = 'fan_mode_medium_action' -CONF_FAN_MODE_MIDDLE_ACTION = 'fan_mode_middle_action' -CONF_FAN_MODE_OFF_ACTION = 'fan_mode_off_action' -CONF_FAN_MODE_ON_ACTION = 'fan_mode_on_action' -CONF_FAN_ONLY_ACTION = 'fan_only_action' -CONF_FAN_ONLY_MODE = 'fan_only_mode' -CONF_FAST_CONNECT = 'fast_connect' -CONF_FILE = 'file' -CONF_FILTER = 'filter' -CONF_FILTER_OUT = 'filter_out' -CONF_FILTERS = 'filters' -CONF_FLASH_LENGTH = 'flash_length' -CONF_FOR = 'for' -CONF_FORCE_UPDATE = 'force_update' -CONF_FORMALDEHYDE = 'formaldehyde' -CONF_FORMAT = 'format' -CONF_FREQUENCY = 'frequency' -CONF_FROM = 'from' -CONF_FULL_UPDATE_EVERY = 'full_update_every' -CONF_GAIN = 'gain' -CONF_GAMMA_CORRECT = 'gamma_correct' -CONF_GAS_RESISTANCE = 'gas_resistance' -CONF_GATEWAY = 'gateway' -CONF_GLYPHS = 'glyphs' -CONF_GPIO = 'gpio' -CONF_GREEN = 'green' -CONF_GROUP = 'group' -CONF_HARDWARE_UART = 'hardware_uart' -CONF_HEARTBEAT = 'heartbeat' -CONF_HEAT_ACTION = 'heat_action' -CONF_HEAT_MODE = 'heat_mode' -CONF_HEATER = 'heater' -CONF_HIDDEN = 'hidden' -CONF_HIDE_TIMESTAMP = 'hide_timestamp' -CONF_HIGH = 'high' -CONF_HIGH_VOLTAGE_REFERENCE = 'high_voltage_reference' -CONF_HOUR = 'hour' -CONF_HOURS = 'hours' -CONF_HUMIDITY = 'humidity' +CONF_CHANGE_MODE_EVERY = "change_mode_every" +CONF_CHANNEL = "channel" +CONF_CHANNELS = "channels" +CONF_CHIPSET = "chipset" +CONF_CLIENT_ID = "client_id" +CONF_CLK_PIN = "clk_pin" +CONF_CLOCK_PIN = "clock_pin" +CONF_CLOSE_ACTION = "close_action" +CONF_CLOSE_DURATION = "close_duration" +CONF_CLOSE_ENDSTOP = "close_endstop" +CONF_CO2 = "co2" +CONF_CODE = "code" +CONF_COLD_WHITE = "cold_white" +CONF_COLD_WHITE_COLOR_TEMPERATURE = "cold_white_color_temperature" +CONF_COLOR_CORRECT = "color_correct" +CONF_COLOR_TEMPERATURE = "color_temperature" +CONF_COLORS = "colors" +CONF_COMMAND = "command" +CONF_COMMAND_TOPIC = "command_topic" +CONF_COMMENT = "comment" +CONF_COMMIT = "commit" +CONF_COMPONENT_ID = "component_id" +CONF_COMPONENTS = "components" +CONF_CONDITION = "condition" +CONF_CONDITION_ID = "condition_id" +CONF_CONDUCTIVITY = "conductivity" +CONF_CONTRAST = "contrast" +CONF_COOL_ACTION = "cool_action" +CONF_COOL_MODE = "cool_mode" +CONF_COUNT_MODE = "count_mode" +CONF_CRON = "cron" +CONF_CS_PIN = "cs_pin" +CONF_CSS_INCLUDE = "css_include" +CONF_CSS_URL = "css_url" +CONF_CURRENT = "current" +CONF_CURRENT_OPERATION = "current_operation" +CONF_CURRENT_RESISTOR = "current_resistor" +CONF_DALLAS_ID = "dallas_id" +CONF_DATA = "data" +CONF_DATA_PIN = "data_pin" +CONF_DATA_PINS = "data_pins" +CONF_DATA_RATE = "data_rate" +CONF_DATA_TEMPLATE = "data_template" +CONF_DAYS_OF_MONTH = "days_of_month" +CONF_DAYS_OF_WEEK = "days_of_week" +CONF_DC_PIN = "dc_pin" +CONF_DEBOUNCE = "debounce" +CONF_DECELERATION = "deceleration" +CONF_DEFAULT_TARGET_TEMPERATURE_HIGH = "default_target_temperature_high" +CONF_DEFAULT_TARGET_TEMPERATURE_LOW = "default_target_temperature_low" +CONF_DEFAULT_TRANSITION_LENGTH = "default_transition_length" +CONF_DELAY = "delay" +CONF_DELTA = "delta" +CONF_DEVICE = "device" +CONF_DEVICE_CLASS = "device_class" +CONF_DIMENSIONS = "dimensions" +CONF_DIO_PIN = "dio_pin" +CONF_DIR_PIN = "dir_pin" +CONF_DIRECTION = "direction" +CONF_DIRECTION_OUTPUT = "direction_output" +CONF_DISCOVERY = "discovery" +CONF_DISCOVERY_PREFIX = "discovery_prefix" +CONF_DISCOVERY_RETAIN = "discovery_retain" +CONF_DISTANCE = "distance" +CONF_DITHER = "dither" +CONF_DIV_RATIO = "div_ratio" +CONF_DNS1 = "dns1" +CONF_DNS2 = "dns2" +CONF_DOMAIN = "domain" +CONF_DRY_ACTION = "dry_action" +CONF_DRY_MODE = "dry_mode" +CONF_DUMP = "dump" +CONF_DURATION = "duration" +CONF_EAP = "eap" +CONF_ECHO_PIN = "echo_pin" +CONF_EFFECT = "effect" +CONF_EFFECTS = "effects" +CONF_ELSE = "else" +CONF_ENABLE_PIN = "enable_pin" +CONF_ENABLE_TIME = "enable_time" +CONF_ENERGY = "energy" +CONF_ENTITY_ID = "entity_id" +CONF_ESP8266_RESTORE_FROM_FLASH = "esp8266_restore_from_flash" +CONF_ESPHOME = "esphome" +CONF_ESPHOME_CORE_VERSION = "esphome_core_version" +CONF_EVENT = "event" +CONF_EXPIRE_AFTER = "expire_after" +CONF_EXTERNAL_VCC = "external_vcc" +CONF_FALLING_EDGE = "falling_edge" +CONF_FAMILY = "family" +CONF_FAN_MODE = "fan_mode" +CONF_FAN_MODE_AUTO_ACTION = "fan_mode_auto_action" +CONF_FAN_MODE_DIFFUSE_ACTION = "fan_mode_diffuse_action" +CONF_FAN_MODE_FOCUS_ACTION = "fan_mode_focus_action" +CONF_FAN_MODE_HIGH_ACTION = "fan_mode_high_action" +CONF_FAN_MODE_LOW_ACTION = "fan_mode_low_action" +CONF_FAN_MODE_MEDIUM_ACTION = "fan_mode_medium_action" +CONF_FAN_MODE_MIDDLE_ACTION = "fan_mode_middle_action" +CONF_FAN_MODE_OFF_ACTION = "fan_mode_off_action" +CONF_FAN_MODE_ON_ACTION = "fan_mode_on_action" +CONF_FAN_ONLY_ACTION = "fan_only_action" +CONF_FAN_ONLY_MODE = "fan_only_mode" +CONF_FAST_CONNECT = "fast_connect" +CONF_FILE = "file" +CONF_FILTER = "filter" +CONF_FILTER_OUT = "filter_out" +CONF_FILTERS = "filters" +CONF_FLASH_LENGTH = "flash_length" +CONF_FOR = "for" +CONF_FORCE_UPDATE = "force_update" +CONF_FORMALDEHYDE = "formaldehyde" +CONF_FORMAT = "format" +CONF_FREQUENCY = "frequency" +CONF_FROM = "from" +CONF_FULL_UPDATE_EVERY = "full_update_every" +CONF_GAIN = "gain" +CONF_GAMMA_CORRECT = "gamma_correct" +CONF_GAS_RESISTANCE = "gas_resistance" +CONF_GATEWAY = "gateway" +CONF_GLYPHS = "glyphs" +CONF_GPIO = "gpio" +CONF_GREEN = "green" +CONF_GROUP = "group" +CONF_HARDWARE_UART = "hardware_uart" +CONF_HEARTBEAT = "heartbeat" +CONF_HEAT_ACTION = "heat_action" +CONF_HEAT_MODE = "heat_mode" +CONF_HEATER = "heater" +CONF_HIDDEN = "hidden" +CONF_HIDE_TIMESTAMP = "hide_timestamp" +CONF_HIGH = "high" +CONF_HIGH_VOLTAGE_REFERENCE = "high_voltage_reference" +CONF_HOUR = "hour" +CONF_HOURS = "hours" +CONF_HUMIDITY = "humidity" CONF_HYSTERESIS = "hysteresis" -CONF_I2C = 'i2c' -CONF_I2C_ID = 'i2c_id' -CONF_ICON = 'icon' -CONF_ID = 'id' -CONF_IDENTITY = 'identity' -CONF_IDLE = 'idle' -CONF_IDLE_ACTION = 'idle_action' -CONF_IDLE_LEVEL = 'idle_level' -CONF_IDLE_TIME = 'idle_time' -CONF_IF = 'if' -CONF_IIR_FILTER = 'iir_filter' -CONF_ILLUMINANCE = 'illuminance' -CONF_IMPEDANCE = 'impedance' -CONF_INCLUDES = 'includes' -CONF_INDEX = 'index' -CONF_INDOOR = 'indoor' -CONF_INITIAL_MODE = 'initial_mode' -CONF_INITIAL_VALUE = 'initial_value' -CONF_INTEGRATION_TIME = 'integration_time' -CONF_INTENSITY = 'intensity' -CONF_INTERLOCK = 'interlock' -CONF_INTERNAL = 'internal' -CONF_INTERNAL_FILTER = 'internal_filter' -CONF_INTERVAL = 'interval' -CONF_INVALID_COOLDOWN = 'invalid_cooldown' -CONF_INVERT = 'invert' -CONF_INVERTED = 'inverted' -CONF_IP_ADDRESS = 'ip_address' -CONF_JS_INCLUDE = 'js_include' -CONF_JS_URL = 'js_url' -CONF_JVC = 'jvc' -CONF_KEEP_ON_TIME = 'keep_on_time' -CONF_KEEPALIVE = 'keepalive' -CONF_KEY = 'key' -CONF_LAMBDA = 'lambda' -CONF_LENGTH = 'length' -CONF_LEVEL = 'level' -CONF_LG = 'lg' -CONF_LIBRARIES = 'libraries' -CONF_LIGHT = 'light' -CONF_LIGHTNING_ENERGY = 'lightning_energy' -CONF_LIGHTNING_THRESHOLD = 'lightning_threshold' -CONF_LOADED_INTEGRATIONS = 'loaded_integrations' -CONF_LOCAL = 'local' -CONF_LOG_TOPIC = 'log_topic' -CONF_LOGGER = 'logger' -CONF_LOGS = 'logs' -CONF_LOW = 'low' -CONF_LOW_VOLTAGE_REFERENCE = 'low_voltage_reference' -CONF_MAC_ADDRESS = 'mac_address' -CONF_MAINS_FILTER = 'mains_filter' -CONF_MAKE_ID = 'make_id' -CONF_MANUAL_IP = 'manual_ip' -CONF_MANUFACTURER_ID = 'manufacturer_id' -CONF_MASK_DISTURBER = 'mask_disturber' -CONF_MAX_CURRENT = 'max_current' -CONF_MAX_DURATION = 'max_duration' -CONF_MAX_LENGTH = 'max_length' -CONF_MAX_LEVEL = 'max_level' -CONF_MAX_POWER = 'max_power' -CONF_MAX_REFRESH_RATE = 'max_refresh_rate' -CONF_MAX_SPEED = 'max_speed' -CONF_MAX_TEMPERATURE = 'max_temperature' -CONF_MAX_VALUE = 'max_value' -CONF_MAX_VOLTAGE = 'max_voltage' -CONF_MEASUREMENT_DURATION = 'measurement_duration' -CONF_MEASUREMENT_SEQUENCE_NUMBER = 'measurement_sequence_number' -CONF_MEDIUM = 'medium' -CONF_MEMORY_BLOCKS = 'memory_blocks' -CONF_METHOD = 'method' -CONF_MIN_LENGTH = 'min_length' -CONF_MIN_LEVEL = 'min_level' -CONF_MIN_POWER = 'min_power' -CONF_MIN_TEMPERATURE = 'min_temperature' -CONF_MIN_VALUE = 'min_value' -CONF_MINUTE = 'minute' -CONF_MINUTES = 'minutes' -CONF_MISO_PIN = 'miso_pin' -CONF_MODE = 'mode' -CONF_MODEL = 'model' -CONF_MOISTURE = 'moisture' -CONF_MONTHS = 'months' -CONF_MOSI_PIN = 'mosi_pin' -CONF_MOTION = 'motion' -CONF_MOVEMENT_COUNTER = 'movement_counter' -CONF_MQTT = 'mqtt' -CONF_MQTT_ID = 'mqtt_id' -CONF_MULTIPLEXER = 'multiplexer' -CONF_MULTIPLY = 'multiply' -CONF_NAME = 'name' -CONF_NBITS = 'nbits' -CONF_NEC = 'nec' -CONF_NETWORKS = 'networks' -CONF_NOISE_LEVEL = 'noise_level' -CONF_NUM_ATTEMPTS = 'num_attempts' -CONF_NUM_CHANNELS = 'num_channels' -CONF_NUM_CHIPS = 'num_chips' -CONF_NUM_LEDS = 'num_leds' -CONF_NUMBER = 'number' -CONF_OFF_MODE = 'off_mode' -CONF_OFFSET = 'offset' -CONF_ON = 'on' -CONF_ON_BLE_ADVERTISE = 'on_ble_advertise' -CONF_ON_BLE_MANUFACTURER_DATA_ADVERTISE = 'on_ble_manufacturer_data_advertise' -CONF_ON_BLE_SERVICE_DATA_ADVERTISE = 'on_ble_service_data_advertise' -CONF_ON_BOOT = 'on_boot' -CONF_ON_CLICK = 'on_click' -CONF_ON_DOUBLE_CLICK = 'on_double_click' -CONF_ON_JSON_MESSAGE = 'on_json_message' -CONF_ON_LOOP = 'on_loop' -CONF_ON_MESSAGE = 'on_message' -CONF_ON_MULTI_CLICK = 'on_multi_click' -CONF_ON_PRESS = 'on_press' -CONF_ON_RAW_VALUE = 'on_raw_value' -CONF_ON_RELEASE = 'on_release' -CONF_ON_SHUTDOWN = 'on_shutdown' -CONF_ON_STATE = 'on_state' -CONF_ON_TAG = 'on_tag' -CONF_ON_TIME = 'on_time' -CONF_ON_TIME_SYNC = 'on_time_sync' -CONF_ON_TURN_OFF = 'on_turn_off' -CONF_ON_TURN_ON = 'on_turn_on' -CONF_ON_VALUE = 'on_value' -CONF_ON_VALUE_RANGE = 'on_value_range' -CONF_ONE = 'one' -CONF_OPEN_ACTION = 'open_action' -CONF_OPEN_DRAIN_INTERRUPT = 'open_drain_interrupt' -CONF_OPEN_DURATION = 'open_duration' -CONF_OPEN_ENDSTOP = 'open_endstop' -CONF_OPTIMISTIC = 'optimistic' -CONF_OR = 'or' -CONF_OSCILLATING = 'oscillating' -CONF_OSCILLATION_COMMAND_TOPIC = 'oscillation_command_topic' -CONF_OSCILLATION_OUTPUT = 'oscillation_output' -CONF_OSCILLATION_STATE_TOPIC = 'oscillation_state_topic' -CONF_OTA = 'ota' -CONF_OUTPUT = 'output' -CONF_OUTPUT_ID = 'output_id' -CONF_OUTPUTS = 'outputs' -CONF_OVERSAMPLING = 'oversampling' -CONF_PACKAGES = 'packages' -CONF_PAGE_ID = 'page_id' -CONF_PAGES = 'pages' -CONF_PANASONIC = 'panasonic' -CONF_PASSWORD = 'password' -CONF_PAYLOAD = 'payload' -CONF_PAYLOAD_AVAILABLE = 'payload_available' -CONF_PAYLOAD_NOT_AVAILABLE = 'payload_not_available' -CONF_PERIOD = 'period' -CONF_PHASE_BALANCER = 'phase_balancer' -CONF_PIN = 'pin' -CONF_PIN_A = 'pin_a' -CONF_PIN_B = 'pin_b' -CONF_PIN_C = 'pin_c' -CONF_PIN_D = 'pin_d' -CONF_PINS = 'pins' -CONF_PLATFORM = 'platform' -CONF_PLATFORMIO_OPTIONS = 'platformio_options' -CONF_PM_1_0 = 'pm_1_0' -CONF_PM_10_0 = 'pm_10_0' -CONF_PM_2_5 = 'pm_2_5' -CONF_PM_4_0 = 'pm_4_0' -CONF_PM_SIZE = 'pm_size' -CONF_PMC_0_5 = 'pmc_0_5' -CONF_PMC_1_0 = 'pmc_1_0' -CONF_PMC_10_0 = 'pmc_10_0' -CONF_PMC_2_5 = 'pmc_2_5' -CONF_PMC_4_0 = 'pmc_4_0' -CONF_PORT = 'port' -CONF_POSITION = 'position' -CONF_POSITION_ACTION = 'position_action' -CONF_POWER = 'power' -CONF_POWER_FACTOR = 'power_factor' -CONF_POWER_ON_VALUE = 'power_on_value' -CONF_POWER_SAVE_MODE = 'power_save_mode' -CONF_POWER_SUPPLY = 'power_supply' -CONF_PRESSURE = 'pressure' -CONF_PRIORITY = 'priority' -CONF_PROTOCOL = 'protocol' -CONF_PULL_MODE = 'pull_mode' -CONF_PULSE_LENGTH = 'pulse_length' -CONF_QOS = 'qos' -CONF_RANDOM = 'random' -CONF_RANGE = 'range' -CONF_RANGE_FROM = 'range_from' -CONF_RANGE_TO = 'range_to' -CONF_RATE = 'rate' -CONF_RAW = 'raw' -CONF_RC_CODE_1 = 'rc_code_1' -CONF_RC_CODE_2 = 'rc_code_2' -CONF_REBOOT_TIMEOUT = 'reboot_timeout' -CONF_RECEIVE_TIMEOUT = 'receive_timeout' -CONF_RED = 'red' -CONF_REFERENCE_RESISTANCE = 'reference_resistance' -CONF_REFERENCE_TEMPERATURE = 'reference_temperature' -CONF_REPEAT = 'repeat' -CONF_REPOSITORY = 'repository' -CONF_RESET_PIN = 'reset_pin' -CONF_RESIZE = 'resize' -CONF_RESOLUTION = 'resolution' -CONF_RESTORE = 'restore' -CONF_RESTORE_MODE = 'restore_mode' -CONF_RESTORE_STATE = 'restore_state' -CONF_RESTORE_VALUE = 'restore_value' -CONF_RETAIN = 'retain' -CONF_RGB_ORDER = 'rgb_order' -CONF_RGBW = 'rgbw' -CONF_RISING_EDGE = 'rising_edge' -CONF_ROTATION = 'rotation' -CONF_RS_PIN = 'rs_pin' -CONF_RTD_NOMINAL_RESISTANCE = 'rtd_nominal_resistance' -CONF_RTD_WIRES = 'rtd_wires' -CONF_RUN_CYCLES = 'run_cycles' -CONF_RUN_DURATION = 'run_duration' -CONF_RW_PIN = 'rw_pin' -CONF_RX_BUFFER_SIZE = 'rx_buffer_size' -CONF_RX_ONLY = 'rx_only' -CONF_RX_PIN = 'rx_pin' -CONF_SAFE_MODE = 'safe_mode' -CONF_SAMSUNG = 'samsung' -CONF_SCAN = 'scan' -CONF_SCL = 'scl' -CONF_SCL_PIN = 'scl_pin' -CONF_SDA = 'sda' -CONF_SDO_PIN = 'sdo_pin' -CONF_SECOND = 'second' -CONF_SECONDS = 'seconds' -CONF_SEGMENTS = 'segments' -CONF_SEL_PIN = 'sel_pin' -CONF_SEND_EVERY = 'send_every' -CONF_SEND_FIRST_AT = 'send_first_at' -CONF_SENSOR = 'sensor' -CONF_SENSOR_ID = 'sensor_id' -CONF_SENSORS = 'sensors' -CONF_SEQUENCE = 'sequence' -CONF_SERVERS = 'servers' -CONF_SERVICE = 'service' -CONF_SERVICE_UUID = 'service_uuid' -CONF_SERVICES = 'services' -CONF_SETUP_MODE = 'setup_mode' -CONF_SETUP_PRIORITY = 'setup_priority' -CONF_SHUNT_RESISTANCE = 'shunt_resistance' -CONF_SHUNT_VOLTAGE = 'shunt_voltage' -CONF_SHUTDOWN_MESSAGE = 'shutdown_message' -CONF_SIZE = 'size' -CONF_SLEEP_DURATION = 'sleep_duration' -CONF_SLEEP_PIN = 'sleep_pin' -CONF_SLEEP_WHEN_DONE = 'sleep_when_done' -CONF_SONY = 'sony' -CONF_SPEED = 'speed' -CONF_SPEED_COMMAND_TOPIC = 'speed_command_topic' -CONF_SPEED_STATE_TOPIC = 'speed_state_topic' -CONF_SPI_ID = 'spi_id' -CONF_SPIKE_REJECTION = 'spike_rejection' -CONF_SSID = 'ssid' -CONF_SSL_FINGERPRINTS = 'ssl_fingerprints' -CONF_STATE = 'state' -CONF_STATE_TOPIC = 'state_topic' -CONF_STATIC_IP = 'static_ip' -CONF_STEP_MODE = 'step_mode' -CONF_STEP_PIN = 'step_pin' -CONF_STOP = 'stop' -CONF_STOP_ACTION = 'stop_action' -CONF_SUBNET = 'subnet' -CONF_SUBSTITUTIONS = 'substitutions' -CONF_SUPPORTS_COOL = 'supports_cool' -CONF_SUPPORTS_HEAT = 'supports_heat' -CONF_SWING_BOTH_ACTION = 'swing_both_action' -CONF_SWING_HORIZONTAL_ACTION = 'swing_horizontal_action' -CONF_SWING_MODE = 'swing_mode' -CONF_SWING_OFF_ACTION = 'swing_off_action' -CONF_SWING_VERTICAL_ACTION = 'swing_vertical_action' +CONF_I2C = "i2c" +CONF_I2C_ID = "i2c_id" +CONF_ICON = "icon" +CONF_ID = "id" +CONF_IDENTITY = "identity" +CONF_IDLE = "idle" +CONF_IDLE_ACTION = "idle_action" +CONF_IDLE_LEVEL = "idle_level" +CONF_IDLE_TIME = "idle_time" +CONF_IF = "if" +CONF_IIR_FILTER = "iir_filter" +CONF_ILLUMINANCE = "illuminance" +CONF_IMPEDANCE = "impedance" +CONF_INCLUDES = "includes" +CONF_INDEX = "index" +CONF_INDOOR = "indoor" +CONF_INITIAL_MODE = "initial_mode" +CONF_INITIAL_VALUE = "initial_value" +CONF_INTEGRATION_TIME = "integration_time" +CONF_INTENSITY = "intensity" +CONF_INTERLOCK = "interlock" +CONF_INTERNAL = "internal" +CONF_INTERNAL_FILTER = "internal_filter" +CONF_INTERVAL = "interval" +CONF_INVALID_COOLDOWN = "invalid_cooldown" +CONF_INVERT = "invert" +CONF_INVERTED = "inverted" +CONF_IP_ADDRESS = "ip_address" +CONF_JS_INCLUDE = "js_include" +CONF_JS_URL = "js_url" +CONF_JVC = "jvc" +CONF_KEEP_ON_TIME = "keep_on_time" +CONF_KEEPALIVE = "keepalive" +CONF_KEY = "key" +CONF_LAMBDA = "lambda" +CONF_LENGTH = "length" +CONF_LEVEL = "level" +CONF_LG = "lg" +CONF_LIBRARIES = "libraries" +CONF_LIGHT = "light" +CONF_LIGHTNING_ENERGY = "lightning_energy" +CONF_LIGHTNING_THRESHOLD = "lightning_threshold" +CONF_LOADED_INTEGRATIONS = "loaded_integrations" +CONF_LOCAL = "local" +CONF_LOG_TOPIC = "log_topic" +CONF_LOGGER = "logger" +CONF_LOGS = "logs" +CONF_LOW = "low" +CONF_LOW_VOLTAGE_REFERENCE = "low_voltage_reference" +CONF_MAC_ADDRESS = "mac_address" +CONF_MAINS_FILTER = "mains_filter" +CONF_MAKE_ID = "make_id" +CONF_MANUAL_IP = "manual_ip" +CONF_MANUFACTURER_ID = "manufacturer_id" +CONF_MASK_DISTURBER = "mask_disturber" +CONF_MAX_CURRENT = "max_current" +CONF_MAX_DURATION = "max_duration" +CONF_MAX_LENGTH = "max_length" +CONF_MAX_LEVEL = "max_level" +CONF_MAX_POWER = "max_power" +CONF_MAX_REFRESH_RATE = "max_refresh_rate" +CONF_MAX_SPEED = "max_speed" +CONF_MAX_TEMPERATURE = "max_temperature" +CONF_MAX_VALUE = "max_value" +CONF_MAX_VOLTAGE = "max_voltage" +CONF_MEASUREMENT_DURATION = "measurement_duration" +CONF_MEASUREMENT_SEQUENCE_NUMBER = "measurement_sequence_number" +CONF_MEDIUM = "medium" +CONF_MEMORY_BLOCKS = "memory_blocks" +CONF_METHOD = "method" +CONF_MIN_LENGTH = "min_length" +CONF_MIN_LEVEL = "min_level" +CONF_MIN_POWER = "min_power" +CONF_MIN_TEMPERATURE = "min_temperature" +CONF_MIN_VALUE = "min_value" +CONF_MINUTE = "minute" +CONF_MINUTES = "minutes" +CONF_MISO_PIN = "miso_pin" +CONF_MODE = "mode" +CONF_MODEL = "model" +CONF_MOISTURE = "moisture" +CONF_MONTHS = "months" +CONF_MOSI_PIN = "mosi_pin" +CONF_MOTION = "motion" +CONF_MOVEMENT_COUNTER = "movement_counter" +CONF_MQTT = "mqtt" +CONF_MQTT_ID = "mqtt_id" +CONF_MULTIPLEXER = "multiplexer" +CONF_MULTIPLY = "multiply" +CONF_NAME = "name" +CONF_NBITS = "nbits" +CONF_NEC = "nec" +CONF_NETWORKS = "networks" +CONF_NOISE_LEVEL = "noise_level" +CONF_NUM_ATTEMPTS = "num_attempts" +CONF_NUM_CHANNELS = "num_channels" +CONF_NUM_CHIPS = "num_chips" +CONF_NUM_LEDS = "num_leds" +CONF_NUMBER = "number" +CONF_OFF_MODE = "off_mode" +CONF_OFFSET = "offset" +CONF_ON = "on" +CONF_ON_BLE_ADVERTISE = "on_ble_advertise" +CONF_ON_BLE_MANUFACTURER_DATA_ADVERTISE = "on_ble_manufacturer_data_advertise" +CONF_ON_BLE_SERVICE_DATA_ADVERTISE = "on_ble_service_data_advertise" +CONF_ON_BOOT = "on_boot" +CONF_ON_CLICK = "on_click" +CONF_ON_DOUBLE_CLICK = "on_double_click" +CONF_ON_JSON_MESSAGE = "on_json_message" +CONF_ON_LOOP = "on_loop" +CONF_ON_MESSAGE = "on_message" +CONF_ON_MULTI_CLICK = "on_multi_click" +CONF_ON_PRESS = "on_press" +CONF_ON_RAW_VALUE = "on_raw_value" +CONF_ON_RELEASE = "on_release" +CONF_ON_SHUTDOWN = "on_shutdown" +CONF_ON_STATE = "on_state" +CONF_ON_TAG = "on_tag" +CONF_ON_TIME = "on_time" +CONF_ON_TIME_SYNC = "on_time_sync" +CONF_ON_TURN_OFF = "on_turn_off" +CONF_ON_TURN_ON = "on_turn_on" +CONF_ON_VALUE = "on_value" +CONF_ON_VALUE_RANGE = "on_value_range" +CONF_ONE = "one" +CONF_OPEN_ACTION = "open_action" +CONF_OPEN_DRAIN_INTERRUPT = "open_drain_interrupt" +CONF_OPEN_DURATION = "open_duration" +CONF_OPEN_ENDSTOP = "open_endstop" +CONF_OPTIMISTIC = "optimistic" +CONF_OR = "or" +CONF_OSCILLATING = "oscillating" +CONF_OSCILLATION_COMMAND_TOPIC = "oscillation_command_topic" +CONF_OSCILLATION_OUTPUT = "oscillation_output" +CONF_OSCILLATION_STATE_TOPIC = "oscillation_state_topic" +CONF_OTA = "ota" +CONF_OUTPUT = "output" +CONF_OUTPUT_ID = "output_id" +CONF_OUTPUTS = "outputs" +CONF_OVERSAMPLING = "oversampling" +CONF_PACKAGES = "packages" +CONF_PAGE_ID = "page_id" +CONF_PAGES = "pages" +CONF_PANASONIC = "panasonic" +CONF_PASSWORD = "password" +CONF_PAYLOAD = "payload" +CONF_PAYLOAD_AVAILABLE = "payload_available" +CONF_PAYLOAD_NOT_AVAILABLE = "payload_not_available" +CONF_PERIOD = "period" +CONF_PHASE_BALANCER = "phase_balancer" +CONF_PIN = "pin" +CONF_PIN_A = "pin_a" +CONF_PIN_B = "pin_b" +CONF_PIN_C = "pin_c" +CONF_PIN_D = "pin_d" +CONF_PINS = "pins" +CONF_PLATFORM = "platform" +CONF_PLATFORMIO_OPTIONS = "platformio_options" +CONF_PM_1_0 = "pm_1_0" +CONF_PM_10_0 = "pm_10_0" +CONF_PM_2_5 = "pm_2_5" +CONF_PM_4_0 = "pm_4_0" +CONF_PM_SIZE = "pm_size" +CONF_PMC_0_5 = "pmc_0_5" +CONF_PMC_1_0 = "pmc_1_0" +CONF_PMC_10_0 = "pmc_10_0" +CONF_PMC_2_5 = "pmc_2_5" +CONF_PMC_4_0 = "pmc_4_0" +CONF_PORT = "port" +CONF_POSITION = "position" +CONF_POSITION_ACTION = "position_action" +CONF_POWER = "power" +CONF_POWER_FACTOR = "power_factor" +CONF_POWER_ON_VALUE = "power_on_value" +CONF_POWER_SAVE_MODE = "power_save_mode" +CONF_POWER_SUPPLY = "power_supply" +CONF_PRESSURE = "pressure" +CONF_PRIORITY = "priority" +CONF_PROTOCOL = "protocol" +CONF_PULL_MODE = "pull_mode" +CONF_PULSE_LENGTH = "pulse_length" +CONF_QOS = "qos" +CONF_RANDOM = "random" +CONF_RANGE = "range" +CONF_RANGE_FROM = "range_from" +CONF_RANGE_TO = "range_to" +CONF_RATE = "rate" +CONF_RAW = "raw" +CONF_RC_CODE_1 = "rc_code_1" +CONF_RC_CODE_2 = "rc_code_2" +CONF_REBOOT_TIMEOUT = "reboot_timeout" +CONF_RECEIVE_TIMEOUT = "receive_timeout" +CONF_RED = "red" +CONF_REFERENCE_RESISTANCE = "reference_resistance" +CONF_REFERENCE_TEMPERATURE = "reference_temperature" +CONF_REPEAT = "repeat" +CONF_REPOSITORY = "repository" +CONF_RESET_PIN = "reset_pin" +CONF_RESIZE = "resize" +CONF_RESOLUTION = "resolution" +CONF_RESTORE = "restore" +CONF_RESTORE_MODE = "restore_mode" +CONF_RESTORE_STATE = "restore_state" +CONF_RESTORE_VALUE = "restore_value" +CONF_RETAIN = "retain" +CONF_RGB_ORDER = "rgb_order" +CONF_RGBW = "rgbw" +CONF_RISING_EDGE = "rising_edge" +CONF_ROTATION = "rotation" +CONF_RS_PIN = "rs_pin" +CONF_RTD_NOMINAL_RESISTANCE = "rtd_nominal_resistance" +CONF_RTD_WIRES = "rtd_wires" +CONF_RUN_CYCLES = "run_cycles" +CONF_RUN_DURATION = "run_duration" +CONF_RW_PIN = "rw_pin" +CONF_RX_BUFFER_SIZE = "rx_buffer_size" +CONF_RX_ONLY = "rx_only" +CONF_RX_PIN = "rx_pin" +CONF_SAFE_MODE = "safe_mode" +CONF_SAMSUNG = "samsung" +CONF_SCAN = "scan" +CONF_SCL = "scl" +CONF_SCL_PIN = "scl_pin" +CONF_SDA = "sda" +CONF_SDO_PIN = "sdo_pin" +CONF_SECOND = "second" +CONF_SECONDS = "seconds" +CONF_SEGMENTS = "segments" +CONF_SEL_PIN = "sel_pin" +CONF_SEND_EVERY = "send_every" +CONF_SEND_FIRST_AT = "send_first_at" +CONF_SENSOR = "sensor" +CONF_SENSOR_ID = "sensor_id" +CONF_SENSORS = "sensors" +CONF_SEQUENCE = "sequence" +CONF_SERVERS = "servers" +CONF_SERVICE = "service" +CONF_SERVICE_UUID = "service_uuid" +CONF_SERVICES = "services" +CONF_SETUP_MODE = "setup_mode" +CONF_SETUP_PRIORITY = "setup_priority" +CONF_SHUNT_RESISTANCE = "shunt_resistance" +CONF_SHUNT_VOLTAGE = "shunt_voltage" +CONF_SHUTDOWN_MESSAGE = "shutdown_message" +CONF_SIZE = "size" +CONF_SLEEP_DURATION = "sleep_duration" +CONF_SLEEP_PIN = "sleep_pin" +CONF_SLEEP_WHEN_DONE = "sleep_when_done" +CONF_SONY = "sony" +CONF_SPEED = "speed" +CONF_SPEED_COMMAND_TOPIC = "speed_command_topic" +CONF_SPEED_STATE_TOPIC = "speed_state_topic" +CONF_SPI_ID = "spi_id" +CONF_SPIKE_REJECTION = "spike_rejection" +CONF_SSID = "ssid" +CONF_SSL_FINGERPRINTS = "ssl_fingerprints" +CONF_STATE = "state" +CONF_STATE_TOPIC = "state_topic" +CONF_STATIC_IP = "static_ip" +CONF_STEP_MODE = "step_mode" +CONF_STEP_PIN = "step_pin" +CONF_STOP = "stop" +CONF_STOP_ACTION = "stop_action" +CONF_SUBNET = "subnet" +CONF_SUBSTITUTIONS = "substitutions" +CONF_SUPPORTS_COOL = "supports_cool" +CONF_SUPPORTS_HEAT = "supports_heat" +CONF_SWING_BOTH_ACTION = "swing_both_action" +CONF_SWING_HORIZONTAL_ACTION = "swing_horizontal_action" +CONF_SWING_MODE = "swing_mode" +CONF_SWING_OFF_ACTION = "swing_off_action" +CONF_SWING_VERTICAL_ACTION = "swing_vertical_action" CONF_SWITCH_DATAPOINT = "switch_datapoint" -CONF_SWITCHES = 'switches' -CONF_SYNC = 'sync' -CONF_TABLET = 'tablet' -CONF_TAG = 'tag' -CONF_TARGET = 'target' -CONF_TARGET_TEMPERATURE = 'target_temperature' -CONF_TARGET_TEMPERATURE_HIGH = 'target_temperature_high' -CONF_TARGET_TEMPERATURE_LOW = 'target_temperature_low' -CONF_TEMPERATURE = 'temperature' -CONF_TEMPERATURE_STEP = 'temperature_step' -CONF_TEXT_SENSORS = 'text_sensors' -CONF_THEN = 'then' -CONF_THRESHOLD = 'threshold' -CONF_THROTTLE = 'throttle' -CONF_TILT = 'tilt' -CONF_TILT_ACTION = 'tilt_action' -CONF_TILT_LAMBDA = 'tilt_lambda' -CONF_TIME = 'time' -CONF_TIME_ID = 'time_id' -CONF_TIMEOUT = 'timeout' -CONF_TIMES = 'times' -CONF_TIMEZONE = 'timezone' -CONF_TIMING = 'timing' -CONF_TO = 'to' -CONF_TOLERANCE = 'tolerance' -CONF_TOPIC = 'topic' -CONF_TOPIC_PREFIX = 'topic_prefix' +CONF_SWITCHES = "switches" +CONF_SYNC = "sync" +CONF_TABLET = "tablet" +CONF_TAG = "tag" +CONF_TARGET = "target" +CONF_TARGET_TEMPERATURE = "target_temperature" +CONF_TARGET_TEMPERATURE_HIGH = "target_temperature_high" +CONF_TARGET_TEMPERATURE_LOW = "target_temperature_low" +CONF_TEMPERATURE = "temperature" +CONF_TEMPERATURE_STEP = "temperature_step" +CONF_TEXT_SENSORS = "text_sensors" +CONF_THEN = "then" +CONF_THRESHOLD = "threshold" +CONF_THROTTLE = "throttle" +CONF_TILT = "tilt" +CONF_TILT_ACTION = "tilt_action" +CONF_TILT_LAMBDA = "tilt_lambda" +CONF_TIME = "time" +CONF_TIME_ID = "time_id" +CONF_TIMEOUT = "timeout" +CONF_TIMES = "times" +CONF_TIMEZONE = "timezone" +CONF_TIMING = "timing" +CONF_TO = "to" +CONF_TOLERANCE = "tolerance" +CONF_TOPIC = "topic" +CONF_TOPIC_PREFIX = "topic_prefix" CONF_TOTAL = "total" -CONF_TRANSITION_LENGTH = 'transition_length' -CONF_TRIGGER_ID = 'trigger_id' -CONF_TRIGGER_PIN = 'trigger_pin' -CONF_TURN_OFF_ACTION = 'turn_off_action' -CONF_TURN_ON_ACTION = 'turn_on_action' -CONF_TVOC = 'tvoc' -CONF_TX_BUFFER_SIZE = 'tx_buffer_size' -CONF_TX_PIN = 'tx_pin' -CONF_TX_POWER = 'tx_power' -CONF_TYPE = 'type' -CONF_TYPE_ID = 'type_id' -CONF_UART_ID = 'uart_id' -CONF_UID = 'uid' -CONF_UNIQUE = 'unique' -CONF_UNIT_OF_MEASUREMENT = 'unit_of_measurement' -CONF_UPDATE_INTERVAL = 'update_interval' -CONF_UPDATE_ON_BOOT = 'update_on_boot' -CONF_URL = 'url' -CONF_USE_ADDRESS = 'use_address' -CONF_USERNAME = 'username' -CONF_UUID = 'uuid' -CONF_VALUE = 'value' -CONF_VARIABLES = 'variables' -CONF_VARIANT = 'variant' -CONF_VISUAL = 'visual' -CONF_VOLTAGE = 'voltage' -CONF_VOLTAGE_ATTENUATION = 'voltage_attenuation' -CONF_VOLTAGE_DIVIDER = 'voltage_divider' -CONF_WAIT_TIME = 'wait_time' -CONF_WAIT_UNTIL = 'wait_until' -CONF_WAKEUP_PIN = 'wakeup_pin' -CONF_WARM_WHITE = 'warm_white' -CONF_WARM_WHITE_COLOR_TEMPERATURE = 'warm_white_color_temperature' -CONF_WATCHDOG_THRESHOLD = 'watchdog_threshold' -CONF_WEIGHT = 'weight' -CONF_WHILE = 'while' -CONF_WHITE = 'white' -CONF_WIDTH = 'width' -CONF_WIFI = 'wifi' -CONF_WILL_MESSAGE = 'will_message' -CONF_WIND_DIRECTION_DEGREES = 'wind_direction_degrees' -CONF_WIND_SPEED = 'wind_speed' -CONF_WINDOW_SIZE = 'window_size' -CONF_ZERO = 'zero' +CONF_TRANSITION_LENGTH = "transition_length" +CONF_TRIGGER_ID = "trigger_id" +CONF_TRIGGER_PIN = "trigger_pin" +CONF_TURN_OFF_ACTION = "turn_off_action" +CONF_TURN_ON_ACTION = "turn_on_action" +CONF_TVOC = "tvoc" +CONF_TX_BUFFER_SIZE = "tx_buffer_size" +CONF_TX_PIN = "tx_pin" +CONF_TX_POWER = "tx_power" +CONF_TYPE = "type" +CONF_TYPE_ID = "type_id" +CONF_UART_ID = "uart_id" +CONF_UID = "uid" +CONF_UNIQUE = "unique" +CONF_UNIT_OF_MEASUREMENT = "unit_of_measurement" +CONF_UPDATE_INTERVAL = "update_interval" +CONF_UPDATE_ON_BOOT = "update_on_boot" +CONF_URL = "url" +CONF_USE_ADDRESS = "use_address" +CONF_USERNAME = "username" +CONF_UUID = "uuid" +CONF_VALUE = "value" +CONF_VARIABLES = "variables" +CONF_VARIANT = "variant" +CONF_VISUAL = "visual" +CONF_VOLTAGE = "voltage" +CONF_VOLTAGE_ATTENUATION = "voltage_attenuation" +CONF_VOLTAGE_DIVIDER = "voltage_divider" +CONF_WAIT_TIME = "wait_time" +CONF_WAIT_UNTIL = "wait_until" +CONF_WAKEUP_PIN = "wakeup_pin" +CONF_WARM_WHITE = "warm_white" +CONF_WARM_WHITE_COLOR_TEMPERATURE = "warm_white_color_temperature" +CONF_WATCHDOG_THRESHOLD = "watchdog_threshold" +CONF_WEIGHT = "weight" +CONF_WHILE = "while" +CONF_WHITE = "white" +CONF_WIDTH = "width" +CONF_WIFI = "wifi" +CONF_WILL_MESSAGE = "will_message" +CONF_WIND_DIRECTION_DEGREES = "wind_direction_degrees" +CONF_WIND_SPEED = "wind_speed" +CONF_WINDOW_SIZE = "window_size" +CONF_ZERO = "zero" -ENV_NOGITIGNORE = 'ESPHOME_NOGITIGNORE' -ENV_QUICKWIZARD = 'ESPHOME_QUICKWIZARD' +ENV_NOGITIGNORE = "ESPHOME_NOGITIGNORE" +ENV_QUICKWIZARD = "ESPHOME_QUICKWIZARD" -ICON_ACCELERATION = 'mdi:axis-arrow' -ICON_ACCELERATION_X = 'mdi:axis-x-arrow' -ICON_ACCELERATION_Y = 'mdi:axis-y-arrow' -ICON_ACCELERATION_Z = 'mdi:axis-z-arrow' -ICON_ARROW_EXPAND_VERTICAL = 'mdi:arrow-expand-vertical' -ICON_BATTERY = 'mdi:battery' -ICON_BRIEFCASE_DOWNLOAD = 'mdi:briefcase-download' -ICON_BRIGHTNESS_5 = 'mdi:brightness-5' -ICON_BUG = 'mdi:bug' -ICON_CHECK_CIRCLE_OUTLINE = 'mdi:check-circle-outline' -ICON_CHEMICAL_WEAPON = 'mdi:chemical-weapon' -ICON_COUNTER = 'mdi:counter' -ICON_CURRENT_AC = 'mdi:current-ac' -ICON_EMPTY = '' -ICON_FLASH = 'mdi:flash' -ICON_FLASK = 'mdi:flask' -ICON_FLASK_OUTLINE = 'mdi:flask-outline' -ICON_FLOWER = 'mdi:flower' -ICON_GAS_CYLINDER = 'mdi:gas-cylinder' -ICON_GAUGE = 'mdi:gauge' -ICON_GRAIN = 'mdi:grain' -ICON_LIGHTBULB = 'mdi:lightbulb' -ICON_MAGNET = 'mdi:magnet' -ICON_MOLECULE_CO2 = 'mdi:molecule-co2' -ICON_MOTION_SENSOR = 'mdi:motion-sensor' -ICON_NEW_BOX = 'mdi:new-box' -ICON_OMEGA = 'mdi:omega' -ICON_PERCENT = 'mdi:percent' -ICON_POWER = 'mdi:power' -ICON_PULSE = 'mdi:pulse' -ICON_RADIATOR = 'mdi:radiator' -ICON_RESTART = 'mdi:restart' -ICON_ROTATE_RIGHT = 'mdi:rotate-right' -ICON_RULER = 'mdi:ruler' -ICON_SCALE = 'mdi:scale' -ICON_SCALE_BATHROOM = 'mdi:scale-bathroom' -ICON_SCREEN_ROTATION = 'mdi:screen-rotation' -ICON_SIGN_DIRECTION = 'mdi:sign-direction' -ICON_SIGNAL = 'mdi:signal-distance-variant' -ICON_SIGNAL_DISTANCE_VARIANT = 'mdi:signal' -ICON_THERMOMETER = 'mdi:thermometer' -ICON_TIMELAPSE = 'mdi:timelapse' -ICON_TIMER = 'mdi:timer-outline' -ICON_WATER_PERCENT = 'mdi:water-percent' -ICON_WEATHER_SUNSET = 'mdi:weather-sunset' -ICON_WEATHER_SUNSET_DOWN = 'mdi:weather-sunset-down' -ICON_WEATHER_SUNSET_UP = 'mdi:weather-sunset-up' -ICON_WEATHER_WINDY = 'mdi:weather-windy' -ICON_WIFI = 'mdi:wifi' +ICON_ACCELERATION = "mdi:axis-arrow" +ICON_ACCELERATION_X = "mdi:axis-x-arrow" +ICON_ACCELERATION_Y = "mdi:axis-y-arrow" +ICON_ACCELERATION_Z = "mdi:axis-z-arrow" +ICON_ARROW_EXPAND_VERTICAL = "mdi:arrow-expand-vertical" +ICON_BATTERY = "mdi:battery" +ICON_BRIEFCASE_DOWNLOAD = "mdi:briefcase-download" +ICON_BRIGHTNESS_5 = "mdi:brightness-5" +ICON_BUG = "mdi:bug" +ICON_CHECK_CIRCLE_OUTLINE = "mdi:check-circle-outline" +ICON_CHEMICAL_WEAPON = "mdi:chemical-weapon" +ICON_COUNTER = "mdi:counter" +ICON_CURRENT_AC = "mdi:current-ac" +ICON_EMPTY = "" +ICON_FLASH = "mdi:flash" +ICON_FLASK = "mdi:flask" +ICON_FLASK_OUTLINE = "mdi:flask-outline" +ICON_FLOWER = "mdi:flower" +ICON_GAS_CYLINDER = "mdi:gas-cylinder" +ICON_GAUGE = "mdi:gauge" +ICON_GRAIN = "mdi:grain" +ICON_LIGHTBULB = "mdi:lightbulb" +ICON_MAGNET = "mdi:magnet" +ICON_MOLECULE_CO2 = "mdi:molecule-co2" +ICON_MOTION_SENSOR = "mdi:motion-sensor" +ICON_NEW_BOX = "mdi:new-box" +ICON_OMEGA = "mdi:omega" +ICON_PERCENT = "mdi:percent" +ICON_POWER = "mdi:power" +ICON_PULSE = "mdi:pulse" +ICON_RADIATOR = "mdi:radiator" +ICON_RESTART = "mdi:restart" +ICON_ROTATE_RIGHT = "mdi:rotate-right" +ICON_RULER = "mdi:ruler" +ICON_SCALE = "mdi:scale" +ICON_SCALE_BATHROOM = "mdi:scale-bathroom" +ICON_SCREEN_ROTATION = "mdi:screen-rotation" +ICON_SIGN_DIRECTION = "mdi:sign-direction" +ICON_SIGNAL = "mdi:signal-distance-variant" +ICON_SIGNAL_DISTANCE_VARIANT = "mdi:signal" +ICON_THERMOMETER = "mdi:thermometer" +ICON_TIMELAPSE = "mdi:timelapse" +ICON_TIMER = "mdi:timer-outline" +ICON_WATER_PERCENT = "mdi:water-percent" +ICON_WEATHER_SUNSET = "mdi:weather-sunset" +ICON_WEATHER_SUNSET_DOWN = "mdi:weather-sunset-down" +ICON_WEATHER_SUNSET_UP = "mdi:weather-sunset-up" +ICON_WEATHER_WINDY = "mdi:weather-windy" +ICON_WIFI = "mdi:wifi" -UNIT_AMPERE = 'A' -UNIT_CELSIUS = '°C' -UNIT_COUNTS_PER_CUBIC_METER = '#/m³' -UNIT_DECIBEL = 'dB' -UNIT_DECIBEL_MILLIWATT = 'dBm' -UNIT_DEGREE_PER_SECOND = '°/s' -UNIT_DEGREES = '°' -UNIT_EMPTY = '' -UNIT_G = 'G' -UNIT_HECTOPASCAL = 'hPa' -UNIT_HERTZ = 'Hz' -UNIT_KELVIN = 'K' -UNIT_KILOGRAM = 'kg' -UNIT_KILOMETER = 'km' -UNIT_KILOMETER_PER_HOUR = 'km/h' -UNIT_LUX = 'lx' -UNIT_METER = 'm' -UNIT_METER_PER_SECOND_SQUARED = 'm/s²' -UNIT_MICROGRAMS_PER_CUBIC_METER = 'µg/m³' -UNIT_MICROMETER = 'µm' -UNIT_MICROSIEMENS_PER_CENTIMETER = 'µS/cm' -UNIT_MICROTESLA = 'µT' -UNIT_MILLIGRAMS_PER_CUBIC_METER = 'mg/m³' -UNIT_MINUTE = 'min' -UNIT_OHM = 'Ω' -UNIT_PARTS_PER_BILLION = 'ppb' -UNIT_PARTS_PER_MILLION = 'ppm' -UNIT_PERCENT = '%' +UNIT_AMPERE = "A" +UNIT_CELSIUS = "°C" +UNIT_COUNTS_PER_CUBIC_METER = "#/m³" +UNIT_DECIBEL = "dB" +UNIT_DECIBEL_MILLIWATT = "dBm" +UNIT_DEGREE_PER_SECOND = "°/s" +UNIT_DEGREES = "°" +UNIT_EMPTY = "" +UNIT_G = "G" +UNIT_HECTOPASCAL = "hPa" +UNIT_HERTZ = "Hz" +UNIT_KELVIN = "K" +UNIT_KILOGRAM = "kg" +UNIT_KILOMETER = "km" +UNIT_KILOMETER_PER_HOUR = "km/h" +UNIT_LUX = "lx" +UNIT_METER = "m" +UNIT_METER_PER_SECOND_SQUARED = "m/s²" +UNIT_MICROGRAMS_PER_CUBIC_METER = "µg/m³" +UNIT_MICROMETER = "µm" +UNIT_MICROSIEMENS_PER_CENTIMETER = "µS/cm" +UNIT_MICROTESLA = "µT" +UNIT_MILLIGRAMS_PER_CUBIC_METER = "mg/m³" +UNIT_MINUTE = "min" +UNIT_OHM = "Ω" +UNIT_PARTS_PER_BILLION = "ppb" +UNIT_PARTS_PER_MILLION = "ppm" +UNIT_PERCENT = "%" UNIT_PULSES = "pulses" -UNIT_PULSES_PER_MINUTE = 'pulses/min' -UNIT_SECOND = 's' -UNIT_STEPS = 'steps' -UNIT_VOLT = 'V' -UNIT_VOLT_AMPS = 'VA' -UNIT_VOLT_AMPS_REACTIVE = 'VAR' -UNIT_WATT = 'W' -UNIT_WATT_HOURS = 'Wh' +UNIT_PULSES_PER_MINUTE = "pulses/min" +UNIT_SECOND = "s" +UNIT_STEPS = "steps" +UNIT_VOLT = "V" +UNIT_VOLT_AMPS = "VA" +UNIT_VOLT_AMPS_REACTIVE = "VAR" +UNIT_WATT = "W" +UNIT_WATT_HOURS = "Wh" # device classes of binary_sensor component -DEVICE_CLASS_BATTERY_CHARGING = 'battery_charging' -DEVICE_CLASS_COLD = 'cold' -DEVICE_CLASS_CONNECTIVITY = 'connectivity' -DEVICE_CLASS_DOOR = 'door' -DEVICE_CLASS_GARAGE_DOOR = 'garage_door' -DEVICE_CLASS_GAS = 'gas' -DEVICE_CLASS_HEAT = 'heat' -DEVICE_CLASS_LIGHT = 'light' -DEVICE_CLASS_LOCK = 'lock' -DEVICE_CLASS_MOISTURE = 'moisture' -DEVICE_CLASS_MOTION = 'motion' -DEVICE_CLASS_MOVING = 'moving' -DEVICE_CLASS_OCCUPANCY = 'occupancy' -DEVICE_CLASS_OPENING = 'opening' -DEVICE_CLASS_PLUG = 'plug' -DEVICE_CLASS_PRESENCE = 'presence' -DEVICE_CLASS_PROBLEM = 'problem' -DEVICE_CLASS_SAFETY = 'safety' -DEVICE_CLASS_SMOKE = 'smoke' -DEVICE_CLASS_SOUND = 'sound' -DEVICE_CLASS_VIBRATION = 'vibration' -DEVICE_CLASS_WINDOW = 'window' +DEVICE_CLASS_BATTERY_CHARGING = "battery_charging" +DEVICE_CLASS_COLD = "cold" +DEVICE_CLASS_CONNECTIVITY = "connectivity" +DEVICE_CLASS_DOOR = "door" +DEVICE_CLASS_GARAGE_DOOR = "garage_door" +DEVICE_CLASS_GAS = "gas" +DEVICE_CLASS_HEAT = "heat" +DEVICE_CLASS_LIGHT = "light" +DEVICE_CLASS_LOCK = "lock" +DEVICE_CLASS_MOISTURE = "moisture" +DEVICE_CLASS_MOTION = "motion" +DEVICE_CLASS_MOVING = "moving" +DEVICE_CLASS_OCCUPANCY = "occupancy" +DEVICE_CLASS_OPENING = "opening" +DEVICE_CLASS_PLUG = "plug" +DEVICE_CLASS_PRESENCE = "presence" +DEVICE_CLASS_PROBLEM = "problem" +DEVICE_CLASS_SAFETY = "safety" +DEVICE_CLASS_SMOKE = "smoke" +DEVICE_CLASS_SOUND = "sound" +DEVICE_CLASS_VIBRATION = "vibration" +DEVICE_CLASS_WINDOW = "window" # device classes of both binary_sensor and sensor component -DEVICE_CLASS_EMPTY = '' -DEVICE_CLASS_BATTERY = 'battery' -DEVICE_CLASS_POWER = 'power' +DEVICE_CLASS_EMPTY = "" +DEVICE_CLASS_BATTERY = "battery" +DEVICE_CLASS_POWER = "power" # device classes of sensor component -DEVICE_CLASS_CURRENT = 'current' -DEVICE_CLASS_ENERGY = 'energy' -DEVICE_CLASS_HUMIDITY = 'humidity' -DEVICE_CLASS_ILLUMINANCE = 'illuminance' -DEVICE_CLASS_SIGNAL_STRENGTH = 'signal_strength' -DEVICE_CLASS_TEMPERATURE = 'temperature' -DEVICE_CLASS_POWER_FACTOR = 'power_factor' -DEVICE_CLASS_PRESSURE = 'pressure' -DEVICE_CLASS_TIMESTAMP = 'timestamp' -DEVICE_CLASS_VOLTAGE = 'voltage' +DEVICE_CLASS_CURRENT = "current" +DEVICE_CLASS_ENERGY = "energy" +DEVICE_CLASS_HUMIDITY = "humidity" +DEVICE_CLASS_ILLUMINANCE = "illuminance" +DEVICE_CLASS_SIGNAL_STRENGTH = "signal_strength" +DEVICE_CLASS_TEMPERATURE = "temperature" +DEVICE_CLASS_POWER_FACTOR = "power_factor" +DEVICE_CLASS_PRESSURE = "pressure" +DEVICE_CLASS_TIMESTAMP = "timestamp" +DEVICE_CLASS_VOLTAGE = "voltage" diff --git a/esphome/core.py b/esphome/core.py index 2295e4275..cf2a07d35 100644 --- a/esphome/core.py +++ b/esphome/core.py @@ -10,8 +10,14 @@ import re # pylint: disable=unused-import, wrong-import-order from typing import Any, Dict, List, Optional, Set, TYPE_CHECKING # noqa -from esphome.const import CONF_ARDUINO_VERSION, SOURCE_FILE_EXTENSIONS, \ - CONF_COMMENT, CONF_ESPHOME, CONF_USE_ADDRESS, CONF_WIFI +from esphome.const import ( + CONF_ARDUINO_VERSION, + SOURCE_FILE_EXTENSIONS, + CONF_COMMENT, + CONF_ESPHOME, + CONF_USE_ADDRESS, + CONF_WIFI, +) from esphome.helpers import ensure_unique_string, is_hassio from esphome.util import OrderedDict @@ -42,7 +48,7 @@ class IPAddress: self.args = args def __str__(self): - return '.'.join(str(x) for x in self.args) + return ".".join(str(x) for x in self.args) class MACAddress: @@ -52,14 +58,14 @@ class MACAddress: self.parts = parts def __str__(self): - return ':'.join(f'{part:02X}' for part in self.parts) + return ":".join(f"{part:02X}" for part in self.parts) @property def as_hex(self): from esphome.cpp_generator import RawExpression - num = ''.join(f'{part:02X}' for part in self.parts) - return RawExpression(f'0x{num}ULL') + num = "".join(f"{part:02X}" for part in self.parts) + return RawExpression(f"0x{num}ULL") def is_approximately_integer(value): @@ -69,8 +75,15 @@ def is_approximately_integer(value): class TimePeriod: - def __init__(self, microseconds=None, milliseconds=None, seconds=None, - minutes=None, hours=None, days=None): + def __init__( + self, + microseconds=None, + milliseconds=None, + seconds=None, + minutes=None, + hours=None, + days=None, + ): if days is not None: if not is_approximately_integer(days): frac_days, days = math.modf(days) @@ -121,33 +134,33 @@ class TimePeriod: def as_dict(self): out = OrderedDict() if self.microseconds is not None: - out['microseconds'] = self.microseconds + out["microseconds"] = self.microseconds if self.milliseconds is not None: - out['milliseconds'] = self.milliseconds + out["milliseconds"] = self.milliseconds if self.seconds is not None: - out['seconds'] = self.seconds + out["seconds"] = self.seconds if self.minutes is not None: - out['minutes'] = self.minutes + out["minutes"] = self.minutes if self.hours is not None: - out['hours'] = self.hours + out["hours"] = self.hours if self.days is not None: - out['days'] = self.days + out["days"] = self.days return out def __str__(self): if self.microseconds is not None: - return f'{self.total_microseconds}us' + return f"{self.total_microseconds}us" if self.milliseconds is not None: - return f'{self.total_milliseconds}ms' + return f"{self.total_milliseconds}ms" if self.seconds is not None: - return f'{self.total_seconds}s' + return f"{self.total_seconds}s" if self.minutes is not None: - return f'{self.total_minutes}min' + return f"{self.total_minutes}min" if self.hours is not None: - return f'{self.total_hours}h' + return f"{self.total_hours}h" if self.days is not None: - return f'{self.total_days}d' - return '0s' + return f"{self.total_days}d" + return "0s" def __repr__(self): return f"TimePeriod<{self.total_microseconds}>" @@ -223,7 +236,7 @@ class TimePeriodMinutes(TimePeriod): pass -LAMBDA_PROG = re.compile(r'id\(\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\)(\.?)') +LAMBDA_PROG = re.compile(r"id\(\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\)(\.?)") class Lambda: @@ -240,12 +253,13 @@ class Lambda: def comment_remover(self, text): def replacer(match): s = match.group(0) - if s.startswith('/'): + if s.startswith("/"): return " " # note: a space and not an empty string return s + pattern = re.compile( r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', - re.DOTALL | re.MULTILINE + re.DOTALL | re.MULTILINE, ) return re.sub(pattern, replacer, text) @@ -258,7 +272,9 @@ class Lambda: @property def requires_ids(self): if self._requires_ids is None: - self._requires_ids = [ID(self.parts[i]) for i in range(1, len(self.parts), 3)] + self._requires_ids = [ + ID(self.parts[i]) for i in range(1, len(self.parts), 3) + ] return self._requires_ids @property @@ -275,7 +291,7 @@ class Lambda: return self.value def __repr__(self): - return f'Lambda<{self.value}>' + return f"Lambda<{self.value}>" class ID: @@ -286,26 +302,28 @@ class ID: else: self.is_manual = is_manual self.is_declaration = is_declaration - self.type: Optional['MockObjClass'] = type + self.type: Optional["MockObjClass"] = type def resolve(self, registered_ids): from esphome.config_validation import RESERVED_IDS if self.id is None: - base = str(self.type).replace('::', '_').lower() - name = ''.join(c for c in base if c.isalnum() or c == '_') + base = str(self.type).replace("::", "_").lower() + name = "".join(c for c in base if c.isalnum() or c == "_") used = set(registered_ids) | set(RESERVED_IDS) self.id = ensure_unique_string(name, used) return self.id def __str__(self): if self.id is None: - return '' + return "" return self.id def __repr__(self): - return (f'ID<{self.id} declaration={self.is_declaration}, ' - f'type={self.type}, manual={self.is_manual}>') + return ( + f"ID<{self.id} declaration={self.is_declaration}, " + f"type={self.type}, manual={self.is_manual}>" + ) def __eq__(self, other): if isinstance(other, ID): @@ -316,8 +334,12 @@ class ID: return hash(self.id) def copy(self): - return ID(self.id, is_declaration=self.is_declaration, type=self.type, - is_manual=self.is_manual) + return ID( + self.id, + is_declaration=self.is_declaration, + type=self.type, + is_manual=self.is_manual, + ) class DocumentLocation: @@ -328,18 +350,14 @@ class DocumentLocation: @classmethod def from_mark(cls, mark): - return cls( - mark.name, - mark.line, - mark.column - ) + return cls(mark.name, mark.line, mark.column) def __str__(self): - return f'{self.document} {self.line}:{self.column}' + return f"{self.document} {self.line}:{self.column}" @property def as_line_directive(self): - document_path = str(self.document).replace('\\', '\\\\') + document_path = str(self.document).replace("\\", "\\\\") return f'#line {self.line + 1} "{document_path}"' @@ -351,12 +369,11 @@ class DocumentRange: @classmethod def from_marks(cls, start_mark, end_mark): return cls( - DocumentLocation.from_mark(start_mark), - DocumentLocation.from_mark(end_mark) + DocumentLocation.from_mark(start_mark), DocumentLocation.from_mark(end_mark) ) def __str__(self): - return f'[{self.start_mark} - {self.end_mark}]' + return f"[{self.start_mark} - {self.end_mark}]" class Define: @@ -367,14 +384,14 @@ class Define: @property def as_build_flag(self): if self.value is None: - return f'-D{self.name}' - return f'-D{self.name}={self.value}' + return f"-D{self.name}" + return f"-D{self.name}={self.value}" @property def as_macro(self): if self.value is None: - return f'#define {self.name}' - return f'#define {self.name} {self.value}' + return f"#define {self.name}" + return f"#define {self.name} {self.value}" @property def as_tuple(self): @@ -398,7 +415,7 @@ class Library: def as_lib_dep(self): if self.version is None: return self.name - return f'{self.name}@{self.version}' + return f"{self.name}@{self.version}" @property def as_tuple(self): @@ -419,13 +436,13 @@ def coroutine(func): def coroutine_with_priority(priority): def decorator(func): - if getattr(func, '_esphome_coroutine', False): + if getattr(func, "_esphome_coroutine", False): # If func is already a coroutine, do not re-wrap it (performance) return func @functools.wraps(func) def _wrapper_generator(*args, **kwargs): - instance_id = kwargs.pop('__esphome_coroutine_instance__') + instance_id = kwargs.pop("__esphome_coroutine_instance__") if not inspect.isgeneratorfunction(func): # If func is not a generator, return result immediately yield func(*args, **kwargs) @@ -455,8 +472,9 @@ def coroutine_with_priority(priority): @functools.wraps(func) def wrapper(*args, **kwargs): import random - instance_id = random.randint(0, 2**32) - kwargs['__esphome_coroutine_instance__'] = instance_id + + instance_id = random.randint(0, 2 ** 32) + kwargs["__esphome_coroutine_instance__"] = instance_id gen = _wrapper_generator(*args, **kwargs) # pylint: disable=protected-access CORE._add_active_coroutine(instance_id, gen) @@ -466,6 +484,7 @@ def coroutine_with_priority(priority): wrapper._esphome_coroutine = True wrapper.priority = priority return wrapper + return decorator @@ -511,17 +530,17 @@ class EsphomeCore: # Task counter for pending tasks self.task_counter = 0 # The variable cache, for each ID this holds a MockObj of the variable obj - self.variables: Dict[str, 'MockObj'] = {} + self.variables: Dict[str, "MockObj"] = {} # A list of statements that go in the main setup() block - self.main_statements: List['Statement'] = [] + self.main_statements: List["Statement"] = [] # A list of statements to insert in the global block (includes and global variables) - self.global_statements: List['Statement'] = [] + self.global_statements: List["Statement"] = [] # A set of platformio libraries to add to the project self.libraries: List[Library] = [] # A set of build flags to set in the platformio project self.build_flags: Set[str] = set() # A set of defines to set for the compile process in esphome/core/defines.h - self.defines: Set['Define'] = set() + self.defines: Set["Define"] = set() # A dictionary of started coroutines, used to warn when a coroutine was not # awaited. self.active_coroutines: Dict[int, Any] = {} @@ -558,11 +577,11 @@ class EsphomeCore: if self.config is None: raise ValueError("Config has not been loaded yet") - if 'wifi' in self.config: + if "wifi" in self.config: return self.config[CONF_WIFI][CONF_USE_ADDRESS] - if 'ethernet' in self.config: - return self.config['ethernet'][CONF_USE_ADDRESS] + if "ethernet" in self.config: + return self.config["ethernet"][CONF_USE_ADDRESS] return None @@ -608,33 +627,33 @@ class EsphomeCore: return os.path.join(self.build_path, path_) def relative_src_path(self, *path): - return self.relative_build_path('src', *path) + return self.relative_build_path("src", *path) def relative_pioenvs_path(self, *path): if is_hassio(): - return os.path.join('/data', self.name, '.pioenvs', *path) - return self.relative_build_path('.pioenvs', *path) + return os.path.join("/data", self.name, ".pioenvs", *path) + return self.relative_build_path(".pioenvs", *path) def relative_piolibdeps_path(self, *path): if is_hassio(): - return os.path.join('/data', self.name, '.piolibdeps', *path) - return self.relative_build_path('.piolibdeps', *path) + return os.path.join("/data", self.name, ".piolibdeps", *path) + return self.relative_build_path(".piolibdeps", *path) @property def firmware_bin(self): - return self.relative_pioenvs_path(self.name, 'firmware.bin') + return self.relative_pioenvs_path(self.name, "firmware.bin") @property def is_esp8266(self): if self.esp_platform is None: raise ValueError("No platform specified") - return self.esp_platform == 'ESP8266' + return self.esp_platform == "ESP8266" @property def is_esp32(self): if self.esp_platform is None: raise ValueError("No platform specified") - return self.esp_platform == 'ESP32' + return self.esp_platform == "ESP32" def add_job(self, func, *args, **kwargs): coro = coroutine(func) @@ -667,14 +686,17 @@ class EsphomeCore: # Print not-awaited coroutines for obj in self.active_coroutines.values(): - _LOGGER.warning("Coroutine '%s' %s was never awaited with 'yield'.", obj.__name__, obj) + _LOGGER.warning( + "Coroutine '%s' %s was never awaited with 'yield'.", obj.__name__, obj + ) _LOGGER.warning("Please file a bug report with your configuration.") if self.active_coroutines: raise EsphomeError() if self.component_ids: - comps = ', '.join(f"'{x}'" for x in self.component_ids) - _LOGGER.warning("Components %s were never registered. Please create a bug report", - comps) + comps = ", ".join(f"'{x}'" for x in self.component_ids) + _LOGGER.warning( + "Components %s were never registered. Please create a bug report", comps + ) _LOGGER.warning("with your configuration.") raise EsphomeError() self.active_coroutines.clear() @@ -685,8 +707,10 @@ class EsphomeCore: if isinstance(expression, Expression): expression = statement(expression) if not isinstance(expression, Statement): - raise ValueError("Add '{}' must be expression or statement, not {}" - "".format(expression, type(expression))) + raise ValueError( + "Add '{}' must be expression or statement, not {}" + "".format(expression, type(expression)) + ) self.main_statements.append(expression) _LOGGER.debug("Adding: %s", expression) @@ -698,16 +722,20 @@ class EsphomeCore: if isinstance(expression, Expression): expression = statement(expression) if not isinstance(expression, Statement): - raise ValueError("Add '{}' must be expression or statement, not {}" - "".format(expression, type(expression))) + raise ValueError( + "Add '{}' must be expression or statement, not {}" + "".format(expression, type(expression)) + ) self.global_statements.append(expression) _LOGGER.debug("Adding global: %s", expression) return expression def add_library(self, library): if not isinstance(library, Library): - raise ValueError("Library {} must be instance of Library, not {}" - "".format(library, type(library))) + raise ValueError( + "Library {} must be instance of Library, not {}" + "".format(library, type(library)) + ) _LOGGER.debug("Adding library: %s", library) for other in self.libraries[:]: if other.name != library.name: @@ -722,9 +750,11 @@ class EsphomeCore: if other.version == library.version: break - raise ValueError("Version pinning failed! Libraries {} and {} " - "requested with conflicting versions!" - "".format(library, other)) + raise ValueError( + "Version pinning failed! Libraries {} and {} " + "requested with conflicting versions!" + "".format(library, other) + ) else: self.libraries.append(library) return library @@ -740,8 +770,10 @@ class EsphomeCore: elif isinstance(define, Define): pass else: - raise ValueError("Define {} must be string or Define, not {}" - "".format(define, type(define))) + raise ValueError( + "Define {} must be string or Define, not {}" + "".format(define, type(define)) + ) self.defines.add(define) _LOGGER.debug("Adding define: %s", define) return define @@ -784,7 +816,7 @@ class EsphomeCore: text = str(statement(exp)) text = text.rstrip() main_code.append(text) - return '\n'.join(main_code) + '\n\n' + return "\n".join(main_code) + "\n\n" @property def cpp_global_section(self): @@ -795,7 +827,7 @@ class EsphomeCore: text = str(statement(exp)) text = text.rstrip() global_code.append(text) - return '\n'.join(global_code) + '\n' + return "\n".join(global_code) + "\n" class AutoLoad(OrderedDict): @@ -804,13 +836,14 @@ class AutoLoad(OrderedDict): class EnumValue: """Special type used by ESPHome to mark enum values for cv.enum.""" + @property def enum_value(self): - return getattr(self, '_enum_value', None) + return getattr(self, "_enum_value", None) @enum_value.setter def enum_value(self, value): - setattr(self, '_enum_value', value) + setattr(self, "_enum_value", value) CORE = EsphomeCore() diff --git a/esphome/core_config.py b/esphome/core_config.py index f1bb18eef..c0498a8fa 100644 --- a/esphome/core_config.py +++ b/esphome/core_config.py @@ -5,25 +5,45 @@ import re import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation, pins -from esphome.const import CONF_ARDUINO_VERSION, CONF_BOARD, CONF_BOARD_FLASH_MODE, \ - CONF_BUILD_PATH, CONF_COMMENT, CONF_ESPHOME, CONF_INCLUDES, CONF_LIBRARIES, \ - CONF_NAME, CONF_ON_BOOT, CONF_ON_LOOP, CONF_ON_SHUTDOWN, CONF_PLATFORM, \ - CONF_PLATFORMIO_OPTIONS, CONF_PRIORITY, CONF_TRIGGER_ID, \ - CONF_ESP8266_RESTORE_FROM_FLASH, ARDUINO_VERSION_ESP8266, \ - ARDUINO_VERSION_ESP32, ESP_PLATFORMS +from esphome.const import ( + CONF_ARDUINO_VERSION, + CONF_BOARD, + CONF_BOARD_FLASH_MODE, + CONF_BUILD_PATH, + CONF_COMMENT, + CONF_ESPHOME, + CONF_INCLUDES, + CONF_LIBRARIES, + CONF_NAME, + CONF_ON_BOOT, + CONF_ON_LOOP, + CONF_ON_SHUTDOWN, + CONF_PLATFORM, + CONF_PLATFORMIO_OPTIONS, + CONF_PRIORITY, + CONF_TRIGGER_ID, + CONF_ESP8266_RESTORE_FROM_FLASH, + ARDUINO_VERSION_ESP8266, + ARDUINO_VERSION_ESP32, + ESP_PLATFORMS, +) from esphome.core import CORE, coroutine_with_priority from esphome.helpers import copy_file_if_changed, walk_files _LOGGER = logging.getLogger(__name__) -BUILD_FLASH_MODES = ['qio', 'qout', 'dio', 'dout'] -StartupTrigger = cg.esphome_ns.class_('StartupTrigger', cg.Component, automation.Trigger.template()) -ShutdownTrigger = cg.esphome_ns.class_('ShutdownTrigger', cg.Component, - automation.Trigger.template()) -LoopTrigger = cg.esphome_ns.class_('LoopTrigger', cg.Component, - automation.Trigger.template()) +BUILD_FLASH_MODES = ["qio", "qout", "dio", "dout"] +StartupTrigger = cg.esphome_ns.class_( + "StartupTrigger", cg.Component, automation.Trigger.template() +) +ShutdownTrigger = cg.esphome_ns.class_( + "ShutdownTrigger", cg.Component, automation.Trigger.template() +) +LoopTrigger = cg.esphome_ns.class_( + "LoopTrigger", cg.Component, automation.Trigger.template() +) -VERSION_REGEX = re.compile(r'^[0-9]+\.[0-9]+\.[0-9]+(?:[ab]\d+)?$') +VERSION_REGEX = re.compile(r"^[0-9]+\.[0-9]+\.[0-9]+(?:[ab]\d+)?$") def validate_board(value): @@ -35,8 +55,11 @@ def validate_board(value): raise NotImplementedError if value not in board_pins: - raise cv.Invalid("Could not find board '{}'. Valid boards are {}".format( - value, ', '.join(sorted(board_pins.keys())))) + raise cv.Invalid( + "Could not find board '{}'. Valid boards are {}".format( + value, ", ".join(sorted(board_pins.keys())) + ) + ) return value @@ -44,16 +67,16 @@ validate_platform = cv.one_of(*ESP_PLATFORMS, upper=True) PLATFORMIO_ESP8266_LUT = { **ARDUINO_VERSION_ESP8266, - 'RECOMMENDED': ARDUINO_VERSION_ESP8266['2.7.4'], - 'LATEST': 'espressif8266', - 'DEV': ARDUINO_VERSION_ESP8266['dev'], + "RECOMMENDED": ARDUINO_VERSION_ESP8266["2.7.4"], + "LATEST": "espressif8266", + "DEV": ARDUINO_VERSION_ESP8266["dev"], } PLATFORMIO_ESP32_LUT = { **ARDUINO_VERSION_ESP32, - 'RECOMMENDED': ARDUINO_VERSION_ESP32['1.0.4'], - 'LATEST': 'espressif32', - 'DEV': ARDUINO_VERSION_ESP32['dev'], + "RECOMMENDED": ARDUINO_VERSION_ESP32["1.0.4"], + "LATEST": "espressif32", + "DEV": ARDUINO_VERSION_ESP32["dev"], } @@ -61,18 +84,28 @@ def validate_arduino_version(value): value = cv.string_strict(value) value_ = value.upper() if CORE.is_esp8266: - if VERSION_REGEX.match(value) is not None and value_ not in PLATFORMIO_ESP8266_LUT: - raise cv.Invalid("Unfortunately the arduino framework version '{}' is unsupported " - "at this time. You can override this by manually using " - "espressif8266@".format(value)) + if ( + VERSION_REGEX.match(value) is not None + and value_ not in PLATFORMIO_ESP8266_LUT + ): + raise cv.Invalid( + "Unfortunately the arduino framework version '{}' is unsupported " + "at this time. You can override this by manually using " + "espressif8266@".format(value) + ) if value_ in PLATFORMIO_ESP8266_LUT: return PLATFORMIO_ESP8266_LUT[value_] return value if CORE.is_esp32: - if VERSION_REGEX.match(value) is not None and value_ not in PLATFORMIO_ESP32_LUT: - raise cv.Invalid("Unfortunately the arduino framework version '{}' is unsupported " - "at this time. You can override this by manually using " - "espressif32@".format(value)) + if ( + VERSION_REGEX.match(value) is not None + and value_ not in PLATFORMIO_ESP32_LUT + ): + raise cv.Invalid( + "Unfortunately the arduino framework version '{}' is unsupported " + "at this time. You can override this by manually using " + "espressif32@".format(value) + ) if value_ in PLATFORMIO_ESP32_LUT: return PLATFORMIO_ESP32_LUT[value_] return value @@ -83,7 +116,7 @@ def default_build_path(): return CORE.name -VALID_INCLUDE_EXTS = {'.h', '.hpp', '.tcc', '.ino', '.cpp', '.c'} +VALID_INCLUDE_EXTS = {".h", ".hpp", ".tcc", ".ino", ".cpp", ".c"} def valid_include(value): @@ -94,62 +127,85 @@ def valid_include(value): value = cv.file_(value) _, ext = os.path.splitext(value) if ext not in VALID_INCLUDE_EXTS: - raise cv.Invalid("Include has invalid file extension {} - valid extensions are {}" - "".format(ext, ', '.join(VALID_INCLUDE_EXTS))) + raise cv.Invalid( + "Include has invalid file extension {} - valid extensions are {}" + "".format(ext, ", ".join(VALID_INCLUDE_EXTS)) + ) return value -CONFIG_SCHEMA = cv.Schema({ - cv.Required(CONF_NAME): cv.valid_name, - cv.Required(CONF_PLATFORM): cv.one_of('ESP8266', 'ESP32', upper=True), - cv.Required(CONF_BOARD): validate_board, - cv.Optional(CONF_COMMENT): cv.string, - cv.Optional(CONF_ARDUINO_VERSION, default='recommended'): validate_arduino_version, - cv.Optional(CONF_BUILD_PATH, default=default_build_path): cv.string, - cv.Optional(CONF_PLATFORMIO_OPTIONS, default={}): cv.Schema({ - cv.string_strict: cv.Any([cv.string], cv.string), - }), - cv.SplitDefault(CONF_ESP8266_RESTORE_FROM_FLASH, esp8266=False): cv.All(cv.only_on_esp8266, - cv.boolean), +CONFIG_SCHEMA = cv.Schema( + { + cv.Required(CONF_NAME): cv.valid_name, + cv.Required(CONF_PLATFORM): cv.one_of("ESP8266", "ESP32", upper=True), + cv.Required(CONF_BOARD): validate_board, + cv.Optional(CONF_COMMENT): cv.string, + cv.Optional( + CONF_ARDUINO_VERSION, default="recommended" + ): validate_arduino_version, + cv.Optional(CONF_BUILD_PATH, default=default_build_path): cv.string, + cv.Optional(CONF_PLATFORMIO_OPTIONS, default={}): cv.Schema( + { + cv.string_strict: cv.Any([cv.string], cv.string), + } + ), + cv.SplitDefault(CONF_ESP8266_RESTORE_FROM_FLASH, esp8266=False): cv.All( + cv.only_on_esp8266, cv.boolean + ), + cv.SplitDefault(CONF_BOARD_FLASH_MODE, esp8266="dout"): cv.one_of( + *BUILD_FLASH_MODES, lower=True + ), + cv.Optional(CONF_ON_BOOT): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StartupTrigger), + cv.Optional(CONF_PRIORITY, default=600.0): cv.float_, + } + ), + cv.Optional(CONF_ON_SHUTDOWN): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ShutdownTrigger), + } + ), + cv.Optional(CONF_ON_LOOP): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LoopTrigger), + } + ), + cv.Optional(CONF_INCLUDES, default=[]): cv.ensure_list(valid_include), + cv.Optional(CONF_LIBRARIES, default=[]): cv.ensure_list(cv.string_strict), + cv.Optional("esphome_core_version"): cv.invalid( + "The esphome_core_version option has been " + "removed in 1.13 - the esphome core source " + "files are now bundled with ESPHome." + ), + } +) - cv.SplitDefault(CONF_BOARD_FLASH_MODE, esp8266='dout'): cv.one_of(*BUILD_FLASH_MODES, - lower=True), - cv.Optional(CONF_ON_BOOT): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StartupTrigger), - cv.Optional(CONF_PRIORITY, default=600.0): cv.float_, - }), - cv.Optional(CONF_ON_SHUTDOWN): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ShutdownTrigger), - }), - cv.Optional(CONF_ON_LOOP): automation.validate_automation({ - cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(LoopTrigger), - }), - cv.Optional(CONF_INCLUDES, default=[]): cv.ensure_list(valid_include), - cv.Optional(CONF_LIBRARIES, default=[]): cv.ensure_list(cv.string_strict), +PRELOAD_CONFIG_SCHEMA = cv.Schema( + { + cv.Required(CONF_NAME): cv.valid_name, + cv.Required(CONF_PLATFORM): validate_platform, + }, + extra=cv.ALLOW_EXTRA, +) - cv.Optional('esphome_core_version'): cv.invalid("The esphome_core_version option has been " - "removed in 1.13 - the esphome core source " - "files are now bundled with ESPHome.") -}) - -PRELOAD_CONFIG_SCHEMA = cv.Schema({ - cv.Required(CONF_NAME): cv.valid_name, - cv.Required(CONF_PLATFORM): validate_platform, -}, extra=cv.ALLOW_EXTRA) - -PRELOAD_CONFIG_SCHEMA2 = PRELOAD_CONFIG_SCHEMA.extend({ - cv.Required(CONF_BOARD): validate_board, - cv.Optional(CONF_BUILD_PATH, default=default_build_path): cv.string, -}) +PRELOAD_CONFIG_SCHEMA2 = PRELOAD_CONFIG_SCHEMA.extend( + { + cv.Required(CONF_BOARD): validate_board, + cv.Optional(CONF_BUILD_PATH, default=default_build_path): cv.string, + } +) def preload_core_config(config): - core_key = 'esphome' - if 'esphomeyaml' in config: - _LOGGER.warning("The esphomeyaml section has been renamed to esphome in 1.11.0. " - "Please replace 'esphomeyaml:' in your configuration with 'esphome:'.") - config[CONF_ESPHOME] = config.pop('esphomeyaml') - core_key = 'esphomeyaml' + core_key = "esphome" + if "esphomeyaml" in config: + _LOGGER.warning( + "The esphomeyaml section has been renamed to esphome in 1.11.0. " + "Please replace 'esphomeyaml:' in your configuration with 'esphome:'." + ) + config[CONF_ESPHOME] = config.pop("esphomeyaml") + core_key = "esphomeyaml" if CONF_ESPHOME not in config: raise cv.RequiredFieldInvalid("required key not provided", CONF_ESPHOME) with cv.prepend_path(core_key): @@ -168,7 +224,7 @@ def include_file(path, basename): copy_file_if_changed(path, dst) _, ext = os.path.splitext(path) - if ext in ['.h', '.hpp', '.tcc']: + if ext in [".h", ".hpp", ".tcc"]: # Header, add include statement cg.add_global(cg.RawStatement(f'#include "{basename}"')) @@ -192,7 +248,9 @@ def add_includes(includes): @coroutine_with_priority(-1000.0) def _esp8266_add_lwip_type(): # If any component has already set this, do not change it - if any(flag.startswith('-DPIO_FRAMEWORK_ARDUINO_LWIP2_') for flag in CORE.build_flags): + if any( + flag.startswith("-DPIO_FRAMEWORK_ARDUINO_LWIP2_") for flag in CORE.build_flags + ): return # Default for platformio is LWIP2_LOW_MEMORY with: @@ -206,7 +264,7 @@ def _esp8266_add_lwip_type(): # - MSS=1460 # - LWIP_FEATURES disabled (because we don't need them) # Other projects like Tasmota & ESPEasy also use this - cg.add_build_flag('-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH') + cg.add_build_flag("-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH") @coroutine_with_priority(30.0) @@ -229,8 +287,10 @@ def _add_automations(config): @coroutine_with_priority(100.0) def to_code(config): - cg.add_global(cg.global_ns.namespace('esphome').using) - cg.add(cg.App.pre_setup(config[CONF_NAME], cg.RawExpression('__DATE__ ", " __TIME__'))) + cg.add_global(cg.global_ns.namespace("esphome").using) + cg.add( + cg.App.pre_setup(config[CONF_NAME], cg.RawExpression('__DATE__ ", " __TIME__')) + ) CORE.add_job(_add_automations, config) @@ -238,27 +298,27 @@ def to_code(config): if CORE.is_esp8266: CORE.add_job(_esp8266_add_lwip_type) - cg.add_build_flag('-fno-exceptions') + cg.add_build_flag("-fno-exceptions") # Libraries if CORE.is_esp32: - cg.add_library('ESPmDNS', None) + cg.add_library("ESPmDNS", None) elif CORE.is_esp8266: - cg.add_library('ESP8266WiFi', None) - cg.add_library('ESP8266mDNS', None) + cg.add_library("ESP8266WiFi", None) + cg.add_library("ESP8266mDNS", None) for lib in config[CONF_LIBRARIES]: - if '@' in lib: - name, vers = lib.split('@', 1) + if "@" in lib: + name, vers = lib.split("@", 1) cg.add_library(name, vers) else: cg.add_library(lib, None) - cg.add_build_flag('-Wno-unused-variable') - cg.add_build_flag('-Wno-unused-but-set-variable') - cg.add_build_flag('-Wno-sign-compare') + cg.add_build_flag("-Wno-unused-variable") + cg.add_build_flag("-Wno-unused-but-set-variable") + cg.add_build_flag("-Wno-sign-compare") if config.get(CONF_ESP8266_RESTORE_FROM_FLASH, False): - cg.add_define('USE_ESP8266_PREFERENCES_FLASH') + cg.add_define("USE_ESP8266_PREFERENCES_FLASH") if config[CONF_INCLUDES]: CORE.add_job(add_includes, config[CONF_INCLUDES]) diff --git a/esphome/cpp_generator.py b/esphome/cpp_generator.py index cfa178c4f..754ce229a 100644 --- a/esphome/cpp_generator.py +++ b/esphome/cpp_generator.py @@ -8,9 +8,20 @@ from esphome.yaml_util import ESPHomeDataBase from typing import Any, Generator, List, Optional, Tuple, Type, Union, Sequence from esphome.core import ( # noqa - CORE, HexInt, ID, Lambda, TimePeriod, TimePeriodMicroseconds, - TimePeriodMilliseconds, TimePeriodMinutes, TimePeriodSeconds, coroutine, Library, Define, - EnumValue) + CORE, + HexInt, + ID, + Lambda, + TimePeriod, + TimePeriodMicroseconds, + TimePeriodMilliseconds, + TimePeriodMinutes, + TimePeriodSeconds, + coroutine, + Library, + Define, + EnumValue, +) from esphome.helpers import cpp_string_escape, indent_all_but_first_and_last from esphome.util import OrderedDict @@ -25,12 +36,23 @@ class Expression(abc.ABC): """ -SafeExpType = Union[Expression, bool, str, str, int, float, TimePeriod, - Type[bool], Type[int], Type[float], Sequence[Any]] +SafeExpType = Union[ + Expression, + bool, + str, + str, + int, + float, + TimePeriod, + Type[bool], + Type[int], + Type[float], + Sequence[Any], +] class RawExpression(Expression): - __slots__ = ("text", ) + __slots__ = ("text",) def __init__(self, text: str): self.text = text @@ -68,7 +90,7 @@ class VariableDeclarationExpression(Expression): class ExpressionList(Expression): - __slots__ = ("args", ) + __slots__ = ("args",) def __init__(self, *args: Optional[SafeExpType]): # Remove every None on end @@ -86,13 +108,13 @@ class ExpressionList(Expression): class TemplateArguments(Expression): - __slots__ = ("args", ) + __slots__ = ("args",) def __init__(self, *args: SafeExpType): self.args = ExpressionList(*args) def __str__(self): - return f'<{self.args}>' + return f"<{self.args}>" def __iter__(self): return iter(self.args) @@ -112,8 +134,8 @@ class CallExpression(Expression): def __str__(self): if self.template_args is not None: - return f'{self.base}{self.template_args}({self.args})' - return f'{self.base}({self.args})' + return f"{self.base}{self.template_args}({self.args})" + return f"{self.base}({self.args})" class StructInitializer(Expression): @@ -132,10 +154,10 @@ class StructInitializer(Expression): self.args[key] = exp def __str__(self): - cpp = f'{self.base}{{\n' + cpp = f"{self.base}{{\n" for key, value in self.args.items(): - cpp += f' .{key} = {value},\n' - cpp += '}' + cpp += f" .{key} = {value},\n" + cpp += "}" return cpp @@ -153,14 +175,14 @@ class ArrayInitializer(Expression): def __str__(self): if not self.args: - return '{}' + return "{}" if self.multiline: - cpp = '{\n' + cpp = "{\n" for arg in self.args: - cpp += f' {arg},\n' - cpp += '}' + cpp += f" {arg},\n" + cpp += "}" else: - cpp = '{' + ', '.join(str(arg) for arg in self.args) + '}' + cpp = "{" + ", ".join(str(arg) for arg in self.args) + "}" return cpp @@ -176,9 +198,11 @@ class ParameterExpression(Expression): class ParameterListExpression(Expression): - __slots__ = ("parameters", ) + __slots__ = ("parameters",) - def __init__(self, *parameters: Union[ParameterExpression, Tuple[SafeExpType, str]]): + def __init__( + self, *parameters: Union[ParameterExpression, Tuple[SafeExpType, str]] + ): self.parameters = [] for parameter in parameters: if not isinstance(parameter, ParameterExpression): @@ -192,7 +216,9 @@ class ParameterListExpression(Expression): class LambdaExpression(Expression): __slots__ = ("parts", "parameters", "capture", "return_type", "source") - def __init__(self, parts, parameters, capture: str = '=', return_type=None, source=None): + def __init__( + self, parts, parameters, capture: str = "=", return_type=None, source=None + ): self.parts = parts if not isinstance(parameters, ParameterListExpression): parameters = ParameterListExpression(*parameters) @@ -202,18 +228,18 @@ class LambdaExpression(Expression): self.return_type = safe_exp(return_type) if return_type is not None else None def __str__(self): - cpp = f'[{self.capture}]({self.parameters})' + cpp = f"[{self.capture}]({self.parameters})" if self.return_type is not None: - cpp += f' -> {self.return_type}' - cpp += ' {\n' + cpp += f" -> {self.return_type}" + cpp += " {\n" if self.source is not None: - cpp += f'{self.source.as_line_directive}\n' - cpp += f'{self.content}\n}}' + cpp += f"{self.source.as_line_directive}\n" + cpp += f"{self.content}\n}}" return indent_all_but_first_and_last(cpp) @property def content(self): - return ''.join(str(part) for part in self.parts) + return "".join(str(part) for part in self.parts) # pylint: disable=abstract-method @@ -222,7 +248,7 @@ class Literal(Expression, metaclass=abc.ABCMeta): class StringLiteral(Literal): - __slots__ = ("string", ) + __slots__ = ("string",) def __init__(self, string: str): super().__init__() @@ -233,7 +259,7 @@ class StringLiteral(Literal): class IntLiteral(Literal): - __slots__ = ("i", ) + __slots__ = ("i",) def __init__(self, i: int): super().__init__() @@ -241,16 +267,16 @@ class IntLiteral(Literal): def __str__(self): if self.i > 4294967295: - return f'{self.i}ULL' + return f"{self.i}ULL" if self.i > 2147483647: - return f'{self.i}UL' + return f"{self.i}UL" if self.i < -2147483648: - return f'{self.i}LL' + return f"{self.i}LL" return str(self.i) class BoolLiteral(Literal): - __slots__ = ("binary", ) + __slots__ = ("binary",) def __init__(self, binary: bool): super().__init__() @@ -261,7 +287,7 @@ class BoolLiteral(Literal): class HexIntLiteral(Literal): - __slots__ = ("i", ) + __slots__ = ("i",) def __init__(self, i: int): super().__init__() @@ -272,7 +298,7 @@ class HexIntLiteral(Literal): class FloatLiteral(Literal): - __slots__ = ("f", ) + __slots__ = ("f",) def __init__(self, value: float): super().__init__() @@ -321,11 +347,15 @@ def safe_exp(obj: SafeExpType) -> Expression: if obj is float: return float_ if isinstance(obj, ID): - raise ValueError("Object {} is an ID. Did you forget to register the variable?" - "".format(obj)) + raise ValueError( + "Object {} is an ID. Did you forget to register the variable?" + "".format(obj) + ) if inspect.isgenerator(obj): - raise ValueError("Object {} is a coroutine. Did you forget to await the expression with " - "'yield'?".format(obj)) + raise ValueError( + "Object {} is a coroutine. Did you forget to await the expression with " + "'yield'?".format(obj) + ) raise ValueError("Object is not an expression", obj) @@ -340,7 +370,7 @@ class Statement(abc.ABC): class RawStatement(Statement): - __slots__ = ("text", ) + __slots__ = ("text",) def __init__(self, text: str): self.text = text @@ -350,7 +380,7 @@ class RawStatement(Statement): class ExpressionStatement(Statement): - __slots__ = ("expression", ) + __slots__ = ("expression",) def __init__(self, expression): self.expression = safe_exp(expression) @@ -360,22 +390,22 @@ class ExpressionStatement(Statement): class LineComment(Statement): - __slots__ = ("value", ) + __slots__ = ("value",) def __init__(self, value: str): self.value = value def __str__(self): - parts = re.sub(r'\\\s*\n', r'\n', self.value, re.MULTILINE).split('\n') - parts = [f'// {x}' for x in parts] - return '\n'.join(parts) + parts = re.sub(r"\\\s*\n", r"\n", self.value, re.MULTILINE).split("\n") + parts = [f"// {x}" for x in parts] + return "\n".join(parts) class ProgmemAssignmentExpression(AssignmentExpression): __slots__ = () def __init__(self, type_, name, rhs, obj): - super().__init__(type_, '', name, rhs, obj) + super().__init__(type_, "", name, rhs, obj) def __str__(self): return f"static const {self.type} {self.name}[] PROGMEM = {self.rhs}" @@ -383,7 +413,7 @@ class ProgmemAssignmentExpression(AssignmentExpression): def progmem_array(id_, rhs) -> "MockObj": rhs = safe_exp(rhs) - obj = MockObj(id_, '.') + obj = MockObj(id_, ".") assignment = ProgmemAssignmentExpression(id_.type, id_, rhs, obj) CORE.add(assignment) CORE.register_variable(id_, obj) @@ -391,15 +421,14 @@ def progmem_array(id_, rhs) -> "MockObj": def statement(expression: Union[Expression, Statement]) -> Statement: - """Convert expression into a statement unless is already a statement. - """ + """Convert expression into a statement unless is already a statement.""" if isinstance(expression, Statement): return expression return ExpressionStatement(expression) def variable(id_: ID, rhs: SafeExpType, type_: "MockObj" = None) -> "MockObj": - """Declare a new variable (not pointer type) in the code generation. + """Declare a new variable, not pointer type, in the code generation. :param id_: The ID used to declare the variable. :param rhs: The expression to place on the right hand side of the assignment. @@ -410,10 +439,10 @@ def variable(id_: ID, rhs: SafeExpType, type_: "MockObj" = None) -> "MockObj": """ assert isinstance(id_, ID) rhs = safe_exp(rhs) - obj = MockObj(id_, '.') + obj = MockObj(id_, ".") if type_ is not None: id_.type = type_ - assignment = AssignmentExpression(id_.type, '', id_, rhs, obj) + assignment = AssignmentExpression(id_.type, "", id_, rhs, obj) CORE.add(assignment) CORE.register_variable(id_, obj) return obj @@ -430,10 +459,10 @@ def Pvariable(id_: ID, rhs: SafeExpType, type_: "MockObj" = None) -> "MockObj": :returns The new variable as a MockObj. """ rhs = safe_exp(rhs) - obj = MockObj(id_, '->') + obj = MockObj(id_, "->") if type_ is not None: id_.type = type_ - decl = VariableDeclarationExpression(id_.type, '*', id_) + decl = VariableDeclarationExpression(id_.type, "*", id_) CORE.add_global(decl) assignment = AssignmentExpression(None, None, id_, rhs, obj) CORE.add(assignment) @@ -529,8 +558,10 @@ def get_variable_with_full_id(id_: ID) -> Generator[Tuple[ID, "MockObj"], None, @coroutine def process_lambda( - value: Lambda, parameters: List[Tuple[SafeExpType, str]], - capture: str = '=', return_type: SafeExpType = None + value: Lambda, + parameters: List[Tuple[SafeExpType, str]], + capture: str = "=", + return_type: SafeExpType = None, ) -> Generator[LambdaExpression, None, None]: """Process the given lambda value into a LambdaExpression. @@ -551,16 +582,19 @@ def process_lambda( parts = value.parts[:] for i, id in enumerate(value.requires_ids): full_id, var = yield CORE.get_variable_with_full_id(id) - if full_id is not None and isinstance(full_id.type, MockObjClass) and \ - full_id.type.inherits_from(GlobalsComponent): + if ( + full_id is not None + and isinstance(full_id.type, MockObjClass) + and full_id.type.inherits_from(GlobalsComponent) + ): parts[i * 3 + 1] = var.value() continue - if parts[i * 3 + 2] == '.': + if parts[i * 3 + 2] == ".": parts[i * 3 + 1] = var._ else: parts[i * 3 + 1] = var - parts[i * 3 + 2] = '' + parts[i * 3 + 2] = "" if isinstance(value, ESPHomeDataBase) and value.esp_range is not None: location = value.esp_range.start_mark @@ -576,10 +610,12 @@ def is_template(value): @coroutine -def templatable(value: Any, - args: List[Tuple[SafeExpType, str]], - output_type: Optional[SafeExpType], - to_exp: Any = None): +def templatable( + value: Any, + args: List[Tuple[SafeExpType, str]], + output_type: Optional[SafeExpType], + to_exp: Any = None, +): """Generate code for a templatable config option. If `value` is a templated value, the lambda expression is returned. @@ -608,20 +644,21 @@ class MockObj(Expression): Mostly consists of magic methods that allow ESPHome's codegen syntax. """ + __slots__ = ("base", "op") - def __init__(self, base, op='.'): + def __init__(self, base, op="."): self.base = base self.op = op def __getattr__(self, attr: str) -> "MockObj": - next_op = '.' - if attr.startswith('P') and self.op not in ['::', '']: + next_op = "." + if attr.startswith("P") and self.op not in ["::", ""]: attr = attr[1:] - next_op = '->' - if attr.startswith('_'): + next_op = "->" + if attr.startswith("_"): attr = attr[1:] - return MockObj(f'{self.base}{self.op}{attr}', next_op) + return MockObj(f"{self.base}{self.op}{attr}", next_op) def __call__(self, *args): # type: (SafeExpType) -> MockObj call = CallExpression(self.base, *args) @@ -631,29 +668,29 @@ class MockObj(Expression): return str(self.base) def __repr__(self): - return 'MockObj<{}>'.format(str(self.base)) + return "MockObj<{}>".format(str(self.base)) @property def _(self) -> "MockObj": - return MockObj(f'{self.base}{self.op}') + return MockObj(f"{self.base}{self.op}") @property def new(self) -> "MockObj": - return MockObj(f'new {self.base}', '->') + return MockObj(f"new {self.base}", "->") def template(self, *args: SafeExpType) -> "MockObj": if len(args) != 1 or not isinstance(args[0], TemplateArguments): args = TemplateArguments(*args) else: args = args[0] - return MockObj(f'{self.base}{args}') + return MockObj(f"{self.base}{args}") def namespace(self, name: str) -> "MockObj": - return MockObj(f'{self._}{name}', '::') + return MockObj(f"{self._}{name}", "::") def class_(self, name: str, *parents: "MockObjClass") -> "MockObjClass": - op = '' if self.op == '' else '::' - return MockObjClass(f'{self.base}{op}{name}', '.', parents=parents) + op = "" if self.op == "" else "::" + return MockObjClass(f"{self.base}{op}{name}", ".", parents=parents) def struct(self, name: str) -> "MockObjClass": return self.class_(name) @@ -662,50 +699,50 @@ class MockObj(Expression): return MockObjEnum(enum=name, is_class=is_class, base=self.base, op=self.op) def operator(self, name: str) -> "MockObj": - if name == 'ref': - return MockObj(f'{self.base} &', '') - if name == 'ptr': - return MockObj(f'{self.base} *', '') + if name == "ref": + return MockObj(f"{self.base} &", "") + if name == "ptr": + return MockObj(f"{self.base} *", "") if name == "const": - return MockObj(f'const {self.base}', '') + return MockObj(f"const {self.base}", "") raise ValueError("Expected one of ref, ptr, const.") @property def using(self) -> "MockObj": - assert self.op == '::' - return MockObj(f'using namespace {self.base}') + assert self.op == "::" + return MockObj(f"using namespace {self.base}") def __getitem__(self, item: Union[str, Expression]) -> "MockObj": - next_op = '.' - if isinstance(item, str) and item.startswith('P'): + next_op = "." + if isinstance(item, str) and item.startswith("P"): item = item[1:] - next_op = '->' - return MockObj(f'{self.base}[{item}]', next_op) + next_op = "->" + return MockObj(f"{self.base}[{item}]", next_op) class MockObjEnum(MockObj): def __init__(self, *args, **kwargs): - self._enum = kwargs.pop('enum') - self._is_class = kwargs.pop('is_class') - base = kwargs.pop('base') + self._enum = kwargs.pop("enum") + self._is_class = kwargs.pop("is_class") + base = kwargs.pop("base") if self._is_class: - base = base + '::' + self._enum - kwargs['op'] = '::' - kwargs['base'] = base + base = base + "::" + self._enum + kwargs["op"] = "::" + kwargs["base"] = base MockObj.__init__(self, *args, **kwargs) def __str__(self): if self._is_class: return super().__str__() - return f'{self.base}{self.op}{self._enum}' + return f"{self.base}{self.op}{self._enum}" def __repr__(self): - return f'MockObj<{str(self.base)}>' + return f"MockObj<{str(self.base)}>" class MockObjClass(MockObj): def __init__(self, *args, **kwargs): - parens = kwargs.pop('parents') + parens = kwargs.pop("parents") MockObj.__init__(self, *args, **kwargs) self._parents = [] for paren in parens: @@ -730,7 +767,7 @@ class MockObjClass(MockObj): args = args[0] new_parents = self._parents[:] new_parents.append(self) - return MockObjClass(f'{self.base}{args}', parents=new_parents) + return MockObjClass(f"{self.base}{args}", parents=new_parents) def __repr__(self): - return f'MockObjClass<{str(self.base)}, parents={self._parents}>' + return f"MockObjClass<{str(self.base)}, parents={self._parents}>" diff --git a/esphome/cpp_helpers.py b/esphome/cpp_helpers.py index f01981acc..e83f989d7 100644 --- a/esphome/cpp_helpers.py +++ b/esphome/cpp_helpers.py @@ -1,5 +1,12 @@ -from esphome.const import CONF_INVERTED, CONF_MODE, CONF_NUMBER, CONF_SETUP_PRIORITY, \ - CONF_UPDATE_INTERVAL, CONF_TYPE_ID +from esphome.const import ( + CONF_INVERTED, + CONF_MODE, + CONF_NUMBER, + CONF_SETUP_PRIORITY, + CONF_UPDATE_INTERVAL, + CONF_TYPE_ID, +) + # pylint: disable=unused-import from esphome.core import coroutine, ID, CORE, ConfigType from esphome.cpp_generator import RawExpression, add, get_variable @@ -16,6 +23,7 @@ def gpio_pin_expression(conf): if conf is None: return from esphome import pins + for key, (func, _) in pins.PIN_SCHEMA_REGISTRY.items(): if key in conf: yield coroutine(func)(conf) @@ -38,9 +46,11 @@ def register_component(var, config): """ id_ = str(var.base) if id_ not in CORE.component_ids: - raise ValueError("Component ID {} was not declared to inherit from Component, " - "or was registered twice. Please create a bug report with your " - "configuration.".format(id_)) + raise ValueError( + "Component ID {} was not declared to inherit from Component, " + "or was registered twice. Please create a bug report with your " + "configuration.".format(id_) + ) CORE.component_ids.remove(id_) if CONF_SETUP_PRIORITY in config: add(var.set_setup_priority(config[CONF_SETUP_PRIORITY])) diff --git a/esphome/cpp_types.py b/esphome/cpp_types.py index 4a9dce332..3036249a0 100644 --- a/esphome/cpp_types.py +++ b/esphome/cpp_types.py @@ -1,33 +1,33 @@ from esphome.cpp_generator import MockObj -global_ns = MockObj('', '') -void = global_ns.namespace('void') -nullptr = global_ns.namespace('nullptr') -float_ = global_ns.namespace('float') -double = global_ns.namespace('double') -bool_ = global_ns.namespace('bool') -int_ = global_ns.namespace('int') -std_ns = global_ns.namespace('std') -std_string = std_ns.class_('string') -std_vector = std_ns.class_('vector') -uint8 = global_ns.namespace('uint8_t') -uint16 = global_ns.namespace('uint16_t') -uint32 = global_ns.namespace('uint32_t') -int32 = global_ns.namespace('int32_t') -const_char_ptr = global_ns.namespace('const char *') -NAN = global_ns.namespace('NAN') +global_ns = MockObj("", "") +void = global_ns.namespace("void") +nullptr = global_ns.namespace("nullptr") +float_ = global_ns.namespace("float") +double = global_ns.namespace("double") +bool_ = global_ns.namespace("bool") +int_ = global_ns.namespace("int") +std_ns = global_ns.namespace("std") +std_string = std_ns.class_("string") +std_vector = std_ns.class_("vector") +uint8 = global_ns.namespace("uint8_t") +uint16 = global_ns.namespace("uint16_t") +uint32 = global_ns.namespace("uint32_t") +int32 = global_ns.namespace("int32_t") +const_char_ptr = global_ns.namespace("const char *") +NAN = global_ns.namespace("NAN") esphome_ns = global_ns # using namespace esphome; App = esphome_ns.App -Nameable = esphome_ns.class_('Nameable') -Component = esphome_ns.class_('Component') -ComponentPtr = Component.operator('ptr') -PollingComponent = esphome_ns.class_('PollingComponent', Component) -Application = esphome_ns.class_('Application') -optional = esphome_ns.class_('optional') -arduino_json_ns = global_ns.namespace('ArduinoJson') -JsonObject = arduino_json_ns.class_('JsonObject') -JsonObjectRef = JsonObject.operator('ref') -JsonObjectConstRef = JsonObjectRef.operator('const') -Controller = esphome_ns.class_('Controller') +Nameable = esphome_ns.class_("Nameable") +Component = esphome_ns.class_("Component") +ComponentPtr = Component.operator("ptr") +PollingComponent = esphome_ns.class_("PollingComponent", Component) +Application = esphome_ns.class_("Application") +optional = esphome_ns.class_("optional") +arduino_json_ns = global_ns.namespace("ArduinoJson") +JsonObject = arduino_json_ns.class_("JsonObject") +JsonObjectRef = JsonObject.operator("ref") +JsonObjectConstRef = JsonObjectRef.operator("const") +Controller = esphome_ns.class_("Controller") -GPIOPin = esphome_ns.class_('GPIOPin') +GPIOPin = esphome_ns.class_("GPIOPin") diff --git a/esphome/dashboard/dashboard.py b/esphome/dashboard/dashboard.py index c53c68b3a..1575d9f9b 100644 --- a/esphome/dashboard/dashboard.py +++ b/esphome/dashboard/dashboard.py @@ -27,8 +27,13 @@ import tornado.websocket from esphome import const, util from esphome.helpers import mkdir_p, get_bool_env, run_system_command -from esphome.storage_json import EsphomeStorageJSON, StorageJSON, \ - esphome_storage_path, ext_storage_path, trash_storage_path +from esphome.storage_json import ( + EsphomeStorageJSON, + StorageJSON, + esphome_storage_path, + ext_storage_path, + trash_storage_path, +) from esphome.util import shlex_quote, get_serial_ports from .util import password_hash @@ -42,18 +47,18 @@ _LOGGER = logging.getLogger(__name__) class DashboardSettings: def __init__(self): - self.config_dir = '' - self.password_hash = '' - self.username = '' + self.config_dir = "" + self.password_hash = "" + self.username = "" self.using_password = False self.on_hassio = False self.cookie_secret = None def parse_args(self, args): self.on_hassio = args.hassio - password = args.password or os.getenv('PASSWORD', '') + password = args.password or os.getenv("PASSWORD", "") if not self.on_hassio: - self.username = args.username or os.getenv('USERNAME', '') + self.username = args.username or os.getenv("USERNAME", "") self.using_password = bool(password) if self.using_password: self.password_hash = password_hash(password) @@ -61,17 +66,17 @@ class DashboardSettings: @property def relative_url(self): - return os.getenv('ESPHOME_DASHBOARD_RELATIVE_URL', '/') + return os.getenv("ESPHOME_DASHBOARD_RELATIVE_URL", "/") @property def status_use_ping(self): - return get_bool_env('ESPHOME_DASHBOARD_USE_PING') + return get_bool_env("ESPHOME_DASHBOARD_USE_PING") @property def using_hassio_auth(self): if not self.on_hassio: return False - return not get_bool_env('DISABLE_HA_AUTHENTICATION') + return not get_bool_env("DISABLE_HA_AUTHENTICATION") @property def using_auth(self): @@ -84,10 +89,7 @@ class DashboardSettings: return False # Compare password in constant running time (to prevent timing attacks) - return hmac.compare_digest( - self.password_hash, - password_hash(password) - ) + return hmac.compare_digest(self.password_hash, password_hash(password)) def rel_path(self, *args): return os.path.join(self.config_dir, *args) @@ -98,24 +100,24 @@ class DashboardSettings: settings = DashboardSettings() -cookie_authenticated_yes = b'yes' +cookie_authenticated_yes = b"yes" def template_args(): version = const.__version__ - if 'b' in version: - docs_link = 'https://beta.esphome.io/' - elif 'dev' in version: - docs_link = 'https://next.esphome.io/' + if "b" in version: + docs_link = "https://beta.esphome.io/" + elif "dev" in version: + docs_link = "https://next.esphome.io/" else: - docs_link = 'https://www.esphome.io/' + docs_link = "https://www.esphome.io/" return { - 'version': version, - 'docs_link': docs_link, - 'get_static_file_url': get_static_file_url, - 'relative_url': settings.relative_url, - 'streamer_mode': get_bool_env('ESPHOME_STREAMER_MODE'), - 'config_dir': settings.config_dir, + "version": version, + "docs_link": docs_link, + "get_static_file_url": get_static_file_url, + "relative_url": settings.relative_url, + "streamer_mode": get_bool_env("ESPHOME_STREAMER_MODE"), + "config_dir": settings.config_dir, } @@ -123,9 +125,10 @@ def authenticated(func): @functools.wraps(func) def decorator(self, *args, **kwargs): if not is_authenticated(self): - self.redirect('./login') + self.redirect("./login") return None return func(self, *args, **kwargs) + return decorator @@ -133,23 +136,27 @@ def is_authenticated(request_handler): if settings.on_hassio: # Handle ingress - disable auth on ingress port # X-Hassio-Ingress is automatically stripped on the non-ingress server in nginx - header = request_handler.request.headers.get('X-Hassio-Ingress', 'NO') - if str(header) == 'YES': + header = request_handler.request.headers.get("X-Hassio-Ingress", "NO") + if str(header) == "YES": return True if settings.using_auth: - return request_handler.get_secure_cookie('authenticated') == cookie_authenticated_yes + return ( + request_handler.get_secure_cookie("authenticated") + == cookie_authenticated_yes + ) return True def bind_config(func): def decorator(self, *args, **kwargs): - configuration = self.get_argument('configuration') + configuration = self.get_argument("configuration") if not is_allowed(configuration): self.set_status(500) return None kwargs = kwargs.copy() - kwargs['configuration'] = configuration + kwargs["configuration"] = configuration return func(self, *args, **kwargs) + return decorator @@ -160,7 +167,7 @@ class BaseHandler(tornado.web.RequestHandler): def websocket_class(cls): # pylint: disable=protected-access - if not hasattr(cls, '_message_handlers'): + if not hasattr(cls, "_message_handlers"): cls._message_handlers = {} for _, method in cls.__dict__.items(): @@ -175,6 +182,7 @@ def websocket_method(name): # pylint: disable=protected-access fn._message_handler = name return fn + return wrap @@ -190,7 +198,7 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler): def on_message(self, message): # Messages are always JSON, 500 when not json_message = json.loads(message) - type_ = json_message['type'] + type_ = json_message["type"] # pylint: disable=no-member handlers = type(self)._message_handlers if type_ not in handlers: @@ -199,17 +207,19 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler): handlers[type_](self, json_message) - @websocket_method('spawn') + @websocket_method("spawn") def handle_spawn(self, json_message): if self._proc is not None: # spawn can only be called once return command = self.build_command(json_message) - _LOGGER.info("Running command '%s'", ' '.join(shlex_quote(x) for x in command)) - self._proc = tornado.process.Subprocess(command, - stdout=tornado.process.Subprocess.STREAM, - stderr=subprocess.STDOUT, - stdin=tornado.process.Subprocess.STREAM) + _LOGGER.info("Running command '%s'", " ".join(shlex_quote(x) for x in command)) + self._proc = tornado.process.Subprocess( + command, + stdout=tornado.process.Subprocess.STREAM, + stderr=subprocess.STDOUT, + stdin=tornado.process.Subprocess.STREAM, + ) self._proc.set_exit_callback(self._proc_on_exit) tornado.ioloop.IOLoop.current().spawn_callback(self._redirect_stdout) @@ -217,34 +227,34 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler): def is_process_active(self): return self._proc is not None and self._proc.returncode is None - @websocket_method('stdin') + @websocket_method("stdin") def handle_stdin(self, json_message): if not self.is_process_active: return - data = json_message['data'] - data = codecs.encode(data, 'utf8', 'replace') + data = json_message["data"] + data = codecs.encode(data, "utf8", "replace") _LOGGER.debug("< stdin: %s", data) self._proc.stdin.write(data) @tornado.gen.coroutine def _redirect_stdout(self): - reg = b'[\n\r]' + reg = b"[\n\r]" while True: try: data = yield self._proc.stdout.read_until_regex(reg) except tornado.iostream.StreamClosedError: break - data = codecs.decode(data, 'utf8', 'replace') + data = codecs.decode(data, "utf8", "replace") _LOGGER.debug("> stdout: %s", data) - self.write_message({'event': 'line', 'data': data}) + self.write_message({"event": "line", "data": data}) def _proc_on_exit(self, returncode): if not self._is_closed: # Check if the proc was not forcibly closed _LOGGER.info("Process exited with return code %s", returncode) - self.write_message({'event': 'exit', 'code': returncode}) + self.write_message({"event": "exit", "code": returncode}) def on_close(self): # Check if proc exists (if 'start' has been run) @@ -260,45 +270,57 @@ class EsphomeCommandWebSocket(tornado.websocket.WebSocketHandler): class EsphomeLogsHandler(EsphomeCommandWebSocket): def build_command(self, json_message): - config_file = settings.rel_path(json_message['configuration']) - return ["esphome", "--dashboard", config_file, "logs", '--serial-port', - json_message["port"]] + config_file = settings.rel_path(json_message["configuration"]) + return [ + "esphome", + "--dashboard", + config_file, + "logs", + "--serial-port", + json_message["port"], + ] class EsphomeUploadHandler(EsphomeCommandWebSocket): def build_command(self, json_message): - config_file = settings.rel_path(json_message['configuration']) - return ["esphome", "--dashboard", config_file, "run", '--upload-port', - json_message["port"]] + config_file = settings.rel_path(json_message["configuration"]) + return [ + "esphome", + "--dashboard", + config_file, + "run", + "--upload-port", + json_message["port"], + ] class EsphomeCompileHandler(EsphomeCommandWebSocket): def build_command(self, json_message): - config_file = settings.rel_path(json_message['configuration']) + config_file = settings.rel_path(json_message["configuration"]) return ["esphome", "--dashboard", config_file, "compile"] class EsphomeValidateHandler(EsphomeCommandWebSocket): def build_command(self, json_message): - config_file = settings.rel_path(json_message['configuration']) + config_file = settings.rel_path(json_message["configuration"]) return ["esphome", "--dashboard", config_file, "config"] class EsphomeCleanMqttHandler(EsphomeCommandWebSocket): def build_command(self, json_message): - config_file = settings.rel_path(json_message['configuration']) + config_file = settings.rel_path(json_message["configuration"]) return ["esphome", "--dashboard", config_file, "clean-mqtt"] class EsphomeCleanHandler(EsphomeCommandWebSocket): def build_command(self, json_message): - config_file = settings.rel_path(json_message['configuration']) + config_file = settings.rel_path(json_message["configuration"]) return ["esphome", "--dashboard", config_file, "clean"] class EsphomeVscodeHandler(EsphomeCommandWebSocket): def build_command(self, json_message): - return ["esphome", "--dashboard", "-q", 'dummy', "vscode"] + return ["esphome", "--dashboard", "-q", "dummy", "vscode"] class EsphomeAceEditorHandler(EsphomeCommandWebSocket): @@ -318,15 +340,15 @@ class SerialPortRequestHandler(BaseHandler): data = [] for port in ports: desc = port.description - if port.path == '/dev/ttyAMA0': - desc = 'UART pins on GPIO header' - split_desc = desc.split(' - ') + if port.path == "/dev/ttyAMA0": + desc = "UART pins on GPIO header" + split_desc = desc.split(" - ") if len(split_desc) == 2 and split_desc[0] == split_desc[1]: # Some serial ports repeat their values desc = split_desc[0] - data.append({'port': port.path, 'desc': desc}) - data.append({'port': 'OTA', 'desc': 'Over-The-Air'}) - data.sort(key=lambda x: x['port'], reverse=True) + data.append({"port": port.path, "desc": desc}) + data.append({"port": "OTA", "desc": "Over-The-Air"}) + data.sort(key=lambda x: x["port"], reverse=True) self.write(json.dumps(data)) @@ -336,12 +358,11 @@ class WizardRequestHandler(BaseHandler): from esphome import wizard kwargs = { - k: ''.join(x.decode() for x in v) - for k, v in self.request.arguments.items() + k: "".join(x.decode() for x in v) for k, v in self.request.arguments.items() } - destination = settings.rel_path(kwargs['name'] + '.yaml') + destination = settings.rel_path(kwargs["name"] + ".yaml") wizard.wizard_write(path=destination, **kwargs) - self.redirect('./?begin=True') + self.redirect("./?begin=True") class DownloadBinaryRequestHandler(BaseHandler): @@ -356,10 +377,10 @@ class DownloadBinaryRequestHandler(BaseHandler): return path = storage_json.firmware_bin_path - self.set_header('Content-Type', 'application/octet-stream') - filename = f'{storage_json.name}.bin' + self.set_header("Content-Type", "application/octet-stream") + filename = f"{storage_json.name}.bin" self.set_header("Content-Disposition", f'attachment; filename="{filename}"') - with open(path, 'rb') as f: + with open(path, "rb") as f: while True: data = f.read(16384) if not data: @@ -386,7 +407,9 @@ class DashboardEntry: @property def storage(self): # type: () -> Optional[StorageJSON] if not self._loaded_storage: - self._storage = StorageJSON.load(ext_storage_path(settings.config_dir, self.filename)) + self._storage = StorageJSON.load( + ext_storage_path(settings.config_dir, self.filename) + ) self._loaded_storage = True return self._storage @@ -399,7 +422,7 @@ class DashboardEntry: @property def name(self): if self.storage is None: - return self.filename[:-len('.yaml')] + return self.filename[: -len(".yaml")] return self.storage.name @property @@ -429,8 +452,8 @@ class DashboardEntry: @property def update_old(self): if self.storage is None: - return '' - return self.storage.esphome_version or '' + return "" + return self.storage.esphome_version or "" @property def update_new(self): @@ -446,18 +469,23 @@ class DashboardEntry: class MainRequestHandler(BaseHandler): @authenticated def get(self): - begin = bool(self.get_argument('begin', False)) + begin = bool(self.get_argument("begin", False)) entries = _list_dashboard_entries() - self.render("templates/index.html", entries=entries, begin=begin, - **template_args(), login_enabled=settings.using_auth) + self.render( + "templates/index.html", + entries=entries, + begin=begin, + **template_args(), + login_enabled=settings.using_auth, + ) def _ping_func(filename, address): - if os.name == 'nt': - command = ['ping', '-n', '1', address] + if os.name == "nt": + command = ["ping", "-n", "1", address] else: - command = ['ping', '-c', '1', address] + command = ["ping", "-c", "1", address] rc, _, _ = run_system_command(*command) return filename, rc == 0 @@ -474,7 +502,9 @@ class MDNSStatusThread(threading.Thread): stat.start() while not STOP_EVENT.is_set(): entries = _list_dashboard_entries() - stat.request_query({entry.filename: entry.name + '.local.' for entry in entries}) + stat.request_query( + {entry.filename: entry.name + ".local." for entry in entries} + ) PING_REQUEST.wait() PING_REQUEST.clear() @@ -499,8 +529,9 @@ class PingStatusThread(threading.Thread): PING_RESULT[entry.filename] = None continue - result = pool.apply_async(_ping_func, (entry.filename, entry.address), - callback=callback) + result = pool.apply_async( + _ping_func, (entry.filename, entry.address), callback=callback + ) queue.append(result) while queue: @@ -541,10 +572,10 @@ class EditRequestHandler(BaseHandler): @bind_config def get(self, configuration=None): filename = settings.rel_path(configuration) - content = '' + content = "" if os.path.isfile(filename): # pylint: disable=no-value-for-parameter - with open(filename, 'r') as f: + with open(filename, "r") as f: content = f.read() self.write(content) @@ -552,7 +583,7 @@ class EditRequestHandler(BaseHandler): @bind_config def post(self, configuration=None): # pylint: disable=no-value-for-parameter - with open(settings.rel_path(configuration), 'wb') as f: + with open(settings.rel_path(configuration), "wb") as f: f.write(self.request.body) self.set_status(200) @@ -596,29 +627,34 @@ PING_REQUEST = threading.Event() class LoginHandler(BaseHandler): def get(self): if is_authenticated(self): - self.redirect('/') + self.redirect("/") else: self.render_login_page() def render_login_page(self, error=None): - self.render("templates/login.html", error=error, hassio=settings.using_hassio_auth, - has_username=bool(settings.username), **template_args()) + self.render( + "templates/login.html", + error=error, + hassio=settings.using_hassio_auth, + has_username=bool(settings.username), + **template_args(), + ) def post_hassio_login(self): import requests headers = { - 'X-HASSIO-KEY': os.getenv('HASSIO_TOKEN'), + "X-HASSIO-KEY": os.getenv("HASSIO_TOKEN"), } data = { - 'username': self.get_argument('username', ''), - 'password': self.get_argument('password', '') + "username": self.get_argument("username", ""), + "password": self.get_argument("password", ""), } try: - req = requests.post('http://hassio/auth', headers=headers, data=data) + req = requests.post("http://hassio/auth", headers=headers, data=data) if req.status_code == 200: self.set_secure_cookie("authenticated", cookie_authenticated_yes) - self.redirect('/') + self.redirect("/") return except Exception as err: # pylint: disable=broad-except _LOGGER.warning("Error during Hass.io auth request: %s", err) @@ -629,13 +665,15 @@ class LoginHandler(BaseHandler): self.render_login_page(error="Invalid username or password") def post_native_login(self): - username = self.get_argument("username", '') - password = self.get_argument("password", '') + username = self.get_argument("username", "") + password = self.get_argument("password", "") if settings.check_password(username, password): self.set_secure_cookie("authenticated", cookie_authenticated_yes) self.redirect("/") return - error_str = "Invalid username or password" if settings.username else "Invalid password" + error_str = ( + "Invalid username or password" if settings.username else "Invalid password" + ) self.set_status(401) self.render_login_page(error=error_str) @@ -650,22 +688,22 @@ class LogoutHandler(BaseHandler): @authenticated def get(self): self.clear_cookie("authenticated") - self.redirect('./login') + self.redirect("./login") _STATIC_FILE_HASHES = {} def get_static_file_url(name): - static_path = os.path.join(os.path.dirname(__file__), 'static') + static_path = os.path.join(os.path.dirname(__file__), "static") if name in _STATIC_FILE_HASHES: hash_ = _STATIC_FILE_HASHES[name] else: path = os.path.join(static_path, name) - with open(path, 'rb') as f_handle: + with open(path, "rb") as f_handle: hash_ = hashlib.md5(f_handle.read()).hexdigest()[:8] _STATIC_FILE_HASHES[name] = hash_ - return f'./static/{name}?hash={hash_}' + return f"./static/{name}?hash={hash_}" def make_app(debug=False): @@ -684,44 +722,53 @@ def make_app(debug=False): request_time = 1000.0 * handler.request.request_time() # pylint: disable=protected-access - log_method("%d %s %.2fms", handler.get_status(), - handler._request_summary(), request_time) + log_method( + "%d %s %.2fms", + handler.get_status(), + handler._request_summary(), + request_time, + ) class StaticFileHandler(tornado.web.StaticFileHandler): def set_extra_headers(self, path): if debug: - self.set_header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0') + self.set_header( + "Cache-Control", "no-store, no-cache, must-revalidate, max-age=0" + ) - static_path = os.path.join(os.path.dirname(__file__), 'static') + static_path = os.path.join(os.path.dirname(__file__), "static") app_settings = { - 'debug': debug, - 'cookie_secret': settings.cookie_secret, - 'log_function': log_function, - 'websocket_ping_interval': 30.0, + "debug": debug, + "cookie_secret": settings.cookie_secret, + "log_function": log_function, + "websocket_ping_interval": 30.0, } rel = settings.relative_url - app = tornado.web.Application([ - (rel + "", MainRequestHandler), - (rel + "login", LoginHandler), - (rel + "logout", LogoutHandler), - (rel + "logs", EsphomeLogsHandler), - (rel + "upload", EsphomeUploadHandler), - (rel + "compile", EsphomeCompileHandler), - (rel + "validate", EsphomeValidateHandler), - (rel + "clean-mqtt", EsphomeCleanMqttHandler), - (rel + "clean", EsphomeCleanHandler), - (rel + "vscode", EsphomeVscodeHandler), - (rel + "ace", EsphomeAceEditorHandler), - (rel + "update-all", EsphomeUpdateAllHandler), - (rel + "edit", EditRequestHandler), - (rel + "download.bin", DownloadBinaryRequestHandler), - (rel + "serial-ports", SerialPortRequestHandler), - (rel + "ping", PingRequestHandler), - (rel + "delete", DeleteRequestHandler), - (rel + "undo-delete", UndoDeleteRequestHandler), - (rel + "wizard.html", WizardRequestHandler), - (rel + r"static/(.*)", StaticFileHandler, {'path': static_path}), - ], **app_settings) + app = tornado.web.Application( + [ + (rel + "", MainRequestHandler), + (rel + "login", LoginHandler), + (rel + "logout", LogoutHandler), + (rel + "logs", EsphomeLogsHandler), + (rel + "upload", EsphomeUploadHandler), + (rel + "compile", EsphomeCompileHandler), + (rel + "validate", EsphomeValidateHandler), + (rel + "clean-mqtt", EsphomeCleanMqttHandler), + (rel + "clean", EsphomeCleanHandler), + (rel + "vscode", EsphomeVscodeHandler), + (rel + "ace", EsphomeAceEditorHandler), + (rel + "update-all", EsphomeUpdateAllHandler), + (rel + "edit", EditRequestHandler), + (rel + "download.bin", DownloadBinaryRequestHandler), + (rel + "serial-ports", SerialPortRequestHandler), + (rel + "ping", PingRequestHandler), + (rel + "delete", DeleteRequestHandler), + (rel + "undo-delete", UndoDeleteRequestHandler), + (rel + "wizard.html", WizardRequestHandler), + (rel + r"static/(.*)", StaticFileHandler, {"path": static_path}), + ], + **app_settings, + ) if debug: _STATIC_FILE_HASHES.clear() @@ -743,20 +790,26 @@ def start_web_server(args): app = make_app(args.verbose) if args.socket is not None: - _LOGGER.info("Starting dashboard web server on unix socket %s and configuration dir %s...", - args.socket, settings.config_dir) + _LOGGER.info( + "Starting dashboard web server on unix socket %s and configuration dir %s...", + args.socket, + settings.config_dir, + ) server = tornado.httpserver.HTTPServer(app) socket = tornado.netutil.bind_unix_socket(args.socket, mode=0o666) server.add_socket(socket) else: - _LOGGER.info("Starting dashboard web server on port %s and configuration dir %s...", - args.port, settings.config_dir) + _LOGGER.info( + "Starting dashboard web server on port %s and configuration dir %s...", + args.port, + settings.config_dir, + ) app.listen(args.port) if args.open_ui: import webbrowser - webbrowser.open(f'localhost:{args.port}') + webbrowser.open(f"localhost:{args.port}") if settings.status_use_ping: status_thread = PingStatusThread() diff --git a/esphome/espota2.py b/esphome/espota2.py index a1408a7d4..785cb155d 100644 --- a/esphome/espota2.py +++ b/esphome/espota2.py @@ -52,14 +52,15 @@ class ProgressBar: return self.last_progress = new_progress block = int(round(bar_length * progress)) - text = "\rUploading: [{0}] {1}% {2}".format("=" * block + " " * (bar_length - block), - new_progress, status) + text = "\rUploading: [{0}] {1}% {2}".format( + "=" * block + " " * (bar_length - block), new_progress, status + ) sys.stderr.write(text) sys.stderr.flush() # pylint: disable=no-self-use def done(self): - sys.stderr.write('\n') + sys.stderr.write("\n") sys.stderr.flush() @@ -78,7 +79,7 @@ def receive_exactly(sock, amount, msg, expect, decode=True): if decode: data = [] else: - data = b'' + data = b"" try: data += recv_decode(sock, 1, decode=decode) @@ -106,32 +107,48 @@ def check_error(data, expect): if dat == RESPONSE_ERROR_MAGIC: raise OTAError("Error: Invalid magic byte") if dat == RESPONSE_ERROR_UPDATE_PREPARE: - raise OTAError("Error: Couldn't prepare flash memory for update. Is the binary too big? " - "Please try restarting the ESP.") + raise OTAError( + "Error: Couldn't prepare flash memory for update. Is the binary too big? " + "Please try restarting the ESP." + ) if dat == RESPONSE_ERROR_AUTH_INVALID: raise OTAError("Error: Authentication invalid. Is the password correct?") if dat == RESPONSE_ERROR_WRITING_FLASH: - raise OTAError("Error: Wring OTA data to flash memory failed. See USB logs for more " - "information.") + raise OTAError( + "Error: Wring OTA data to flash memory failed. See USB logs for more " + "information." + ) if dat == RESPONSE_ERROR_UPDATE_END: - raise OTAError("Error: Finishing update failed. See the MQTT/USB logs for more " - "information.") + raise OTAError( + "Error: Finishing update failed. See the MQTT/USB logs for more " + "information." + ) if dat == RESPONSE_ERROR_INVALID_BOOTSTRAPPING: - raise OTAError("Error: Please press the reset button on the ESP. A manual reset is " - "required on the first OTA-Update after flashing via USB.") + raise OTAError( + "Error: Please press the reset button on the ESP. A manual reset is " + "required on the first OTA-Update after flashing via USB." + ) if dat == RESPONSE_ERROR_WRONG_CURRENT_FLASH_CONFIG: - raise OTAError("Error: ESP has been flashed with wrong flash size. Please choose the " - "correct 'board' option (esp01_1m always works) and then flash over USB.") + raise OTAError( + "Error: ESP has been flashed with wrong flash size. Please choose the " + "correct 'board' option (esp01_1m always works) and then flash over USB." + ) if dat == RESPONSE_ERROR_WRONG_NEW_FLASH_CONFIG: - raise OTAError("Error: ESP does not have the requested flash size (wrong board). Please " - "choose the correct 'board' option (esp01_1m always works) and try " - "uploading again.") + raise OTAError( + "Error: ESP does not have the requested flash size (wrong board). Please " + "choose the correct 'board' option (esp01_1m always works) and try " + "uploading again." + ) if dat == RESPONSE_ERROR_ESP8266_NOT_ENOUGH_SPACE: - raise OTAError("Error: ESP does not have enough space to store OTA file. Please try " - "flashing a minimal firmware (remove everything except ota)") + raise OTAError( + "Error: ESP does not have enough space to store OTA file. Please try " + "flashing a minimal firmware (remove everything except ota)" + ) if dat == RESPONSE_ERROR_ESP32_NOT_ENOUGH_SPACE: - raise OTAError("Error: The OTA partition on the ESP is too small. ESPHome needs to resize " - "this partition, please flash over USB.") + raise OTAError( + "Error: The OTA partition on the ESP is too small. ESPHome needs to resize " + "this partition, please flash over USB." + ) if dat == RESPONSE_ERROR_UNKNOWN: raise OTAError("Unknown error from ESP") if not isinstance(expect, (list, tuple)): @@ -147,7 +164,7 @@ def send_check(sock, data, msg): elif isinstance(data, int): data = bytes([data]) elif isinstance(data, str): - data = data.encode('utf8') + data = data.encode("utf8") sock.sendall(data) except OSError as err: @@ -157,42 +174,46 @@ def send_check(sock, data, msg): def perform_ota(sock, password, file_handle, filename): file_md5 = hashlib.md5(file_handle.read()).hexdigest() file_size = file_handle.tell() - _LOGGER.info('Uploading %s (%s bytes)', filename, file_size) + _LOGGER.info("Uploading %s (%s bytes)", filename, file_size) file_handle.seek(0) _LOGGER.debug("MD5 of binary is %s", file_md5) # Enable nodelay, we need it for phase 1 sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) - send_check(sock, MAGIC_BYTES, 'magic bytes') + send_check(sock, MAGIC_BYTES, "magic bytes") - _, version = receive_exactly(sock, 2, 'version', RESPONSE_OK) + _, version = receive_exactly(sock, 2, "version", RESPONSE_OK) if version != OTA_VERSION_1_0: raise OTAError(f"Unsupported OTA version {version}") # Features - send_check(sock, 0x00, 'features') - receive_exactly(sock, 1, 'features', RESPONSE_HEADER_OK) + send_check(sock, 0x00, "features") + receive_exactly(sock, 1, "features", RESPONSE_HEADER_OK) - auth, = receive_exactly(sock, 1, 'auth', [RESPONSE_REQUEST_AUTH, RESPONSE_AUTH_OK]) + (auth,) = receive_exactly( + sock, 1, "auth", [RESPONSE_REQUEST_AUTH, RESPONSE_AUTH_OK] + ) if auth == RESPONSE_REQUEST_AUTH: if not password: raise OTAError("ESP requests password, but no password given!") - nonce = receive_exactly(sock, 32, 'authentication nonce', [], decode=False).decode() + nonce = receive_exactly( + sock, 32, "authentication nonce", [], decode=False + ).decode() _LOGGER.debug("Auth: Nonce is %s", nonce) cnonce = hashlib.md5(str(random.random()).encode()).hexdigest() _LOGGER.debug("Auth: CNonce is %s", cnonce) - send_check(sock, cnonce, 'auth cnonce') + send_check(sock, cnonce, "auth cnonce") result_md5 = hashlib.md5() - result_md5.update(password.encode('utf-8')) + result_md5.update(password.encode("utf-8")) result_md5.update(nonce.encode()) result_md5.update(cnonce.encode()) result = result_md5.hexdigest() _LOGGER.debug("Auth: Result is %s", result) - send_check(sock, result, 'auth result') - receive_exactly(sock, 1, 'auth result', RESPONSE_AUTH_OK) + send_check(sock, result, "auth result") + receive_exactly(sock, 1, "auth result", RESPONSE_AUTH_OK) file_size_encoded = [ (file_size >> 24) & 0xFF, @@ -200,11 +221,11 @@ def perform_ota(sock, password, file_handle, filename): (file_size >> 8) & 0xFF, (file_size >> 0) & 0xFF, ] - send_check(sock, file_size_encoded, 'binary size') - receive_exactly(sock, 1, 'binary size', RESPONSE_UPDATE_PREPARE_OK) + send_check(sock, file_size_encoded, "binary size") + receive_exactly(sock, 1, "binary size", RESPONSE_UPDATE_PREPARE_OK) - send_check(sock, file_md5, 'file checksum') - receive_exactly(sock, 1, 'file checksum', RESPONSE_BIN_MD5_OK) + send_check(sock, file_md5, "file checksum") + receive_exactly(sock, 1, "file checksum", RESPONSE_BIN_MD5_OK) # Disable nodelay for transfer sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 0) @@ -225,7 +246,7 @@ def perform_ota(sock, password, file_handle, filename): try: sock.sendall(chunk) except OSError as err: - sys.stderr.write('\n') + sys.stderr.write("\n") raise OTAError(f"Error sending data: {err}") from err progress.update(offset / float(file_size)) @@ -236,9 +257,9 @@ def perform_ota(sock, password, file_handle, filename): _LOGGER.info("Waiting for result...") - receive_exactly(sock, 1, 'receive OK', RESPONSE_RECEIVE_OK) - receive_exactly(sock, 1, 'Update end', RESPONSE_UPDATE_END_OK) - send_check(sock, RESPONSE_OK, 'end acknowledgement') + receive_exactly(sock, 1, "receive OK", RESPONSE_RECEIVE_OK) + receive_exactly(sock, 1, "Update end", RESPONSE_UPDATE_END_OK) + send_check(sock, RESPONSE_OK, "end acknowledgement") _LOGGER.info("OTA successful") @@ -255,10 +276,14 @@ def run_ota_impl_(remote_host, remote_port, password, filename): try: ip = resolve_ip_address(remote_host) except EsphomeError as err: - _LOGGER.error("Error resolving IP address of %s. Is it connected to WiFi?", - remote_host) - _LOGGER.error("(If this error persists, please set a static IP address: " - "https://esphome.io/components/wifi.html#manual-ips)") + _LOGGER.error( + "Error resolving IP address of %s. Is it connected to WiFi?", + remote_host, + ) + _LOGGER.error( + "(If this error persists, please set a static IP address: " + "https://esphome.io/components/wifi.html#manual-ips)" + ) raise OTAError(err) from err _LOGGER.info(" -> %s", ip) @@ -271,7 +296,7 @@ def run_ota_impl_(remote_host, remote_port, password, filename): _LOGGER.error("Connecting to %s:%s failed: %s", remote_host, remote_port, err) return 1 - file_handle = open(filename, 'rb') + file_handle = open(filename, "rb") try: perform_ota(sock, password, file_handle, filename) except OTAError as err: diff --git a/esphome/helpers.py b/esphome/helpers.py index 1389804fd..780a2aa88 100644 --- a/esphome/helpers.py +++ b/esphome/helpers.py @@ -22,48 +22,48 @@ def ensure_unique_string(preferred_string, current_strings): return test_string -def indent_all_but_first_and_last(text, padding=' '): +def indent_all_but_first_and_last(text, padding=" "): lines = text.splitlines(True) if len(lines) <= 2: return text - return lines[0] + ''.join(padding + line for line in lines[1:-1]) + lines[-1] + return lines[0] + "".join(padding + line for line in lines[1:-1]) + lines[-1] -def indent_list(text, padding=' '): +def indent_list(text, padding=" "): return [padding + line for line in text.splitlines()] -def indent(text, padding=' '): - return '\n'.join(indent_list(text, padding)) +def indent(text, padding=" "): + return "\n".join(indent_list(text, padding)) # From https://stackoverflow.com/a/14945195/8924614 -def cpp_string_escape(string, encoding='utf-8'): +def cpp_string_escape(string, encoding="utf-8"): def _should_escape(byte): # type: (int) -> bool if not 32 <= byte < 127: return True - if byte in (ord('\\'), ord('"')): + if byte in (ord("\\"), ord('"')): return True return False if isinstance(string, str): string = string.encode(encoding) - result = '' + result = "" for character in string: if _should_escape(character): - result += f'\\{character:03o}' + result += f"\\{character:03o}" else: result += chr(character) return '"' + result + '"' -def color(the_color, message=''): +def color(the_color, message=""): from colorlog.escape_codes import escape_codes, parse_colors if not message: res = parse_colors(the_color) else: - res = parse_colors(the_color) + message + escape_codes['reset'] + res = parse_colors(the_color) + message + escape_codes["reset"] return res @@ -85,15 +85,17 @@ def mkdir_p(path): os.makedirs(path) except OSError as err: import errno + if err.errno == errno.EEXIST and os.path.isdir(path): pass else: from esphome.core import EsphomeError + raise EsphomeError(f"Error creating directories {path}: {err}") from err def is_ip_address(host): - parts = host.split('.') + parts = host.split(".") if len(parts) != 4: return False try: @@ -111,17 +113,21 @@ def _resolve_with_zeroconf(host): try: zc = Zeroconf() except Exception as err: - raise EsphomeError("Cannot start mDNS sockets, is this a docker container without " - "host network mode?") from err + raise EsphomeError( + "Cannot start mDNS sockets, is this a docker container without " + "host network mode?" + ) from err try: - info = zc.resolve_host(host + '.') + info = zc.resolve_host(host + ".") except Exception as err: raise EsphomeError(f"Error resolving mDNS hostname: {err}") from err finally: zc.close() if info is None: - raise EsphomeError("Error resolving address with mDNS: Did not respond. " - "Maybe the device is offline.") + raise EsphomeError( + "Error resolving address with mDNS: Did not respond. " + "Maybe the device is offline." + ) return info @@ -131,7 +137,7 @@ def resolve_ip_address(host): errs = [] - if host.endswith('.local'): + if host.endswith(".local"): try: return _resolve_with_zeroconf(host) except EsphomeError as err: @@ -141,8 +147,9 @@ def resolve_ip_address(host): return socket.gethostbyname(host) except OSError as err: errs.append(str(err)) - raise EsphomeError("Error resolving IP address: {}" - "".format(', '.join(errs))) from err + raise EsphomeError( + "Error resolving IP address: {}" "".format(", ".join(errs)) + ) from err def get_bool_env(var, default=False): @@ -150,7 +157,7 @@ def get_bool_env(var, default=False): def is_hassio(): - return get_bool_env('ESPHOME_IS_HASSIO') + return get_bool_env("ESPHOME_IS_HASSIO") def walk_files(path): @@ -161,13 +168,15 @@ def walk_files(path): def read_file(path): try: - with codecs.open(path, 'r', encoding='utf-8') as f_handle: + with codecs.open(path, "r", encoding="utf-8") as f_handle: return f_handle.read() except OSError as err: from esphome.core import EsphomeError + raise EsphomeError(f"Error reading file {path}: {err}") from err except UnicodeDecodeError as err: from esphome.core import EsphomeError + raise EsphomeError(f"Error reading file {path}: {err}") from err @@ -187,7 +196,9 @@ def _write_file(path: Union[Path, str], text: Union[str, bytes]): tmp_path = None try: - with tempfile.NamedTemporaryFile(mode="wb", dir=directory, delete=False) as f_handle: + with tempfile.NamedTemporaryFile( + mode="wb", dir=directory, delete=False + ) as f_handle: tmp_path = f_handle.name f_handle.write(data) # Newer tempfile implementations create the file with mode 0o600 @@ -207,6 +218,7 @@ def write_file(path: Union[Path, str], text: str): _write_file(path, text) except OSError as err: from esphome.core import EsphomeError + raise EsphomeError(f"Could not write file at {path}") from err @@ -223,6 +235,7 @@ def write_file_if_changed(path: Union[Path, str], text: str): def copy_file_if_changed(src, dst): import shutil + if file_compare(src, dst): return mkdir_p(os.path.dirname(dst)) @@ -230,6 +243,7 @@ def copy_file_if_changed(src, dst): shutil.copy(src, dst) except OSError as err: from esphome.core import EsphomeError + raise EsphomeError(f"Error copying file {src} to {dst}: {err}") from err @@ -247,16 +261,19 @@ def file_compare(path1, path2): # File doesn't exist or another error -> not equal return False - if stat.S_IFMT(stat1.st_mode) != stat.S_IFREG or stat.S_IFMT(stat2.st_mode) != stat.S_IFREG: + if ( + stat.S_IFMT(stat1.st_mode) != stat.S_IFREG + or stat.S_IFMT(stat2.st_mode) != stat.S_IFREG + ): # At least one of them is not a regular file (or does not exist) return False if stat1.st_size != stat2.st_size: # Different sizes return False - bufsize = 8*1024 + bufsize = 8 * 1024 # Read files in blocks until a mismatch is found - with open(path1, 'rb') as fh1, open(path2, 'rb') as fh2: + with open(path1, "rb") as fh1, open(path2, "rb") as fh2: while True: blob1, blob2 = fh1.read(bufsize), fh2.read(bufsize) if blob1 != blob2: @@ -270,11 +287,11 @@ def file_compare(path1, path2): # A dict of types that need to be converted to heaptypes before a class can be added # to the object _TYPE_OVERLOADS = { - int: type('EInt', (int,), dict()), - float: type('EFloat', (float,), dict()), - str: type('EStr', (str,), dict()), - dict: type('EDict', (str,), dict()), - list: type('EList', (list,), dict()), + int: type("EInt", (int,), dict()), + float: type("EFloat", (float,), dict()), + str: type("EStr", (str,), dict()), + dict: type("EDict", (str,), dict()), + list: type("EList", (list,), dict()), } # cache created classes here diff --git a/esphome/legacy.py b/esphome/legacy.py index 27373ee1a..6b3b1d6c9 100644 --- a/esphome/legacy.py +++ b/esphome/legacy.py @@ -4,7 +4,7 @@ import sys def main(): print("The esphomeyaml command has been renamed to esphome.") print("") - print("$ esphome {}".format(' '.join(sys.argv[1:]))) + print("$ esphome {}".format(" ".join(sys.argv[1:]))) return 1 diff --git a/esphome/mqtt.py b/esphome/mqtt.py index 499ccbe7f..86937ba37 100644 --- a/esphome/mqtt.py +++ b/esphome/mqtt.py @@ -7,9 +7,20 @@ import time import paho.mqtt.client as mqtt -from esphome.const import CONF_BROKER, CONF_DISCOVERY_PREFIX, CONF_ESPHOME, \ - CONF_LOG_TOPIC, CONF_MQTT, CONF_NAME, CONF_PASSWORD, CONF_PORT, CONF_SSL_FINGERPRINTS, \ - CONF_TOPIC, CONF_TOPIC_PREFIX, CONF_USERNAME +from esphome.const import ( + CONF_BROKER, + CONF_DISCOVERY_PREFIX, + CONF_ESPHOME, + CONF_LOG_TOPIC, + CONF_MQTT, + CONF_NAME, + CONF_PASSWORD, + CONF_PORT, + CONF_SSL_FINGERPRINTS, + CONF_TOPIC, + CONF_TOPIC_PREFIX, + CONF_USERNAME, +) from esphome.core import CORE, EsphomeError from esphome.helpers import color from esphome.util import safe_print @@ -36,21 +47,24 @@ def initialize(config, subscriptions, on_message, username, password, client_id) except OSError: pass - wait_time = min(2**tries, 300) + wait_time = min(2 ** tries, 300) _LOGGER.warning( "Disconnected from MQTT (%s). Trying to reconnect in %s s", - result_code, wait_time) + result_code, + wait_time, + ) time.sleep(wait_time) tries += 1 - client = mqtt.Client(client_id or '') + client = mqtt.Client(client_id or "") client.on_connect = on_connect client.on_message = on_message client.on_disconnect = on_disconnect if username is None: if config[CONF_MQTT].get(CONF_USERNAME): - client.username_pw_set(config[CONF_MQTT][CONF_USERNAME], - config[CONF_MQTT][CONF_PASSWORD]) + client.username_pw_set( + config[CONF_MQTT][CONF_USERNAME], config[CONF_MQTT][CONF_PASSWORD] + ) elif username: client.username_pw_set(username, password) @@ -59,8 +73,14 @@ def initialize(config, subscriptions, on_message, username, password, client_id) tls_version = ssl.PROTOCOL_TLS # pylint: disable=no-member else: tls_version = ssl.PROTOCOL_SSLv23 - client.tls_set(ca_certs=None, certfile=None, keyfile=None, cert_reqs=ssl.CERT_REQUIRED, - tls_version=tls_version, ciphers=None) + client.tls_set( + ca_certs=None, + certfile=None, + keyfile=None, + cert_reqs=ssl.CERT_REQUIRED, + tls_version=tls_version, + ciphers=None, + ) try: host = str(config[CONF_MQTT][CONF_BROKER]) @@ -84,17 +104,17 @@ def show_logs(config, topic=None, username=None, password=None, client_id=None): if CONF_LOG_TOPIC in conf: topic = config[CONF_MQTT][CONF_LOG_TOPIC][CONF_TOPIC] elif CONF_TOPIC_PREFIX in config[CONF_MQTT]: - topic = config[CONF_MQTT][CONF_TOPIC_PREFIX] + '/debug' + topic = config[CONF_MQTT][CONF_TOPIC_PREFIX] + "/debug" else: - topic = config[CONF_ESPHOME][CONF_NAME] + '/debug' + topic = config[CONF_ESPHOME][CONF_NAME] + "/debug" else: _LOGGER.error("MQTT isn't setup, can't start MQTT logs") return 1 _LOGGER.info("Starting log output from %s", topic) def on_message(client, userdata, msg): - time_ = datetime.now().time().strftime('[%H:%M:%S]') - payload = msg.payload.decode(errors='backslashreplace') + time_ = datetime.now().time().strftime("[%H:%M:%S]") + payload = msg.payload.decode(errors="backslashreplace") message = time_ + payload safe_print(message) @@ -103,12 +123,14 @@ def show_logs(config, topic=None, username=None, password=None, client_id=None): def clear_topic(config, topic, username=None, password=None, client_id=None): if topic is None: - discovery_prefix = config[CONF_MQTT].get(CONF_DISCOVERY_PREFIX, 'homeassistant') + discovery_prefix = config[CONF_MQTT].get(CONF_DISCOVERY_PREFIX, "homeassistant") name = config[CONF_ESPHOME][CONF_NAME] - topic = f'{discovery_prefix}/+/{name}/#' + topic = f"{discovery_prefix}/+/{name}/#" _LOGGER.info("Clearing messages from '%s'", topic) - _LOGGER.info("Please close this window when no more messages appear and the " - "MQTT topic has been cleared of retained messages.") + _LOGGER.info( + "Please close this window when no more messages appear and the " + "MQTT topic has been cleared of retained messages." + ) def on_message(client, userdata, msg): if not msg.payload or not msg.retain: @@ -136,7 +158,9 @@ def get_fingerprint(config): sha1 = hashlib.sha1(cert_der).hexdigest() - safe_print("SHA1 Fingerprint: " + color('cyan', sha1)) - safe_print("Copy the string above into mqtt.ssl_fingerprints section of {}" - "".format(CORE.config_path)) + safe_print("SHA1 Fingerprint: " + color("cyan", sha1)) + safe_print( + "Copy the string above into mqtt.ssl_fingerprints section of {}" + "".format(CORE.config_path) + ) return 0 diff --git a/esphome/pins.py b/esphome/pins.py index 2a154c4db..fef77f394 100644 --- a/esphome/pins.py +++ b/esphome/pins.py @@ -8,53 +8,149 @@ from esphome.util import SimpleRegistry _LOGGER = logging.getLogger(__name__) ESP8266_BASE_PINS = { - 'A0': 17, 'SS': 15, 'MOSI': 13, 'MISO': 12, 'SCK': 14, 'SDA': 4, 'SCL': 5, 'RX': 3, 'TX': 1 + "A0": 17, + "SS": 15, + "MOSI": 13, + "MISO": 12, + "SCK": 14, + "SDA": 4, + "SCL": 5, + "RX": 3, + "TX": 1, } ESP8266_BOARD_PINS = { - 'd1': {'D0': 3, 'D1': 1, 'D2': 16, 'D3': 5, 'D4': 4, 'D5': 14, 'D6': 12, 'D7': 13, 'D8': 0, - 'D9': 2, 'D10': 15, 'D11': 13, 'D12': 14, 'D13': 14, 'D14': 4, 'D15': 5, 'LED': 2}, - 'd1_mini': {'D0': 16, 'D1': 5, 'D2': 4, 'D3': 0, 'D4': 2, 'D5': 14, 'D6': 12, 'D7': 13, - 'D8': 15, 'LED': 2}, - 'd1_mini_lite': 'd1_mini', - 'd1_mini_pro': 'd1_mini', - 'esp01': {}, - 'esp01_1m': {}, - 'esp07': {}, - 'esp12e': {}, - 'esp210': {}, - 'esp8285': {}, - 'esp_wroom_02': {}, - 'espduino': {'LED': 16}, - 'espectro': {'LED': 15, 'BUTTON': 2}, - 'espino': {'LED': 2, 'LED_RED': 2, 'LED_GREEN': 4, 'LED_BLUE': 5, 'BUTTON': 0}, - 'espinotee': {'LED': 16}, - 'espresso_lite_v1': {'LED': 16}, - 'espresso_lite_v2': {'LED': 2}, - 'gen4iod': {}, - 'heltec_wifi_kit_8': 'd1_mini', - 'huzzah': {'LED': 0, 'LED_RED': 0, 'LED_BLUE': 2, 'D4': 4, 'D5': 5, 'D12': 12, - 'D13': 13, 'D14': 14, 'D15': 15, 'D16': 16}, - 'inventone': {}, - 'modwifi': {}, - 'nodemcu': {'D0': 16, 'D1': 5, 'D2': 4, 'D3': 0, 'D4': 2, 'D5': 14, 'D6': 12, 'D7': 13, - 'D8': 15, 'D9': 3, 'D10': 1, 'LED': 16}, - 'nodemcuv2': 'nodemcu', - 'oak': {'P0': 2, 'P1': 5, 'P2': 0, 'P3': 3, 'P4': 1, 'P5': 4, 'P6': 15, 'P7': 13, 'P8': 12, - 'P9': 14, 'P10': 16, 'P11': 17, 'LED': 5}, - 'phoenix_v1': {'LED': 16}, - 'phoenix_v2': {'LED': 2}, - 'sparkfunBlynk': 'thing', - 'thing': {'LED': 5, 'SDA': 2, 'SCL': 14}, - 'thingdev': 'thing', - 'wifi_slot': {'LED': 2}, - 'wifiduino': {'D0': 3, 'D1': 1, 'D2': 2, 'D3': 0, 'D4': 4, 'D5': 5, 'D6': 16, 'D7': 14, - 'D8': 12, 'D9': 13, 'D10': 15, 'D11': 13, 'D12': 12, 'D13': 14}, - 'wifinfo': {'LED': 12, 'D0': 16, 'D1': 5, 'D2': 4, 'D3': 0, 'D4': 2, 'D5': 14, 'D6': 12, - 'D7': 13, 'D8': 15, 'D9': 3, 'D10': 1}, - 'wio_link': {'LED': 2, 'GROVE': 15, 'D0': 14, 'D1': 12, 'D2': 13, 'BUTTON': 0}, - 'wio_node': {'LED': 2, 'GROVE': 15, 'D0': 3, 'D1': 5, 'BUTTON': 0}, - 'xinabox_cw01': {'SDA': 2, 'SCL': 14, 'LED': 5, 'LED_RED': 12, 'LED_GREEN': 13} + "d1": { + "D0": 3, + "D1": 1, + "D2": 16, + "D3": 5, + "D4": 4, + "D5": 14, + "D6": 12, + "D7": 13, + "D8": 0, + "D9": 2, + "D10": 15, + "D11": 13, + "D12": 14, + "D13": 14, + "D14": 4, + "D15": 5, + "LED": 2, + }, + "d1_mini": { + "D0": 16, + "D1": 5, + "D2": 4, + "D3": 0, + "D4": 2, + "D5": 14, + "D6": 12, + "D7": 13, + "D8": 15, + "LED": 2, + }, + "d1_mini_lite": "d1_mini", + "d1_mini_pro": "d1_mini", + "esp01": {}, + "esp01_1m": {}, + "esp07": {}, + "esp12e": {}, + "esp210": {}, + "esp8285": {}, + "esp_wroom_02": {}, + "espduino": {"LED": 16}, + "espectro": {"LED": 15, "BUTTON": 2}, + "espino": {"LED": 2, "LED_RED": 2, "LED_GREEN": 4, "LED_BLUE": 5, "BUTTON": 0}, + "espinotee": {"LED": 16}, + "espresso_lite_v1": {"LED": 16}, + "espresso_lite_v2": {"LED": 2}, + "gen4iod": {}, + "heltec_wifi_kit_8": "d1_mini", + "huzzah": { + "LED": 0, + "LED_RED": 0, + "LED_BLUE": 2, + "D4": 4, + "D5": 5, + "D12": 12, + "D13": 13, + "D14": 14, + "D15": 15, + "D16": 16, + }, + "inventone": {}, + "modwifi": {}, + "nodemcu": { + "D0": 16, + "D1": 5, + "D2": 4, + "D3": 0, + "D4": 2, + "D5": 14, + "D6": 12, + "D7": 13, + "D8": 15, + "D9": 3, + "D10": 1, + "LED": 16, + }, + "nodemcuv2": "nodemcu", + "oak": { + "P0": 2, + "P1": 5, + "P2": 0, + "P3": 3, + "P4": 1, + "P5": 4, + "P6": 15, + "P7": 13, + "P8": 12, + "P9": 14, + "P10": 16, + "P11": 17, + "LED": 5, + }, + "phoenix_v1": {"LED": 16}, + "phoenix_v2": {"LED": 2}, + "sparkfunBlynk": "thing", + "thing": {"LED": 5, "SDA": 2, "SCL": 14}, + "thingdev": "thing", + "wifi_slot": {"LED": 2}, + "wifiduino": { + "D0": 3, + "D1": 1, + "D2": 2, + "D3": 0, + "D4": 4, + "D5": 5, + "D6": 16, + "D7": 14, + "D8": 12, + "D9": 13, + "D10": 15, + "D11": 13, + "D12": 12, + "D13": 14, + }, + "wifinfo": { + "LED": 12, + "D0": 16, + "D1": 5, + "D2": 4, + "D3": 0, + "D4": 2, + "D5": 14, + "D6": 12, + "D7": 13, + "D8": 15, + "D9": 3, + "D10": 1, + }, + "wio_link": {"LED": 2, "GROVE": 15, "D0": 14, "D1": 12, "D2": 13, "BUTTON": 0}, + "wio_node": {"LED": 2, "GROVE": 15, "D0": 3, "D1": 5, "BUTTON": 0}, + "xinabox_cw01": {"SDA": 2, "SCL": 14, "LED": 5, "LED_RED": 12, "LED_GREEN": 13}, } FLASH_SIZE_1_MB = 2 ** 20 @@ -64,196 +160,711 @@ FLASH_SIZE_4_MB = 4 * FLASH_SIZE_1_MB FLASH_SIZE_16_MB = 16 * FLASH_SIZE_1_MB ESP8266_FLASH_SIZES = { - 'd1': FLASH_SIZE_4_MB, - 'd1_mini': FLASH_SIZE_4_MB, - 'd1_mini_lite': FLASH_SIZE_1_MB, - 'd1_mini_pro': FLASH_SIZE_16_MB, - 'esp01': FLASH_SIZE_512_KB, - 'esp01_1m': FLASH_SIZE_1_MB, - 'esp07': FLASH_SIZE_4_MB, - 'esp12e': FLASH_SIZE_4_MB, - 'esp210': FLASH_SIZE_4_MB, - 'esp8285': FLASH_SIZE_1_MB, - 'esp_wroom_02': FLASH_SIZE_2_MB, - 'espduino': FLASH_SIZE_4_MB, - 'espectro': FLASH_SIZE_4_MB, - 'espino': FLASH_SIZE_4_MB, - 'espinotee': FLASH_SIZE_4_MB, - 'espresso_lite_v1': FLASH_SIZE_4_MB, - 'espresso_lite_v2': FLASH_SIZE_4_MB, - 'gen4iod': FLASH_SIZE_512_KB, - 'heltec_wifi_kit_8': FLASH_SIZE_4_MB, - 'huzzah': FLASH_SIZE_4_MB, - 'inventone': FLASH_SIZE_4_MB, - 'modwifi': FLASH_SIZE_2_MB, - 'nodemcu': FLASH_SIZE_4_MB, - 'nodemcuv2': FLASH_SIZE_4_MB, - 'oak': FLASH_SIZE_4_MB, - 'phoenix_v1': FLASH_SIZE_4_MB, - 'phoenix_v2': FLASH_SIZE_4_MB, - 'sparkfunBlynk': FLASH_SIZE_4_MB, - 'thing': FLASH_SIZE_512_KB, - 'thingdev': FLASH_SIZE_512_KB, - 'wifi_slot': FLASH_SIZE_1_MB, - 'wifiduino': FLASH_SIZE_4_MB, - 'wifinfo': FLASH_SIZE_1_MB, - 'wio_link': FLASH_SIZE_4_MB, - 'wio_node': FLASH_SIZE_4_MB, - 'xinabox_cw01': FLASH_SIZE_4_MB, + "d1": FLASH_SIZE_4_MB, + "d1_mini": FLASH_SIZE_4_MB, + "d1_mini_lite": FLASH_SIZE_1_MB, + "d1_mini_pro": FLASH_SIZE_16_MB, + "esp01": FLASH_SIZE_512_KB, + "esp01_1m": FLASH_SIZE_1_MB, + "esp07": FLASH_SIZE_4_MB, + "esp12e": FLASH_SIZE_4_MB, + "esp210": FLASH_SIZE_4_MB, + "esp8285": FLASH_SIZE_1_MB, + "esp_wroom_02": FLASH_SIZE_2_MB, + "espduino": FLASH_SIZE_4_MB, + "espectro": FLASH_SIZE_4_MB, + "espino": FLASH_SIZE_4_MB, + "espinotee": FLASH_SIZE_4_MB, + "espresso_lite_v1": FLASH_SIZE_4_MB, + "espresso_lite_v2": FLASH_SIZE_4_MB, + "gen4iod": FLASH_SIZE_512_KB, + "heltec_wifi_kit_8": FLASH_SIZE_4_MB, + "huzzah": FLASH_SIZE_4_MB, + "inventone": FLASH_SIZE_4_MB, + "modwifi": FLASH_SIZE_2_MB, + "nodemcu": FLASH_SIZE_4_MB, + "nodemcuv2": FLASH_SIZE_4_MB, + "oak": FLASH_SIZE_4_MB, + "phoenix_v1": FLASH_SIZE_4_MB, + "phoenix_v2": FLASH_SIZE_4_MB, + "sparkfunBlynk": FLASH_SIZE_4_MB, + "thing": FLASH_SIZE_512_KB, + "thingdev": FLASH_SIZE_512_KB, + "wifi_slot": FLASH_SIZE_1_MB, + "wifiduino": FLASH_SIZE_4_MB, + "wifinfo": FLASH_SIZE_1_MB, + "wio_link": FLASH_SIZE_4_MB, + "wio_node": FLASH_SIZE_4_MB, + "xinabox_cw01": FLASH_SIZE_4_MB, } ESP8266_LD_SCRIPTS = { - FLASH_SIZE_512_KB: ('eagle.flash.512k0.ld', 'eagle.flash.512k.ld'), - FLASH_SIZE_1_MB: ('eagle.flash.1m0.ld', 'eagle.flash.1m.ld'), - FLASH_SIZE_2_MB: ('eagle.flash.2m.ld', 'eagle.flash.2m.ld'), - FLASH_SIZE_4_MB: ('eagle.flash.4m.ld', 'eagle.flash.4m.ld'), - FLASH_SIZE_16_MB: ('eagle.flash.16m.ld', 'eagle.flash.16m14m.ld'), + FLASH_SIZE_512_KB: ("eagle.flash.512k0.ld", "eagle.flash.512k.ld"), + FLASH_SIZE_1_MB: ("eagle.flash.1m0.ld", "eagle.flash.1m.ld"), + FLASH_SIZE_2_MB: ("eagle.flash.2m.ld", "eagle.flash.2m.ld"), + FLASH_SIZE_4_MB: ("eagle.flash.4m.ld", "eagle.flash.4m.ld"), + FLASH_SIZE_16_MB: ("eagle.flash.16m.ld", "eagle.flash.16m14m.ld"), } ESP32_BASE_PINS = { - 'TX': 1, 'RX': 3, 'SDA': 21, 'SCL': 22, 'SS': 5, 'MOSI': 23, 'MISO': 19, 'SCK': 18, 'A0': 36, - 'A3': 39, 'A4': 32, 'A5': 33, 'A6': 34, 'A7': 35, 'A10': 4, 'A11': 0, 'A12': 2, 'A13': 15, - 'A14': 13, 'A15': 12, 'A16': 14, 'A17': 27, 'A18': 25, 'A19': 26, 'T0': 4, 'T1': 0, 'T2': 2, - 'T3': 15, 'T4': 13, 'T5': 12, 'T6': 14, 'T7': 27, 'T8': 33, 'T9': 32, 'DAC1': 25, 'DAC2': 26, - 'SVP': 36, 'SVN': 39, + "TX": 1, + "RX": 3, + "SDA": 21, + "SCL": 22, + "SS": 5, + "MOSI": 23, + "MISO": 19, + "SCK": 18, + "A0": 36, + "A3": 39, + "A4": 32, + "A5": 33, + "A6": 34, + "A7": 35, + "A10": 4, + "A11": 0, + "A12": 2, + "A13": 15, + "A14": 13, + "A15": 12, + "A16": 14, + "A17": 27, + "A18": 25, + "A19": 26, + "T0": 4, + "T1": 0, + "T2": 2, + "T3": 15, + "T4": 13, + "T5": 12, + "T6": 14, + "T7": 27, + "T8": 33, + "T9": 32, + "DAC1": 25, + "DAC2": 26, + "SVP": 36, + "SVN": 39, } ESP32_BOARD_PINS = { - 'alksesp32': {'A0': 32, 'A1': 33, 'A2': 25, 'A3': 26, 'A4': 27, 'A5': 14, 'A6': 12, 'A7': 15, - 'D0': 40, 'D1': 41, 'D10': 19, 'D11': 21, 'D12': 22, 'D13': 23, 'D2': 15, - 'D3': 2, 'D4': 0, 'D5': 4, 'D6': 16, 'D7': 17, 'D8': 5, 'D9': 18, 'DHT_PIN': 26, - 'LED': 23, 'L_B': 5, 'L_G': 17, 'L_R': 22, 'L_RGB_B': 16, 'L_RGB_G': 21, - 'L_RGB_R': 4, 'L_Y': 23, 'MISO': 22, 'MOSI': 21, 'PHOTO': 25, 'PIEZO1': 19, - 'PIEZO2': 18, 'POT1': 32, 'POT2': 33, 'S1': 4, 'S2': 16, 'S3': 18, 'S4': 19, - 'S5': 21, 'SCK': 23, 'SCL': 14, 'SDA': 27, 'SS': 19, 'SW1': 15, 'SW2': 2, - 'SW3': 0}, - 'bpi-bit': {'BUTTON_A': 35, 'BUTTON_B': 27, 'BUZZER': 25, 'LIGHT_SENSOR1': 36, - 'LIGHT_SENSOR2': 39, 'MPU9250_INT': 0, 'P0': 25, 'P1': 32, 'P10': 26, 'P11': 27, - 'P12': 2, 'P13': 18, 'P14': 19, 'P15': 23, 'P16': 5, 'P19': 22, 'P2': 33, - 'P20': 21, 'P3': 13, 'P4': 15, 'P5': 35, 'P6': 12, 'P7': 14, 'P8': 16, 'P9': 17, - 'RGB_LED': 4, 'TEMPERATURE_SENSOR': 34}, - 'd-duino-32': {'D1': 5, 'D10': 1, 'D2': 4, 'D3': 0, 'D4': 2, 'D5': 14, 'D6': 12, 'D7': 13, - 'D8': 15, 'D9': 3, 'MISO': 12, 'MOSI': 13, 'SCK': 14, 'SCL': 4, 'SDA': 5, - 'SS': 15}, - 'esp-wrover-kit': {}, - 'esp32-devkitlipo': {}, - 'esp32-evb': {'BUTTON': 34, 'MISO': 15, 'MOSI': 2, 'SCK': 14, 'SCL': 16, 'SDA': 13, 'SS': 17}, - 'esp32-gateway': {'BUTTON': 34, 'LED': 33, 'SCL': 16, 'SDA': 32}, - 'esp32-poe-iso': {'BUTTON': 34, 'MISO': 15, 'MOSI': 2, 'SCK': 14, 'SCL': 16, 'SDA': 13}, - 'esp32-poe': {'BUTTON': 34, 'MISO': 15, 'MOSI': 2, 'SCK': 14, 'SCL': 16, 'SDA': 13}, - 'esp32-pro': {'BUTTON': 34, 'MISO': 15, 'MOSI': 2, 'SCK': 14, 'SCL': 16, 'SDA': 13, 'SS': 17}, - 'esp320': {'LED': 5, 'MISO': 12, 'MOSI': 13, 'SCK': 14, 'SCL': 14, 'SDA': 2, 'SS': 15}, - 'esp32cam': {}, - 'esp32dev': {}, - 'esp32doit-devkit-v1': {'LED': 2}, - 'esp32thing': {'BUTTON': 0, 'LED': 5, 'SS': 2}, - 'esp32vn-iot-uno': {}, - 'espea32': {'BUTTON': 0, 'LED': 5}, - 'espectro32': {'LED': 15, 'SD_SS': 33}, - 'espino32': {'BUTTON': 0, 'LED': 16}, - 'featheresp32': {'A0': 26, 'A1': 25, 'A10': 27, 'A11': 12, 'A12': 13, 'A13': 35, 'A2': 34, - 'A4': 36, 'A5': 4, 'A6': 14, 'A7': 32, 'A8': 15, 'A9': 33, 'Ax': 2, - 'LED': 13, 'MOSI': 18, 'RX': 16, 'SCK': 5, 'SDA': 23, 'SS': 33, 'TX': 17}, - 'firebeetle32': {'LED': 2}, - 'fm-devkit': {'D0': 34, 'D1': 35, 'D10': 0, 'D2': 32, 'D3': 33, 'D4': 27, 'D5': 14, 'D6': 12, - 'D7': 13, 'D8': 15, 'D9': 23, 'I2S_DOUT': 22, 'I2S_LRCLK': 25, 'I2S_MCLK': 2, - 'I2S_SCLK': 26, 'LED': 5, 'SCL': 17, 'SDA': 16, 'SW1': 4, 'SW2': 18, 'SW3': 19, - 'SW4': 21}, - 'frogboard': {}, - 'heltec_wifi_kit_32': {'A1': 37, 'A2': 38, 'BUTTON': 0, 'LED': 25, 'RST_OLED': 16, - 'SCL_OLED': 15, 'SDA_OLED': 4, 'Vext': 21}, - 'heltec_wifi_lora_32': {'BUTTON': 0, 'DIO0': 26, 'DIO1': 33, 'DIO2': 32, 'LED': 25, - 'MOSI': 27, 'RST_LoRa': 14, 'RST_OLED': 16, 'SCK': 5, 'SCL_OLED': 15, - 'SDA_OLED': 4, 'SS': 18, 'Vext': 21}, - 'heltec_wifi_lora_32_V2': {'BUTTON': 0, 'DIO0': 26, 'DIO1': 35, 'DIO2': 34, 'LED': 25, - 'MOSI': 27, 'RST_LoRa': 14, 'RST_OLED': 16, 'SCK': 5, - 'SCL_OLED': 15, 'SDA_OLED': 4, 'SS': 18, 'Vext': 21}, - 'heltec_wireless_stick': {'BUTTON': 0, 'DIO0': 26, 'DIO1': 35, 'DIO2': 34, 'LED': 25, - 'MOSI': 27, 'RST_LoRa': 14, 'RST_OLED': 16, 'SCK': 5, - 'SCL_OLED': 15, 'SDA_OLED': 4, 'SS': 18, 'Vext': 21}, - 'hornbill32dev': {'BUTTON': 0, 'LED': 13}, - 'hornbill32minima': {'SS': 2}, - 'intorobot': {'A1': 39, 'A2': 35, 'A3': 25, 'A4': 26, 'A5': 14, 'A6': 12, 'A7': 15, 'A8': 13, - 'A9': 2, 'BUTTON': 0, 'D0': 19, 'D1': 23, 'D2': 18, 'D3': 17, 'D4': 16, 'D5': 5, - 'D6': 4, 'LED': 4, 'MISO': 17, 'MOSI': 16, 'RGB_B_BUILTIN': 22, - 'RGB_G_BUILTIN': 21, 'RGB_R_BUILTIN': 27, 'SCL': 19, 'SDA': 23, 'T0': 19, - 'T1': 23, 'T2': 18, 'T3': 17, 'T4': 16, 'T5': 5, 'T6': 4}, - 'iotaap_magnolia': {}, - 'iotbusio': {}, - 'iotbusproteus': {}, - 'lolin32': {'LED': 5}, - 'lolin32-lite': {'LED': 22}, - 'lolin_d32': {'LED': 5, '_VBAT': 35}, - 'lolin_d32_pro': {'LED': 5, '_VBAT': 35}, - 'lopy': {'A1': 37, 'A2': 38, 'LED': 0, 'MISO': 37, 'MOSI': 22, 'SCK': 13, 'SCL': 13, - 'SDA': 12, 'SS': 17}, - 'lopy4': {'A1': 37, 'A2': 38, 'LED': 0, 'MISO': 37, 'MOSI': 22, 'SCK': 13, 'SCL': 13, - 'SDA': 12, 'SS': 18}, - 'm5stack-core-esp32': {'ADC1': 35, 'ADC2': 36, 'G0': 0, 'G1': 1, 'G12': 12, 'G13': 13, - 'G15': 15, 'G16': 16, 'G17': 17, 'G18': 18, 'G19': 19, 'G2': 2, - 'G21': 21, 'G22': 22, 'G23': 23, 'G25': 25, 'G26': 26, 'G3': 3, - 'G34': 34, 'G35': 35, 'G36': 36, 'G5': 5, 'RXD2': 16, 'TXD2': 17}, - 'm5stack-fire': {'ADC1': 35, 'ADC2': 36, 'G0': 0, 'G1': 1, 'G12': 12, 'G13': 13, 'G15': 15, - 'G16': 16, 'G17': 17, 'G18': 18, 'G19': 19, 'G2': 2, 'G21': 21, 'G22': 22, - 'G23': 23, 'G25': 25, 'G26': 26, 'G3': 3, 'G34': 34, 'G35': 35, 'G36': 36, - 'G5': 5}, - 'm5stack-grey': {'ADC1': 35, 'ADC2': 36, 'G0': 0, 'G1': 1, 'G12': 12, 'G13': 13, 'G15': 15, - 'G16': 16, 'G17': 17, 'G18': 18, 'G19': 19, 'G2': 2, 'G21': 21, 'G22': 22, - 'G23': 23, 'G25': 25, 'G26': 26, 'G3': 3, 'G34': 34, 'G35': 35, 'G36': 36, - 'G5': 5, 'RXD2': 16, 'TXD2': 17}, - 'm5stick-c': {'ADC1': 35, 'ADC2': 36, 'G0': 0, 'G10': 10, 'G26': 26, 'G32': 32, 'G33': 33, - 'G36': 36, 'G37': 37, 'G39': 39, 'G9': 9, 'MISO': 36, 'MOSI': 15, 'SCK': 13, - 'SCL': 33, 'SDA': 32}, - 'magicbit': {'BLUE_LED': 17, 'BUZZER': 25, 'GREEN_LED': 16, 'LDR': 36, 'LED': 16, - 'LEFT_BUTTON': 35, 'MOTOR1A': 27, 'MOTOR1B': 18, 'MOTOR2A': 16, 'MOTOR2B': 17, - 'POT': 39, 'RED_LED': 27, 'RIGHT_PUTTON': 34, 'YELLOW_LED': 18}, - 'mhetesp32devkit': {'LED': 2}, - 'mhetesp32minikit': {'LED': 2}, - 'microduino-core-esp32': {'A0': 12, 'A1': 13, 'A10': 25, 'A11': 26, 'A12': 27, 'A13': 14, - 'A2': 15, 'A3': 4, 'A6': 38, 'A7': 37, 'A8': 32, 'A9': 33, 'D0': 3, - 'D1': 1, 'D10': 5, 'D11': 23, 'D12': 19, 'D13': 18, 'D14': 12, - 'D15': 13, 'D16': 15, 'D17': 4, 'D18': 22, 'D19': 21, 'D2': 16, - 'D20': 38, 'D21': 37, 'D3': 17, 'D4': 32, 'D5': 33, 'D6': 25, - 'D7': 26, 'D8': 27, 'D9': 14, 'SCL': 21, 'SCL1': 13, 'SDA': 22, - 'SDA1': 12}, - 'nano32': {'BUTTON': 0, 'LED': 16}, - 'nina_w10': {'D0': 3, 'D1': 1, 'D10': 5, 'D11': 19, 'D12': 23, 'D13': 18, 'D14': 13, - 'D15': 12, 'D16': 32, 'D17': 33, 'D18': 21, 'D19': 34, 'D2': 26, 'D20': 36, - 'D21': 39, 'D3': 25, 'D4': 35, 'D5': 27, 'D6': 22, 'D7': 0, 'D8': 15, 'D9': 14, - 'LED_BLUE': 21, 'LED_GREEN': 33, 'LED_RED': 23, 'SCL': 13, 'SDA': 12, 'SW1': 33, - 'SW2': 27}, - 'node32s': {}, - 'nodemcu-32s': {'BUTTON': 0, 'LED': 2}, - 'odroid_esp32': {'ADC1': 35, 'ADC2': 36, 'LED': 2, 'SCL': 4, 'SDA': 15, 'SS': 22}, - 'onehorse32dev': {'A1': 37, 'A2': 38, 'BUTTON': 0, 'LED': 5}, - 'oroca_edubot': {'A0': 34, 'A1': 39, 'A2': 36, 'A3': 33, 'D0': 4, 'D1': 16, 'D2': 17, - 'D3': 22, 'D4': 23, 'D5': 5, 'D6': 18, 'D7': 19, 'D8': 33, 'LED': 13, - 'MOSI': 18, 'RX': 16, 'SCK': 5, 'SDA': 23, 'SS': 2, 'TX': 17, 'VBAT': 35}, - 'pico32': {}, - 'pocket_32': {'LED': 16}, - 'pycom_gpy': {'A1': 37, 'A2': 38, 'LED': 0, 'MISO': 37, 'MOSI': 22, 'SCK': 13, 'SCL': 13, - 'SDA': 12, 'SS': 17}, - 'quantum': {}, - 'sparkfun_lora_gateway_1-channel': {'MISO': 12, 'MOSI': 13, 'SCK': 14, 'SS': 16}, - 'tinypico': {}, - 'ttgo-lora32-v1': {'A1': 37, 'A2': 38, 'BUTTON': 0, 'LED': 2, 'MOSI': 27, 'SCK': 5, 'SS': 18}, - 'ttgo-t-beam': {'BUTTON': 39, 'LED': 14, 'MOSI': 27, 'SCK': 5, 'SS': 18}, - 'ttgo-t-watch': {'BUTTON': 36, 'MISO': 2, 'MOSI': 15, 'SCK': 14, 'SS': 13}, - 'ttgo-t1': {'LED': 22, 'MISO': 2, 'MOSI': 15, 'SCK': 14, 'SCL': 23, 'SS': 13}, - 'ttgo-t7-v13-mini32': {'LED': 22}, - 'ttgo-t7-v14-mini32': {'LED': 19}, - 'turta_iot_node': {}, - 'vintlabs-devkit-v1': {'LED': 2, 'PWM0': 12, 'PWM1': 13, 'PWM2': 14, 'PWM3': 15, 'PWM4': 16, - 'PWM5': 17, 'PWM6': 18, 'PWM7': 19}, - 'wemos_d1_mini32': {'D0': 26, 'D1': 22, 'D2': 21, 'D3': 17, 'D4': 16, 'D5': 18, 'D6': 19, - 'D7': 23, 'D8': 5, 'LED': 2, 'RXD': 3, 'TXD': 1, '_VBAT': 35}, - 'wemosbat': {'LED': 16}, - 'wesp32': {'MISO': 32, 'SCL': 4, 'SDA': 15}, - 'widora-air': {'A1': 39, 'A2': 35, 'A3': 25, 'A4': 26, 'A5': 14, 'A6': 12, 'A7': 15, 'A8': 13, - 'A9': 2, 'BUTTON': 0, 'D0': 19, 'D1': 23, 'D2': 18, 'D3': 17, 'D4': 16, - 'D5': 5, 'D6': 4, 'LED': 25, 'MISO': 17, 'MOSI': 16, 'SCL': 19, 'SDA': 23, - 'T0': 19, 'T1': 23, 'T2': 18, 'T3': 17, 'T4': 16, 'T5': 5, 'T6': 4}, - 'xinabox_cw02': {'LED': 27}, + "alksesp32": { + "A0": 32, + "A1": 33, + "A2": 25, + "A3": 26, + "A4": 27, + "A5": 14, + "A6": 12, + "A7": 15, + "D0": 40, + "D1": 41, + "D10": 19, + "D11": 21, + "D12": 22, + "D13": 23, + "D2": 15, + "D3": 2, + "D4": 0, + "D5": 4, + "D6": 16, + "D7": 17, + "D8": 5, + "D9": 18, + "DHT_PIN": 26, + "LED": 23, + "L_B": 5, + "L_G": 17, + "L_R": 22, + "L_RGB_B": 16, + "L_RGB_G": 21, + "L_RGB_R": 4, + "L_Y": 23, + "MISO": 22, + "MOSI": 21, + "PHOTO": 25, + "PIEZO1": 19, + "PIEZO2": 18, + "POT1": 32, + "POT2": 33, + "S1": 4, + "S2": 16, + "S3": 18, + "S4": 19, + "S5": 21, + "SCK": 23, + "SCL": 14, + "SDA": 27, + "SS": 19, + "SW1": 15, + "SW2": 2, + "SW3": 0, + }, + "bpi-bit": { + "BUTTON_A": 35, + "BUTTON_B": 27, + "BUZZER": 25, + "LIGHT_SENSOR1": 36, + "LIGHT_SENSOR2": 39, + "MPU9250_INT": 0, + "P0": 25, + "P1": 32, + "P10": 26, + "P11": 27, + "P12": 2, + "P13": 18, + "P14": 19, + "P15": 23, + "P16": 5, + "P19": 22, + "P2": 33, + "P20": 21, + "P3": 13, + "P4": 15, + "P5": 35, + "P6": 12, + "P7": 14, + "P8": 16, + "P9": 17, + "RGB_LED": 4, + "TEMPERATURE_SENSOR": 34, + }, + "d-duino-32": { + "D1": 5, + "D10": 1, + "D2": 4, + "D3": 0, + "D4": 2, + "D5": 14, + "D6": 12, + "D7": 13, + "D8": 15, + "D9": 3, + "MISO": 12, + "MOSI": 13, + "SCK": 14, + "SCL": 4, + "SDA": 5, + "SS": 15, + }, + "esp-wrover-kit": {}, + "esp32-devkitlipo": {}, + "esp32-evb": { + "BUTTON": 34, + "MISO": 15, + "MOSI": 2, + "SCK": 14, + "SCL": 16, + "SDA": 13, + "SS": 17, + }, + "esp32-gateway": {"BUTTON": 34, "LED": 33, "SCL": 16, "SDA": 32}, + "esp32-poe-iso": { + "BUTTON": 34, + "MISO": 15, + "MOSI": 2, + "SCK": 14, + "SCL": 16, + "SDA": 13, + }, + "esp32-poe": {"BUTTON": 34, "MISO": 15, "MOSI": 2, "SCK": 14, "SCL": 16, "SDA": 13}, + "esp32-pro": { + "BUTTON": 34, + "MISO": 15, + "MOSI": 2, + "SCK": 14, + "SCL": 16, + "SDA": 13, + "SS": 17, + }, + "esp320": { + "LED": 5, + "MISO": 12, + "MOSI": 13, + "SCK": 14, + "SCL": 14, + "SDA": 2, + "SS": 15, + }, + "esp32cam": {}, + "esp32dev": {}, + "esp32doit-devkit-v1": {"LED": 2}, + "esp32thing": {"BUTTON": 0, "LED": 5, "SS": 2}, + "esp32vn-iot-uno": {}, + "espea32": {"BUTTON": 0, "LED": 5}, + "espectro32": {"LED": 15, "SD_SS": 33}, + "espino32": {"BUTTON": 0, "LED": 16}, + "featheresp32": { + "A0": 26, + "A1": 25, + "A10": 27, + "A11": 12, + "A12": 13, + "A13": 35, + "A2": 34, + "A4": 36, + "A5": 4, + "A6": 14, + "A7": 32, + "A8": 15, + "A9": 33, + "Ax": 2, + "LED": 13, + "MOSI": 18, + "RX": 16, + "SCK": 5, + "SDA": 23, + "SS": 33, + "TX": 17, + }, + "firebeetle32": {"LED": 2}, + "fm-devkit": { + "D0": 34, + "D1": 35, + "D10": 0, + "D2": 32, + "D3": 33, + "D4": 27, + "D5": 14, + "D6": 12, + "D7": 13, + "D8": 15, + "D9": 23, + "I2S_DOUT": 22, + "I2S_LRCLK": 25, + "I2S_MCLK": 2, + "I2S_SCLK": 26, + "LED": 5, + "SCL": 17, + "SDA": 16, + "SW1": 4, + "SW2": 18, + "SW3": 19, + "SW4": 21, + }, + "frogboard": {}, + "heltec_wifi_kit_32": { + "A1": 37, + "A2": 38, + "BUTTON": 0, + "LED": 25, + "RST_OLED": 16, + "SCL_OLED": 15, + "SDA_OLED": 4, + "Vext": 21, + }, + "heltec_wifi_lora_32": { + "BUTTON": 0, + "DIO0": 26, + "DIO1": 33, + "DIO2": 32, + "LED": 25, + "MOSI": 27, + "RST_LoRa": 14, + "RST_OLED": 16, + "SCK": 5, + "SCL_OLED": 15, + "SDA_OLED": 4, + "SS": 18, + "Vext": 21, + }, + "heltec_wifi_lora_32_V2": { + "BUTTON": 0, + "DIO0": 26, + "DIO1": 35, + "DIO2": 34, + "LED": 25, + "MOSI": 27, + "RST_LoRa": 14, + "RST_OLED": 16, + "SCK": 5, + "SCL_OLED": 15, + "SDA_OLED": 4, + "SS": 18, + "Vext": 21, + }, + "heltec_wireless_stick": { + "BUTTON": 0, + "DIO0": 26, + "DIO1": 35, + "DIO2": 34, + "LED": 25, + "MOSI": 27, + "RST_LoRa": 14, + "RST_OLED": 16, + "SCK": 5, + "SCL_OLED": 15, + "SDA_OLED": 4, + "SS": 18, + "Vext": 21, + }, + "hornbill32dev": {"BUTTON": 0, "LED": 13}, + "hornbill32minima": {"SS": 2}, + "intorobot": { + "A1": 39, + "A2": 35, + "A3": 25, + "A4": 26, + "A5": 14, + "A6": 12, + "A7": 15, + "A8": 13, + "A9": 2, + "BUTTON": 0, + "D0": 19, + "D1": 23, + "D2": 18, + "D3": 17, + "D4": 16, + "D5": 5, + "D6": 4, + "LED": 4, + "MISO": 17, + "MOSI": 16, + "RGB_B_BUILTIN": 22, + "RGB_G_BUILTIN": 21, + "RGB_R_BUILTIN": 27, + "SCL": 19, + "SDA": 23, + "T0": 19, + "T1": 23, + "T2": 18, + "T3": 17, + "T4": 16, + "T5": 5, + "T6": 4, + }, + "iotaap_magnolia": {}, + "iotbusio": {}, + "iotbusproteus": {}, + "lolin32": {"LED": 5}, + "lolin32-lite": {"LED": 22}, + "lolin_d32": {"LED": 5, "_VBAT": 35}, + "lolin_d32_pro": {"LED": 5, "_VBAT": 35}, + "lopy": { + "A1": 37, + "A2": 38, + "LED": 0, + "MISO": 37, + "MOSI": 22, + "SCK": 13, + "SCL": 13, + "SDA": 12, + "SS": 17, + }, + "lopy4": { + "A1": 37, + "A2": 38, + "LED": 0, + "MISO": 37, + "MOSI": 22, + "SCK": 13, + "SCL": 13, + "SDA": 12, + "SS": 18, + }, + "m5stack-core-esp32": { + "ADC1": 35, + "ADC2": 36, + "G0": 0, + "G1": 1, + "G12": 12, + "G13": 13, + "G15": 15, + "G16": 16, + "G17": 17, + "G18": 18, + "G19": 19, + "G2": 2, + "G21": 21, + "G22": 22, + "G23": 23, + "G25": 25, + "G26": 26, + "G3": 3, + "G34": 34, + "G35": 35, + "G36": 36, + "G5": 5, + "RXD2": 16, + "TXD2": 17, + }, + "m5stack-fire": { + "ADC1": 35, + "ADC2": 36, + "G0": 0, + "G1": 1, + "G12": 12, + "G13": 13, + "G15": 15, + "G16": 16, + "G17": 17, + "G18": 18, + "G19": 19, + "G2": 2, + "G21": 21, + "G22": 22, + "G23": 23, + "G25": 25, + "G26": 26, + "G3": 3, + "G34": 34, + "G35": 35, + "G36": 36, + "G5": 5, + }, + "m5stack-grey": { + "ADC1": 35, + "ADC2": 36, + "G0": 0, + "G1": 1, + "G12": 12, + "G13": 13, + "G15": 15, + "G16": 16, + "G17": 17, + "G18": 18, + "G19": 19, + "G2": 2, + "G21": 21, + "G22": 22, + "G23": 23, + "G25": 25, + "G26": 26, + "G3": 3, + "G34": 34, + "G35": 35, + "G36": 36, + "G5": 5, + "RXD2": 16, + "TXD2": 17, + }, + "m5stick-c": { + "ADC1": 35, + "ADC2": 36, + "G0": 0, + "G10": 10, + "G26": 26, + "G32": 32, + "G33": 33, + "G36": 36, + "G37": 37, + "G39": 39, + "G9": 9, + "MISO": 36, + "MOSI": 15, + "SCK": 13, + "SCL": 33, + "SDA": 32, + }, + "magicbit": { + "BLUE_LED": 17, + "BUZZER": 25, + "GREEN_LED": 16, + "LDR": 36, + "LED": 16, + "LEFT_BUTTON": 35, + "MOTOR1A": 27, + "MOTOR1B": 18, + "MOTOR2A": 16, + "MOTOR2B": 17, + "POT": 39, + "RED_LED": 27, + "RIGHT_PUTTON": 34, + "YELLOW_LED": 18, + }, + "mhetesp32devkit": {"LED": 2}, + "mhetesp32minikit": {"LED": 2}, + "microduino-core-esp32": { + "A0": 12, + "A1": 13, + "A10": 25, + "A11": 26, + "A12": 27, + "A13": 14, + "A2": 15, + "A3": 4, + "A6": 38, + "A7": 37, + "A8": 32, + "A9": 33, + "D0": 3, + "D1": 1, + "D10": 5, + "D11": 23, + "D12": 19, + "D13": 18, + "D14": 12, + "D15": 13, + "D16": 15, + "D17": 4, + "D18": 22, + "D19": 21, + "D2": 16, + "D20": 38, + "D21": 37, + "D3": 17, + "D4": 32, + "D5": 33, + "D6": 25, + "D7": 26, + "D8": 27, + "D9": 14, + "SCL": 21, + "SCL1": 13, + "SDA": 22, + "SDA1": 12, + }, + "nano32": {"BUTTON": 0, "LED": 16}, + "nina_w10": { + "D0": 3, + "D1": 1, + "D10": 5, + "D11": 19, + "D12": 23, + "D13": 18, + "D14": 13, + "D15": 12, + "D16": 32, + "D17": 33, + "D18": 21, + "D19": 34, + "D2": 26, + "D20": 36, + "D21": 39, + "D3": 25, + "D4": 35, + "D5": 27, + "D6": 22, + "D7": 0, + "D8": 15, + "D9": 14, + "LED_BLUE": 21, + "LED_GREEN": 33, + "LED_RED": 23, + "SCL": 13, + "SDA": 12, + "SW1": 33, + "SW2": 27, + }, + "node32s": {}, + "nodemcu-32s": {"BUTTON": 0, "LED": 2}, + "odroid_esp32": {"ADC1": 35, "ADC2": 36, "LED": 2, "SCL": 4, "SDA": 15, "SS": 22}, + "onehorse32dev": {"A1": 37, "A2": 38, "BUTTON": 0, "LED": 5}, + "oroca_edubot": { + "A0": 34, + "A1": 39, + "A2": 36, + "A3": 33, + "D0": 4, + "D1": 16, + "D2": 17, + "D3": 22, + "D4": 23, + "D5": 5, + "D6": 18, + "D7": 19, + "D8": 33, + "LED": 13, + "MOSI": 18, + "RX": 16, + "SCK": 5, + "SDA": 23, + "SS": 2, + "TX": 17, + "VBAT": 35, + }, + "pico32": {}, + "pocket_32": {"LED": 16}, + "pycom_gpy": { + "A1": 37, + "A2": 38, + "LED": 0, + "MISO": 37, + "MOSI": 22, + "SCK": 13, + "SCL": 13, + "SDA": 12, + "SS": 17, + }, + "quantum": {}, + "sparkfun_lora_gateway_1-channel": {"MISO": 12, "MOSI": 13, "SCK": 14, "SS": 16}, + "tinypico": {}, + "ttgo-lora32-v1": { + "A1": 37, + "A2": 38, + "BUTTON": 0, + "LED": 2, + "MOSI": 27, + "SCK": 5, + "SS": 18, + }, + "ttgo-t-beam": {"BUTTON": 39, "LED": 14, "MOSI": 27, "SCK": 5, "SS": 18}, + "ttgo-t-watch": {"BUTTON": 36, "MISO": 2, "MOSI": 15, "SCK": 14, "SS": 13}, + "ttgo-t1": {"LED": 22, "MISO": 2, "MOSI": 15, "SCK": 14, "SCL": 23, "SS": 13}, + "ttgo-t7-v13-mini32": {"LED": 22}, + "ttgo-t7-v14-mini32": {"LED": 19}, + "turta_iot_node": {}, + "vintlabs-devkit-v1": { + "LED": 2, + "PWM0": 12, + "PWM1": 13, + "PWM2": 14, + "PWM3": 15, + "PWM4": 16, + "PWM5": 17, + "PWM6": 18, + "PWM7": 19, + }, + "wemos_d1_mini32": { + "D0": 26, + "D1": 22, + "D2": 21, + "D3": 17, + "D4": 16, + "D5": 18, + "D6": 19, + "D7": 23, + "D8": 5, + "LED": 2, + "RXD": 3, + "TXD": 1, + "_VBAT": 35, + }, + "wemosbat": {"LED": 16}, + "wesp32": {"MISO": 32, "SCL": 4, "SDA": 15}, + "widora-air": { + "A1": 39, + "A2": 35, + "A3": 25, + "A4": 26, + "A5": 14, + "A6": 12, + "A7": 15, + "A8": 13, + "A9": 2, + "BUTTON": 0, + "D0": 19, + "D1": 23, + "D2": 18, + "D3": 17, + "D4": 16, + "D5": 5, + "D6": 4, + "LED": 25, + "MISO": 17, + "MOSI": 16, + "SCL": 19, + "SDA": 23, + "T0": 19, + "T1": 23, + "T2": 18, + "T3": 17, + "T4": 16, + "T5": 5, + "T6": 4, + }, + "xinabox_cw02": {"LED": 27}, } @@ -282,24 +893,26 @@ def _lookup_pin(value): def _translate_pin(value): if isinstance(value, dict) or value is None: - raise cv.Invalid("This variable only supports pin numbers, not full pin schemas " - "(with inverted and mode).") + raise cv.Invalid( + "This variable only supports pin numbers, not full pin schemas " + "(with inverted and mode)." + ) if isinstance(value, int): return value try: return int(value) except ValueError: pass - if value.startswith('GPIO'): - return cv.Coerce(int)(value[len('GPIO'):].strip()) + if value.startswith("GPIO"): + return cv.Coerce(int)(value[len("GPIO") :].strip()) return _lookup_pin(value) _ESP_SDIO_PINS = { - 6: 'Flash Clock', - 7: 'Flash Data 0', - 8: 'Flash Data 1', - 11: 'Flash Command', + 6: "Flash Clock", + 7: "Flash Data 0", + 8: "Flash Data 1", + 11: "Flash Command", } @@ -309,11 +922,16 @@ def validate_gpio_pin(value): if value < 0 or value > 39: raise cv.Invalid(f"ESP32: Invalid pin number: {value}") if value in _ESP_SDIO_PINS: - raise cv.Invalid("This pin cannot be used on ESP32s and is already used by " - "the flash interface (function: {})".format(_ESP_SDIO_PINS[value])) + raise cv.Invalid( + "This pin cannot be used on ESP32s and is already used by " + "the flash interface (function: {})".format(_ESP_SDIO_PINS[value]) + ) if 9 <= value <= 10: - _LOGGER.warning("ESP32: Pin %s (9-10) might already be used by the " - "flash interface in QUAD IO flash mode.", value) + _LOGGER.warning( + "ESP32: Pin %s (9-10) might already be used by the " + "flash interface in QUAD IO flash mode.", + value, + ) if value in (20, 24, 28, 29, 30, 31): # These pins are not exposed in GPIO mux (reason unknown) # but they're missing from IO_MUX list in datasheet @@ -323,11 +941,16 @@ def validate_gpio_pin(value): if value < 0 or value > 17: raise cv.Invalid(f"ESP8266: Invalid pin number: {value}") if value in _ESP_SDIO_PINS: - raise cv.Invalid("This pin cannot be used on ESP8266s and is already used by " - "the flash interface (function: {})".format(_ESP_SDIO_PINS[value])) + raise cv.Invalid( + "This pin cannot be used on ESP8266s and is already used by " + "the flash interface (function: {})".format(_ESP_SDIO_PINS[value]) + ) if 9 <= value <= 10: - _LOGGER.warning("ESP8266: Pin %s (9-10) might already be used by the " - "flash interface in QUAD IO flash mode.", value) + _LOGGER.warning( + "ESP8266: Pin %s (9-10) might already be used by the " + "flash interface in QUAD IO flash mode.", + value, + ) return value raise NotImplementedError @@ -345,8 +968,10 @@ def input_pullup_pin(value): return output_pin(value) if CORE.is_esp8266: if value == 0: - raise cv.Invalid("GPIO Pin 0 does not support pullup pin mode. " - "Please choose another pin.") + raise cv.Invalid( + "GPIO Pin 0 does not support pullup pin mode. " + "Please choose another pin." + ) return value raise NotImplementedError @@ -355,8 +980,10 @@ def output_pin(value): value = validate_gpio_pin(value) if CORE.is_esp32: if 34 <= value <= 39: - raise cv.Invalid("ESP32: GPIO{} (34-39) can only be used as an " - "input pin.".format(value)) + raise cv.Invalid( + "ESP32: GPIO{} (34-39) can only be used as an " + "input pin.".format(value) + ) return value if CORE.is_esp8266: if value == 17: @@ -381,15 +1008,37 @@ def analog_pin(value): input_output_pin = cv.All(input_pin, output_pin) PIN_MODES_ESP8266 = [ - 'INPUT', 'OUTPUT', 'INPUT_PULLUP', 'OUTPUT_OPEN_DRAIN', 'SPECIAL', 'FUNCTION_1', - 'FUNCTION_2', 'FUNCTION_3', 'FUNCTION_4', - 'FUNCTION_0', 'WAKEUP_PULLUP', 'WAKEUP_PULLDOWN', 'INPUT_PULLDOWN_16', + "INPUT", + "OUTPUT", + "INPUT_PULLUP", + "OUTPUT_OPEN_DRAIN", + "SPECIAL", + "FUNCTION_1", + "FUNCTION_2", + "FUNCTION_3", + "FUNCTION_4", + "FUNCTION_0", + "WAKEUP_PULLUP", + "WAKEUP_PULLDOWN", + "INPUT_PULLDOWN_16", ] PIN_MODES_ESP32 = [ - 'INPUT', 'OUTPUT', 'INPUT_PULLUP', 'OUTPUT_OPEN_DRAIN', 'SPECIAL', 'FUNCTION_1', - 'FUNCTION_2', 'FUNCTION_3', 'FUNCTION_4', - 'PULLUP', 'PULLDOWN', 'INPUT_PULLDOWN', 'OPEN_DRAIN', 'FUNCTION_5', - 'FUNCTION_6', 'ANALOG', + "INPUT", + "OUTPUT", + "INPUT_PULLUP", + "OUTPUT_OPEN_DRAIN", + "SPECIAL", + "FUNCTION_1", + "FUNCTION_2", + "FUNCTION_3", + "FUNCTION_4", + "PULLUP", + "PULLDOWN", + "INPUT_PULLDOWN", + "OPEN_DRAIN", + "FUNCTION_5", + "FUNCTION_6", + "ANALOG", ] @@ -401,28 +1050,36 @@ def pin_mode(value): raise NotImplementedError -GPIO_FULL_OUTPUT_PIN_SCHEMA = cv.Schema({ - cv.Required(CONF_NUMBER): output_pin, - cv.Optional(CONF_MODE, default='OUTPUT'): pin_mode, - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) +GPIO_FULL_OUTPUT_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_NUMBER): output_pin, + cv.Optional(CONF_MODE, default="OUTPUT"): pin_mode, + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) -GPIO_FULL_INPUT_PIN_SCHEMA = cv.Schema({ - cv.Required(CONF_NUMBER): input_pin, - cv.Optional(CONF_MODE, default='INPUT'): pin_mode, - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) +GPIO_FULL_INPUT_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_NUMBER): input_pin, + cv.Optional(CONF_MODE, default="INPUT"): pin_mode, + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) -GPIO_FULL_INPUT_PULLUP_PIN_SCHEMA = cv.Schema({ - cv.Required(CONF_NUMBER): input_pin, - cv.Optional(CONF_MODE, default='INPUT_PULLUP'): pin_mode, - cv.Optional(CONF_INVERTED, default=False): cv.boolean, -}) +GPIO_FULL_INPUT_PULLUP_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_NUMBER): input_pin, + cv.Optional(CONF_MODE, default="INPUT_PULLUP"): pin_mode, + cv.Optional(CONF_INVERTED, default=False): cv.boolean, + } +) -GPIO_FULL_ANALOG_PIN_SCHEMA = cv.Schema({ - cv.Required(CONF_NUMBER): analog_pin, - cv.Optional(CONF_MODE, default='INPUT'): pin_mode, -}) +GPIO_FULL_ANALOG_PIN_SCHEMA = cv.Schema( + { + cv.Required(CONF_NUMBER): analog_pin, + cv.Optional(CONF_MODE, default="INPUT"): pin_mode, + } +) def shorthand_output_pin(value): @@ -437,10 +1094,12 @@ def shorthand_input_pin(value): def shorthand_input_pullup_pin(value): value = input_pullup_pin(value) - return GPIO_FULL_INPUT_PIN_SCHEMA({ - CONF_NUMBER: value, - CONF_MODE: 'INPUT_PULLUP', - }) + return GPIO_FULL_INPUT_PIN_SCHEMA( + { + CONF_NUMBER: value, + CONF_MODE: "INPUT_PULLUP", + } + ) def shorthand_analog_pin(value): @@ -451,8 +1110,10 @@ def shorthand_analog_pin(value): def validate_has_interrupt(value): if CORE.is_esp8266: if value[CONF_NUMBER] >= 16: - raise cv.Invalid("Pins GPIO16 and GPIO17 do not support interrupts and cannot be used " - "here, got {}".format(value[CONF_NUMBER])) + raise cv.Invalid( + "Pins GPIO16 and GPIO17 do not support interrupts and cannot be used " + "here, got {}".format(value[CONF_NUMBER]) + ) return value diff --git a/esphome/platformio_api.py b/esphome/platformio_api.py index 1cda141a5..87ca12c9a 100644 --- a/esphome/platformio_api.py +++ b/esphome/platformio_api.py @@ -24,6 +24,7 @@ def patch_structhash(): def patched_clean_build_dir(build_dir, *args): from platformio import fs from platformio.project.helpers import get_project_dir + platformio_ini = join(get_project_dir(), "platformio.ini") # if project's config is modified @@ -38,54 +39,59 @@ def patch_structhash(): command.clean_build_dir = patched_clean_build_dir -IGNORE_LIB_WARNINGS = r'(?:' + '|'.join(['Hash', 'Update']) + r')' +IGNORE_LIB_WARNINGS = r"(?:" + "|".join(["Hash", "Update"]) + r")" FILTER_PLATFORMIO_LINES = [ - r'Verbose mode can be enabled via `-v, --verbose` option.*', - r'CONFIGURATION: https://docs.platformio.org/.*', - r'PLATFORM: .*', - r'DEBUG: Current.*', - r'PACKAGES: .*', - r'LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf.*', - r'LDF Modes: Finder ~ chain, Compatibility ~ soft.*', - r'Looking for ' + IGNORE_LIB_WARNINGS + r' library in registry', - r"Warning! Library `.*'" + IGNORE_LIB_WARNINGS + - r".*` has not been found in PlatformIO Registry.", - r"You can ignore this message, if `.*" + IGNORE_LIB_WARNINGS + r".*` is a built-in library.*", - r'Scanning dependencies...', + r"Verbose mode can be enabled via `-v, --verbose` option.*", + r"CONFIGURATION: https://docs.platformio.org/.*", + r"PLATFORM: .*", + r"DEBUG: Current.*", + r"PACKAGES: .*", + r"LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf.*", + r"LDF Modes: Finder ~ chain, Compatibility ~ soft.*", + r"Looking for " + IGNORE_LIB_WARNINGS + r" library in registry", + r"Warning! Library `.*'" + + IGNORE_LIB_WARNINGS + + r".*` has not been found in PlatformIO Registry.", + r"You can ignore this message, if `.*" + + IGNORE_LIB_WARNINGS + + r".*` is a built-in library.*", + r"Scanning dependencies...", r"Found \d+ compatible libraries", - r'Memory Usage -> http://bit.ly/pio-memory-usage', - r'esptool.py v.*', + r"Memory Usage -> http://bit.ly/pio-memory-usage", + r"esptool.py v.*", r"Found: https://platformio.org/lib/show/.*", r"Using cache: .*", - r'Installing dependencies', - r'.* @ .* is already installed', - r'Building in .* mode', - r'Advanced Memory Usage is available via .*', + r"Installing dependencies", + r".* @ .* is already installed", + r"Building in .* mode", + r"Advanced Memory Usage is available via .*", ] def run_platformio_cli(*args, **kwargs) -> Union[str, int]: os.environ["PLATFORMIO_FORCE_COLOR"] = "true" os.environ["PLATFORMIO_BUILD_DIR"] = os.path.abspath(CORE.relative_pioenvs_path()) - os.environ["PLATFORMIO_LIBDEPS_DIR"] = os.path.abspath(CORE.relative_piolibdeps_path()) - cmd = ['platformio'] + list(args) + os.environ["PLATFORMIO_LIBDEPS_DIR"] = os.path.abspath( + CORE.relative_piolibdeps_path() + ) + cmd = ["platformio"] + list(args) if not CORE.verbose: - kwargs['filter_lines'] = FILTER_PLATFORMIO_LINES + kwargs["filter_lines"] = FILTER_PLATFORMIO_LINES - if os.environ.get('ESPHOME_USE_SUBPROCESS') is not None: + if os.environ.get("ESPHOME_USE_SUBPROCESS") is not None: return run_external_process(*cmd, **kwargs) import platformio.__main__ + patch_structhash() - return run_external_command(platformio.__main__.main, - *cmd, **kwargs) + return run_external_command(platformio.__main__.main, *cmd, **kwargs) def run_platformio_cli_run(config, verbose, *args, **kwargs) -> Union[str, int]: - command = ['run', '-d', CORE.build_path] + command = ["run", "-d", CORE.build_path] if verbose: - command += ['-v'] + command += ["-v"] command += list(args) return run_platformio_cli(*command, **kwargs) @@ -95,11 +101,13 @@ def run_compile(config, verbose): def run_upload(config, verbose, port): - return run_platformio_cli_run(config, verbose, '-t', 'upload', '--upload-port', port) + return run_platformio_cli_run( + config, verbose, "-t", "upload", "--upload-port", port + ) def run_idedata(config): - args = ['-t', 'idedata'] + args = ["-t", "idedata"] stdout = run_platformio_cli_run(config, False, *args, capture_stdout=True) match = re.search(r'{\s*".*}', stdout) if match is None: @@ -129,10 +137,10 @@ ESP8266_EXCEPTION_CODES = { 0: "Illegal instruction (Is the flash damaged?)", 1: "SYSCALL instruction", 2: "InstructionFetchError: Processor internal physical address or data error during " - "instruction fetch", + "instruction fetch", 3: "LoadStoreError: Processor internal physical address or data error during load or store", 4: "Level1Interrupt: Level-1 interrupt as indicated by set level-1 bits in the INTERRUPT " - "register", + "register", 5: "Alloca: MOVSP instruction, if caller's registers are not in the register file", 6: "Integer Divide By Zero", 7: "reserved", @@ -147,17 +155,17 @@ ESP8266_EXCEPTION_CODES = { 16: "InstTLBMiss: Error during Instruction TLB refill", 17: "InstTLBMultiHit: Multiple instruction TLB entries matched", 18: "InstFetchPrivilege: An instruction fetch referenced a virtual address at a ring level " - "less than CRING", + "less than CRING", 19: "reserved", 20: "InstFetchProhibited: An instruction fetch referenced a page mapped with an attribute " - "that does not permit instruction fetch", + "that does not permit instruction fetch", 21: "reserved", 22: "reserved", 23: "reserved", 24: "LoadStoreTLBMiss: Error during TLB refill for a load or store", 25: "LoadStoreTLBMultiHit: Multiple TLB entries matched for a load or store", 26: "LoadStorePrivilege: A load or store referenced a virtual address at a ring level less " - "than ", + "than ", 27: "reserved", 28: "Access to invalid address: LOAD (wild pointer?)", 29: "Access to invalid address: STORE (wild pointer?)", @@ -169,7 +177,7 @@ def _decode_pc(config, addr): if not idedata.addr2line_path or not idedata.firmware_elf_path: _LOGGER.debug("decode_pc no addr2line") return - command = [idedata.addr2line_path, '-pfiaC', '-e', idedata.firmware_elf_path, addr] + command = [idedata.addr2line_path, "-pfiaC", "-e", idedata.firmware_elf_path, addr] try: translation = subprocess.check_output(command).decode().strip() except Exception: # pylint: disable=broad-except @@ -179,7 +187,7 @@ def _decode_pc(config, addr): if "?? ??:0" in translation: # Nothing useful return - translation = translation.replace(' at ??:?', '').replace(':?', '') + translation = translation.replace(" at ??:?", "").replace(":?", "") _LOGGER.warning("Decoded %s", translation) @@ -189,15 +197,19 @@ def _parse_register(config, regex, line): _decode_pc(config, match.group(1)) -STACKTRACE_ESP8266_EXCEPTION_TYPE_RE = re.compile(r'[eE]xception \((\d+)\):') -STACKTRACE_ESP8266_PC_RE = re.compile(r'epc1=0x(4[0-9a-fA-F]{7})') -STACKTRACE_ESP8266_EXCVADDR_RE = re.compile(r'excvaddr=0x(4[0-9a-fA-F]{7})') -STACKTRACE_ESP32_PC_RE = re.compile(r'PC\s*:\s*(?:0x)?(4[0-9a-fA-F]{7})') -STACKTRACE_ESP32_EXCVADDR_RE = re.compile(r'EXCVADDR\s*:\s*(?:0x)?(4[0-9a-fA-F]{7})') -STACKTRACE_BAD_ALLOC_RE = re.compile(r'^last failed alloc call: (4[0-9a-fA-F]{7})\((\d+)\)$') -STACKTRACE_ESP32_BACKTRACE_RE = re.compile(r'Backtrace:(?:\s+0x[0-9a-fA-F]{8}:0x[0-9a-fA-F]{8})+') -STACKTRACE_ESP32_BACKTRACE_PC_RE = re.compile(r'4[0-9a-f]{7}') -STACKTRACE_ESP8266_BACKTRACE_PC_RE = re.compile(r'4[0-9a-f]{7}') +STACKTRACE_ESP8266_EXCEPTION_TYPE_RE = re.compile(r"[eE]xception \((\d+)\):") +STACKTRACE_ESP8266_PC_RE = re.compile(r"epc1=0x(4[0-9a-fA-F]{7})") +STACKTRACE_ESP8266_EXCVADDR_RE = re.compile(r"excvaddr=0x(4[0-9a-fA-F]{7})") +STACKTRACE_ESP32_PC_RE = re.compile(r"PC\s*:\s*(?:0x)?(4[0-9a-fA-F]{7})") +STACKTRACE_ESP32_EXCVADDR_RE = re.compile(r"EXCVADDR\s*:\s*(?:0x)?(4[0-9a-fA-F]{7})") +STACKTRACE_BAD_ALLOC_RE = re.compile( + r"^last failed alloc call: (4[0-9a-fA-F]{7})\((\d+)\)$" +) +STACKTRACE_ESP32_BACKTRACE_RE = re.compile( + r"Backtrace:(?:\s+0x[0-9a-fA-F]{8}:0x[0-9a-fA-F]{8})+" +) +STACKTRACE_ESP32_BACKTRACE_PC_RE = re.compile(r"4[0-9a-f]{7}") +STACKTRACE_ESP8266_BACKTRACE_PC_RE = re.compile(r"4[0-9a-f]{7}") def process_stacktrace(config, line, backtrace_state): @@ -206,7 +218,9 @@ def process_stacktrace(config, line, backtrace_state): match = re.match(STACKTRACE_ESP8266_EXCEPTION_TYPE_RE, line) if match is not None: code = int(match.group(1)) - _LOGGER.warning("Exception type: %s", ESP8266_EXCEPTION_CODES.get(code, 'unknown')) + _LOGGER.warning( + "Exception type: %s", ESP8266_EXCEPTION_CODES.get(code, "unknown") + ) # ESP8266 PC/EXCVADDR _parse_register(config, STACKTRACE_ESP8266_PC_RE, line) @@ -218,8 +232,9 @@ def process_stacktrace(config, line, backtrace_state): # bad alloc match = re.match(STACKTRACE_BAD_ALLOC_RE, line) if match is not None: - _LOGGER.warning("Memory allocation of %s bytes failed at %s", - match.group(2), match.group(1)) + _LOGGER.warning( + "Memory allocation of %s bytes failed at %s", match.group(2), match.group(1) + ) _decode_pc(config, match.group(1)) # ESP32 single-line backtrace @@ -230,11 +245,11 @@ def process_stacktrace(config, line, backtrace_state): _decode_pc(config, addr.group()) # ESP8266 multi-line backtrace - if '>>>stack>>>' in line: + if ">>>stack>>>" in line: # Start of backtrace backtrace_state = True _LOGGER.warning("Found stack trace! Trying to decode it") - elif '<< str - return CORE.relative_config_path('.esphome', f'{CORE.config_filename}.json') + return CORE.relative_config_path(".esphome", f"{CORE.config_filename}.json") def ext_storage_path(base_path, config_filename): # type: (str, str) -> str - return os.path.join(base_path, '.esphome', f'{config_filename}.json') + return os.path.join(base_path, ".esphome", f"{config_filename}.json") def esphome_storage_path(base_path): # type: (str) -> str - return os.path.join(base_path, '.esphome', 'esphome.json') + return os.path.join(base_path, ".esphome", "esphome.json") def trash_storage_path(base_path): # type: (str) -> str - return os.path.join(base_path, '.esphome', 'trash') + return os.path.join(base_path, ".esphome", "trash") # pylint: disable=too-many-instance-attributes class StorageJSON: - def __init__(self, storage_version, name, comment, esphome_version, - src_version, arduino_version, address, esp_platform, board, build_path, - firmware_bin_path, loaded_integrations): + def __init__( + self, + storage_version, + name, + comment, + esphome_version, + src_version, + arduino_version, + address, + esp_platform, + board, + build_path, + firmware_bin_path, + loaded_integrations, + ): # Version of the storage JSON schema assert storage_version is None or isinstance(storage_version, int) self.storage_version = storage_version # type: int @@ -63,33 +75,35 @@ class StorageJSON: # The absolute path to the firmware binary self.firmware_bin_path = firmware_bin_path # type: str # A list of strings of names of loaded integrations - self.loaded_integrations = loaded_integrations # type: List[str] + self.loaded_integrations = loaded_integrations # type: List[str] self.loaded_integrations.sort() def as_dict(self): return { - 'storage_version': self.storage_version, - 'name': self.name, - 'comment': self.comment, - 'esphome_version': self.esphome_version, - 'src_version': self.src_version, - 'arduino_version': self.arduino_version, - 'address': self.address, - 'esp_platform': self.esp_platform, - 'board': self.board, - 'build_path': self.build_path, - 'firmware_bin_path': self.firmware_bin_path, - 'loaded_integrations': self.loaded_integrations, + "storage_version": self.storage_version, + "name": self.name, + "comment": self.comment, + "esphome_version": self.esphome_version, + "src_version": self.src_version, + "arduino_version": self.arduino_version, + "address": self.address, + "esp_platform": self.esp_platform, + "board": self.board, + "build_path": self.build_path, + "firmware_bin_path": self.firmware_bin_path, + "loaded_integrations": self.loaded_integrations, } def to_json(self): - return json.dumps(self.as_dict(), indent=2) + '\n' + return json.dumps(self.as_dict(), indent=2) + "\n" def save(self, path): write_file_if_changed(path, self.to_json()) @staticmethod - def from_esphome_core(esph, old): # type: (CoreType, Optional[StorageJSON]) -> StorageJSON + def from_esphome_core( + esph, old + ): # type: (CoreType, Optional[StorageJSON]) -> StorageJSON return StorageJSON( storage_version=1, name=esph.name, @@ -125,23 +139,36 @@ class StorageJSON: @staticmethod def _load_impl(path): # type: (str) -> Optional[StorageJSON] - with codecs.open(path, 'r', encoding='utf-8') as f_handle: + with codecs.open(path, "r", encoding="utf-8") as f_handle: storage = json.load(f_handle) - storage_version = storage['storage_version'] - name = storage.get('name') - comment = storage.get('comment') - esphome_version = storage.get('esphome_version', storage.get('esphomeyaml_version')) - src_version = storage.get('src_version') - arduino_version = storage.get('arduino_version') - address = storage.get('address') - esp_platform = storage.get('esp_platform') - board = storage.get('board') - build_path = storage.get('build_path') - firmware_bin_path = storage.get('firmware_bin_path') - loaded_integrations = storage.get('loaded_integrations', []) - return StorageJSON(storage_version, name, comment, esphome_version, - src_version, arduino_version, address, esp_platform, board, build_path, - firmware_bin_path, loaded_integrations) + storage_version = storage["storage_version"] + name = storage.get("name") + comment = storage.get("comment") + esphome_version = storage.get( + "esphome_version", storage.get("esphomeyaml_version") + ) + src_version = storage.get("src_version") + arduino_version = storage.get("arduino_version") + address = storage.get("address") + esp_platform = storage.get("esp_platform") + board = storage.get("board") + build_path = storage.get("build_path") + firmware_bin_path = storage.get("firmware_bin_path") + loaded_integrations = storage.get("loaded_integrations", []) + return StorageJSON( + storage_version, + name, + comment, + esphome_version, + src_version, + arduino_version, + address, + esp_platform, + board, + build_path, + firmware_bin_path, + loaded_integrations, + ) @staticmethod def load(path): # type: (str) -> Optional[StorageJSON] @@ -155,8 +182,9 @@ class StorageJSON: class EsphomeStorageJSON: - def __init__(self, storage_version, cookie_secret, last_update_check, - remote_version): + def __init__( + self, storage_version, cookie_secret, last_update_check, remote_version + ): # Version of the storage JSON schema assert storage_version is None or isinstance(storage_version, int) self.storage_version = storage_version # type: int @@ -169,10 +197,10 @@ class EsphomeStorageJSON: def as_dict(self): # type: () -> dict return { - 'storage_version': self.storage_version, - 'cookie_secret': self.cookie_secret, - 'last_update_check': self.last_update_check_str, - 'remote_version': self.remote_version, + "storage_version": self.storage_version, + "cookie_secret": self.cookie_secret, + "last_update_check": self.last_update_check_str, + "remote_version": self.remote_version, } @property @@ -187,21 +215,22 @@ class EsphomeStorageJSON: self.last_update_check_str = new.strftime("%Y-%m-%dT%H:%M:%S") def to_json(self): # type: () -> dict - return json.dumps(self.as_dict(), indent=2) + '\n' + return json.dumps(self.as_dict(), indent=2) + "\n" def save(self, path): # type: (str) -> None write_file_if_changed(path, self.to_json()) @staticmethod def _load_impl(path): # type: (str) -> Optional[EsphomeStorageJSON] - with codecs.open(path, 'r', encoding='utf-8') as f_handle: + with codecs.open(path, "r", encoding="utf-8") as f_handle: storage = json.load(f_handle) - storage_version = storage['storage_version'] - cookie_secret = storage.get('cookie_secret') - last_update_check = storage.get('last_update_check') - remote_version = storage.get('remote_version') - return EsphomeStorageJSON(storage_version, cookie_secret, last_update_check, - remote_version) + storage_version = storage["storage_version"] + cookie_secret = storage.get("cookie_secret") + last_update_check = storage.get("last_update_check") + remote_version = storage.get("remote_version") + return EsphomeStorageJSON( + storage_version, cookie_secret, last_update_check, remote_version + ) @staticmethod def load(path): # type: (str) -> Optional[EsphomeStorageJSON] diff --git a/esphome/util.py b/esphome/util.py index 3fe7ba8eb..10f9923c4 100644 --- a/esphome/util.py +++ b/esphome/util.py @@ -24,11 +24,13 @@ class RegistryEntry: @property def coroutine_fun(self): from esphome.core import coroutine + return coroutine(self.fun) @property def schema(self): from esphome.config_validation import Schema + return Schema(self.raw_schema) @@ -60,7 +62,7 @@ def safe_print(message=""): if CORE.dashboard: try: - message = message.replace('\033', '\\033') + message = message.replace("\033", "\\033") except UnicodeEncodeError: pass @@ -71,10 +73,10 @@ def safe_print(message=""): pass try: - print(message.encode('utf-8', 'backslashreplace')) + print(message.encode("utf-8", "backslashreplace")) except UnicodeEncodeError: try: - print(message.encode('ascii', 'backslashreplace')) + print(message.encode("ascii", "backslashreplace")) except UnicodeEncodeError: print("Cannot print line because of invalid locale!") @@ -82,13 +84,13 @@ def safe_print(message=""): def shlex_quote(s): if not s: return "''" - if re.search(r'[^\w@%+=:,./-]', s) is None: + if re.search(r"[^\w@%+=:,./-]", s) is None: return s return "'" + s.replace("'", "'\"'\"'") + "'" -ANSI_ESCAPE = re.compile(r'\033[@-_][0-?]*[ -/]*[@-~]') +ANSI_ESCAPE = re.compile(r"\033[@-_][0-?]*[ -/]*[@-~]") class RedirectText: @@ -97,9 +99,9 @@ class RedirectText: if filter_lines is None: self._filter_pattern = None else: - pattern = r'|'.join(r'(?:' + pattern + r')' for pattern in filter_lines) + pattern = r"|".join(r"(?:" + pattern + r")" for pattern in filter_lines) self._filter_pattern = re.compile(pattern) - self._line_buffer = '' + self._line_buffer = "" def __getattr__(self, item): return getattr(self._out, item) @@ -112,7 +114,7 @@ class RedirectText: # work. The shell we create in the dashboard is not a tty, so python removes # all color codes from the resulting stream. We just convert them to something # we can easily recognize later here. - s = s.replace('\033', '\\033') + s = s.replace("\033", "\\033") self._out.write(s) def write(self, s): @@ -128,13 +130,13 @@ class RedirectText: self._line_buffer += s lines = self._line_buffer.splitlines(True) for line in lines: - if '\n' not in line and '\r' not in line: + if "\n" not in line and "\r" not in line: # Not a complete line, set line buffer self._line_buffer = line break - self._line_buffer = '' + self._line_buffer = "" - line_without_ansi = ANSI_ESCAPE.sub('', line) + line_without_ansi = ANSI_ESCAPE.sub("", line) line_without_end = line_without_ansi.rstrip() if self._filter_pattern.match(line_without_end) is not None: # Filter pattern matched, ignore the line @@ -154,9 +156,9 @@ class RedirectText: return True -def run_external_command(func, *cmd, - capture_stdout: bool = False, - filter_lines: str = None) -> Union[int, str]: +def run_external_command( + func, *cmd, capture_stdout: bool = False, filter_lines: str = None +) -> Union[int, str]: """ Run a function from an external package that acts like a main method. @@ -169,12 +171,13 @@ def run_external_command(func, *cmd, :return: str if `capture_stdout` is set else int exit code. """ + def mock_exit(return_code): raise SystemExit(return_code) orig_argv = sys.argv orig_exit = sys.exit # mock sys.exit - full_cmd = ' '.join(shlex_quote(x) for x in cmd) + full_cmd = " ".join(shlex_quote(x) for x in cmd) _LOGGER.info("Running: %s", full_cmd) orig_stdout = sys.stdout @@ -210,11 +213,11 @@ def run_external_command(func, *cmd, def run_external_process(*cmd, **kwargs): - full_cmd = ' '.join(shlex_quote(x) for x in cmd) + full_cmd = " ".join(shlex_quote(x) for x in cmd) _LOGGER.info("Running: %s", full_cmd) - filter_lines = kwargs.get('filter_lines') + filter_lines = kwargs.get("filter_lines") - capture_stdout = kwargs.get('capture_stdout', False) + capture_stdout = kwargs.get("capture_stdout", False) if capture_stdout: sub_stdout = io.BytesIO() else: @@ -223,9 +226,7 @@ def run_external_process(*cmd, **kwargs): sub_stderr = RedirectText(sys.stderr, filter_lines=filter_lines) try: - return subprocess.call(cmd, - stdout=sub_stdout, - stderr=sub_stderr) + return subprocess.call(cmd, stdout=sub_stdout, stderr=sub_stderr) except Exception as err: # pylint: disable=broad-except _LOGGER.error("Running command failed: %s", err) _LOGGER.error("Please try running %s locally.", full_cmd) @@ -237,7 +238,7 @@ def run_external_process(*cmd, **kwargs): def is_dev_esphome_version(): - return 'dev' in const.__version__ + return "dev" in const.__version__ # Custom OrderedDict with nicer repr method for debugging @@ -253,9 +254,9 @@ def list_yaml_files(folder): def filter_yaml_files(files): - files = [f for f in files if os.path.splitext(f)[1] == '.yaml'] - files = [f for f in files if os.path.basename(f) != 'secrets.yaml'] - files = [f for f in files if not os.path.basename(f).startswith('.')] + files = [f for f in files if os.path.splitext(f)[1] == ".yaml"] + files = [f for f in files if os.path.basename(f) != "secrets.yaml"] + files = [f for f in files if not os.path.basename(f).startswith(".")] return files @@ -268,6 +269,7 @@ class SerialPort: # from https://github.com/pyserial/pyserial/blob/master/serial/tools/list_ports.py def get_serial_ports() -> List[SerialPort]: from serial.tools.list_ports import comports + result = [] for port, desc, info in comports(include_links=True): if not port: @@ -277,13 +279,13 @@ def get_serial_ports() -> List[SerialPort]: # Also add objects in /dev/serial/by-id/ # ref: https://github.com/esphome/issues/issues/1346 - by_id_path = Path('/dev/serial/by-id') - if sys.platform.lower().startswith('linux') and by_id_path.exists(): + by_id_path = Path("/dev/serial/by-id") + if sys.platform.lower().startswith("linux") and by_id_path.exists(): from serial.tools.list_ports_linux import SysFS - for path in by_id_path.glob('*'): + for path in by_id_path.glob("*"): device = SysFS(path) - if device.subsystem == 'platform': + if device.subsystem == "platform": result.append(SerialPort(path=str(path), description=info[1])) result.sort(key=lambda x: x.path) diff --git a/esphome/voluptuous_schema.py b/esphome/voluptuous_schema.py index d10801fb9..86c20510a 100644 --- a/esphome/voluptuous_schema.py +++ b/esphome/voluptuous_schema.py @@ -6,7 +6,7 @@ import voluptuous as vol class ExtraKeysInvalid(vol.Invalid): def __init__(self, *arg, **kwargs): - self.candidates = kwargs.pop('candidates') + self.candidates = kwargs.pop("candidates") vol.Invalid.__init__(self, *arg, **kwargs) @@ -19,7 +19,10 @@ def ensure_multiple_invalid(err): # pylint: disable=protected-access, unidiomatic-typecheck class _Schema(vol.Schema): """Custom cv.Schema that prints similar keys on error.""" - def __init__(self, schema, required=False, extra=vol.PREVENT_EXTRA, extra_schemas=None): + + def __init__( + self, schema, required=False, extra=vol.PREVENT_EXTRA, extra_schemas=None + ): super().__init__(schema, required=required, extra=extra) # List of extra schemas to apply after validation # Should be used sparingly, as it's not a very voluptuous-way/clean way of @@ -37,7 +40,7 @@ class _Schema(vol.Schema): return res def _compile_mapping(self, schema, invalid_msg=None): - invalid_msg = invalid_msg or 'mapping value' + invalid_msg = invalid_msg or "mapping value" # Check some things that ESPHome's schemas do not allow # mostly to keep the logic in this method sane (so these may be re-added if needed). @@ -47,7 +50,9 @@ class _Schema(vol.Schema): if isinstance(key, vol.Remove): raise ValueError("ESPHome does not allow vol.Remove") if isinstance(key, vol.primitive_types): - raise ValueError("All schema keys must be wrapped in cv.Required or cv.Optional") + raise ValueError( + "All schema keys must be wrapped in cv.Required or cv.Optional" + ) # Keys that may be required all_required_keys = {key for key in schema if isinstance(key, vol.Required)} @@ -64,7 +69,9 @@ class _Schema(vol.Schema): _compiled_schema[skey] = (new_key, new_value) # Sort compiled schema (probably not necessary for esphome, but leave it here just in case) - candidates = list(vol.schema_builder._iterate_mapping_candidates(_compiled_schema)) + candidates = list( + vol.schema_builder._iterate_mapping_candidates(_compiled_schema) + ) # After we have the list of candidates in the correct order, we want to apply some # optimization so that each @@ -75,8 +82,13 @@ class _Schema(vol.Schema): for skey, (ckey, cvalue) in candidates: if type(skey) in vol.primitive_types: candidates_by_key.setdefault(skey, []).append((skey, (ckey, cvalue))) - elif isinstance(skey, vol.Marker) and type(skey.schema) in vol.primitive_types: - candidates_by_key.setdefault(skey.schema, []).append((skey, (ckey, cvalue))) + elif ( + isinstance(skey, vol.Marker) + and type(skey.schema) in vol.primitive_types + ): + candidates_by_key.setdefault(skey.schema, []).append( + (skey, (ckey, cvalue)) + ) else: # These are wildcards such as 'int', 'str', 'Remove' and others which should be # applied to all keys @@ -101,7 +113,10 @@ class _Schema(vol.Schema): # Insert default values for non-existing keys. for key in all_default_keys: - if not isinstance(key.default, vol.Undefined) and key.schema not in key_value_map: + if ( + not isinstance(key.default, vol.Undefined) + and key.schema not in key_value_map + ): # A default value has been specified for this missing key, insert it. key_value_map[key.schema] = key.default() @@ -110,8 +125,9 @@ class _Schema(vol.Schema): for key, value in key_value_map.items(): key_path = path + [key] # Optimization. Validate against the matching key first, then fallback to the rest - relevant_candidates = itertools.chain(candidates_by_key.get(key, []), - additional_candidates) + relevant_candidates = itertools.chain( + candidates_by_key.get(key, []), additional_candidates + ) # compare each given key/value against all compiled key/values # schema key, (compiled key, compiled value) @@ -158,14 +174,21 @@ class _Schema(vol.Schema): elif self.extra != vol.REMOVE_EXTRA: if isinstance(key, str) and key_names: matches = difflib.get_close_matches(key, key_names) - errors.append(ExtraKeysInvalid('extra keys not allowed', key_path, - candidates=matches)) + errors.append( + ExtraKeysInvalid( + "extra keys not allowed", + key_path, + candidates=matches, + ) + ) else: - errors.append(vol.Invalid('extra keys not allowed', key_path)) + errors.append( + vol.Invalid("extra keys not allowed", key_path) + ) # for any required keys left that weren't found and don't have defaults: for key in required_keys: - msg = getattr(key, 'msg', None) or 'required key not provided' + msg = getattr(key, "msg", None) or "required key not provided" errors.append(vol.RequiredFieldInvalid(msg, path + [key])) if errors: raise vol.MultipleInvalid(errors) @@ -181,7 +204,7 @@ class _Schema(vol.Schema): # pylint: disable=signature-differs def extend(self, *schemas, **kwargs): - extra = kwargs.pop('extra', None) + extra = kwargs.pop("extra", None) if kwargs: raise ValueError if not schemas: diff --git a/esphome/vscode.py b/esphome/vscode.py index 8782ed6e5..6e1a0270b 100644 --- a/esphome/vscode.py +++ b/esphome/vscode.py @@ -20,11 +20,11 @@ def _dump_range(range): if range is None: return None return { - 'document': range.start_mark.document, - 'start_line': range.start_mark.line, - 'start_col': range.start_mark.column, - 'end_line': range.end_mark.line, - 'end_col': range.end_mark.column, + "document": range.start_mark.document, + "start_line": range.start_mark.line, + "start_col": range.start_mark.column, + "end_line": range.end_mark.line, + "end_col": range.end_mark.column, } @@ -34,36 +34,42 @@ class VSCodeResult: self.validation_errors = [] def dump(self): - return json.dumps({ - 'type': 'result', - 'yaml_errors': self.yaml_errors, - 'validation_errors': self.validation_errors, - }) + return json.dumps( + { + "type": "result", + "yaml_errors": self.yaml_errors, + "validation_errors": self.validation_errors, + } + ) def add_yaml_error(self, message): - self.yaml_errors.append({ - 'message': message, - }) + self.yaml_errors.append( + { + "message": message, + } + ) def add_validation_error(self, range_, message): - self.validation_errors.append({ - 'range': _dump_range(range_), - 'message': message, - }) + self.validation_errors.append( + { + "range": _dump_range(range_), + "message": message, + } + ) def read_config(args): while True: CORE.reset() data = json.loads(input()) - assert data['type'] == 'validate' + assert data["type"] == "validate" CORE.vscode = True CORE.ace = args.ace - f = data['file'] + f = data["file"] if CORE.ace: CORE.config_path = os.path.join(args.configuration[0], f) else: - CORE.config_path = data['file'] + CORE.config_path = data["file"] vs = VSCodeResult() try: res = load_config(dict(args.substitution) if args.substitution else {}) diff --git a/esphome/wizard.py b/esphome/wizard.py index 9b6237acf..620ceb9b5 100644 --- a/esphome/wizard.py +++ b/esphome/wizard.py @@ -7,6 +7,7 @@ import voluptuous as vol import esphome.config_validation as cv from esphome.helpers import color, get_bool_env, write_file + # pylint: disable=anomalous-backslash-in-string from esphome.pins import ESP32_BOARD_PINS, ESP8266_BOARD_PINS from esphome.storage_json import StorageJSON, ext_storage_path @@ -67,22 +68,24 @@ api: def sanitize_double_quotes(value): - return value.replace('\\', '\\\\').replace('"', '\\"') + return value.replace("\\", "\\\\").replace('"', '\\"') def wizard_file(**kwargs): letters = string.ascii_letters + string.digits - ap_name_base = kwargs['name'].replace('_', ' ').title() + ap_name_base = kwargs["name"].replace("_", " ").title() ap_name = f"{ap_name_base} Fallback Hotspot" if len(ap_name) > 32: ap_name = ap_name_base - kwargs['fallback_name'] = ap_name - kwargs['fallback_psk'] = ''.join(random.choice(letters) for _ in range(12)) + kwargs["fallback_name"] = ap_name + kwargs["fallback_psk"] = "".join(random.choice(letters) for _ in range(12)) config = BASE_CONFIG.format(**kwargs) - if kwargs['password']: - config += ' password: "{0}"\n\nota:\n password: "{0}"\n'.format(kwargs['password']) + if kwargs["password"]: + config += ' password: "{0}"\n\nota:\n password: "{0}"\n'.format( + kwargs["password"] + ) else: config += "\nota:\n" @@ -90,26 +93,29 @@ def wizard_file(**kwargs): def wizard_write(path, **kwargs): - name = kwargs['name'] - board = kwargs['board'] + name = kwargs["name"] + board = kwargs["board"] - kwargs['ssid'] = sanitize_double_quotes(kwargs['ssid']) - kwargs['psk'] = sanitize_double_quotes(kwargs['psk']) - kwargs['password'] = sanitize_double_quotes(kwargs['password']) + kwargs["ssid"] = sanitize_double_quotes(kwargs["ssid"]) + kwargs["psk"] = sanitize_double_quotes(kwargs["psk"]) + kwargs["password"] = sanitize_double_quotes(kwargs["password"]) - if 'platform' not in kwargs: - kwargs['platform'] = 'ESP8266' if board in ESP8266_BOARD_PINS else 'ESP32' - platform = kwargs['platform'] + if "platform" not in kwargs: + kwargs["platform"] = "ESP8266" if board in ESP8266_BOARD_PINS else "ESP32" + platform = kwargs["platform"] write_file(path, wizard_file(**kwargs)) - storage = StorageJSON.from_wizard(name, name + '.local', platform, board) + storage = StorageJSON.from_wizard(name, name + ".local", platform, board) storage_path = ext_storage_path(os.path.dirname(path), os.path.basename(path)) storage.save(storage_path) if get_bool_env(ENV_QUICKWIZARD): + def sleep(time): pass + + else: from time import sleep @@ -131,18 +137,25 @@ def default_input(text, default): # From https://stackoverflow.com/a/518232/8924614 def strip_accents(value): - return ''.join(c for c in unicodedata.normalize('NFD', str(value)) - if unicodedata.category(c) != 'Mn') + return "".join( + c + for c in unicodedata.normalize("NFD", str(value)) + if unicodedata.category(c) != "Mn" + ) def wizard(path): - if not path.endswith('.yaml') and not path.endswith('.yml'): - safe_print("Please make your configuration file {} have the extension .yaml or .yml" - "".format(color('cyan', path))) + if not path.endswith(".yaml") and not path.endswith(".yml"): + safe_print( + "Please make your configuration file {} have the extension .yaml or .yml" + "".format(color("cyan", path)) + ) return 1 if os.path.exists(path): - safe_print("Uh oh, it seems like {} already exists, please delete that file first " - "or chose another configuration file.".format(color('cyan', path))) + safe_print( + "Uh oh, it seems like {} already exists, please delete that file first " + "or chose another configuration file.".format(color("cyan", path)) + ) return 2 safe_print("Hi there!") sleep(1.5) @@ -150,16 +163,25 @@ def wizard(path): sleep(1.25) safe_print("And I'm here to help you get started with ESPHome.") sleep(2.0) - safe_print("In 4 steps I'm going to guide you through creating a basic " - "configuration file for your custom ESP8266/ESP32 firmware. Yay!") + safe_print( + "In 4 steps I'm going to guide you through creating a basic " + "configuration file for your custom ESP8266/ESP32 firmware. Yay!" + ) sleep(3.0) safe_print() safe_print_step(1, CORE_BIG) - safe_print("First up, please choose a " + color('green', 'name') + " for your node.") - safe_print("It should be a unique name that can be used to identify the device later.") + safe_print( + "First up, please choose a " + color("green", "name") + " for your node." + ) + safe_print( + "It should be a unique name that can be used to identify the device later." + ) sleep(1) - safe_print("For example, I like calling the node in my living room {}.".format( - color('bold_white', "livingroom"))) + safe_print( + "For example, I like calling the node in my living room {}.".format( + color("bold_white", "livingroom") + ) + ) safe_print() sleep(1) name = input(color("bold_white", "(name): ")) @@ -169,56 +191,80 @@ def wizard(path): name = cv.valid_name(name) break except vol.Invalid: - safe_print(color("red", f"Oh noes, \"{name}\" isn't a valid name. Names can only " - f"include numbers, lower-case letters, underscores and " - f"hyphens.")) - name = strip_accents(name).lower().replace(' ', '_') - name = ''.join(c for c in name if c in ALLOWED_NAME_CHARS) - safe_print("Shall I use \"{}\" as the name instead?".format(color('cyan', name))) + safe_print( + color( + "red", + f'Oh noes, "{name}" isn\'t a valid name. Names can only ' + f"include numbers, lower-case letters, underscores and " + f"hyphens.", + ) + ) + name = strip_accents(name).lower().replace(" ", "_") + name = "".join(c for c in name if c in ALLOWED_NAME_CHARS) + safe_print( + 'Shall I use "{}" as the name instead?'.format(color("cyan", name)) + ) sleep(0.5) name = default_input("(name [{}]): ", name) - safe_print("Great! Your node is now called \"{}\".".format(color('cyan', name))) + safe_print('Great! Your node is now called "{}".'.format(color("cyan", name))) sleep(1) safe_print_step(2, ESP_BIG) - safe_print("Now I'd like to know what microcontroller you're using so that I can compile " - "firmwares for it.") - safe_print("Are you using an " + color('green', 'ESP32') + " or " + - color('green', 'ESP8266') + " platform? (Choose ESP8266 for Sonoff devices)") + safe_print( + "Now I'd like to know what microcontroller you're using so that I can compile " + "firmwares for it." + ) + safe_print( + "Are you using an " + + color("green", "ESP32") + + " or " + + color("green", "ESP8266") + + " platform? (Choose ESP8266 for Sonoff devices)" + ) while True: sleep(0.5) safe_print() safe_print("Please enter either ESP32 or ESP8266.") platform = input(color("bold_white", "(ESP32/ESP8266): ")) try: - platform = vol.All(vol.Upper, vol.Any('ESP32', 'ESP8266'))(platform) + platform = vol.All(vol.Upper, vol.Any("ESP32", "ESP8266"))(platform) break except vol.Invalid: - safe_print("Unfortunately, I can't find an espressif microcontroller called " - "\"{}\". Please try again.".format(platform)) - safe_print("Thanks! You've chosen {} as your platform.".format(color('cyan', platform))) + safe_print( + "Unfortunately, I can't find an espressif microcontroller called " + '"{}". Please try again.'.format(platform) + ) + safe_print( + "Thanks! You've chosen {} as your platform.".format(color("cyan", platform)) + ) safe_print() sleep(1) - if platform == 'ESP32': - board_link = 'http://docs.platformio.org/en/latest/platforms/espressif32.html#boards' + if platform == "ESP32": + board_link = ( + "http://docs.platformio.org/en/latest/platforms/espressif32.html#boards" + ) else: - board_link = 'http://docs.platformio.org/en/latest/platforms/espressif8266.html#boards' + board_link = ( + "http://docs.platformio.org/en/latest/platforms/espressif8266.html#boards" + ) - safe_print("Next, I need to know what " + color('green', 'board') + " you're using.") + safe_print( + "Next, I need to know what " + color("green", "board") + " you're using." + ) sleep(0.5) - safe_print("Please go to {} and choose a board.".format(color('green', board_link))) - if platform == 'ESP32': - safe_print("(Type " + color('green', 'esp01_1m') + " for Sonoff devices)") + safe_print("Please go to {} and choose a board.".format(color("green", board_link))) + if platform == "ESP32": + safe_print("(Type " + color("green", "esp01_1m") + " for Sonoff devices)") safe_print() # Don't sleep because user needs to copy link - if platform == 'ESP32': - safe_print("For example \"{}\".".format(color("bold_white", 'nodemcu-32s'))) + if platform == "ESP32": + safe_print('For example "{}".'.format(color("bold_white", "nodemcu-32s"))) boards = list(ESP32_BOARD_PINS.keys()) else: - safe_print("For example \"{}\".".format(color("bold_white", 'nodemcuv2'))) + safe_print('For example "{}".'.format(color("bold_white", "nodemcuv2"))) boards = list(ESP8266_BOARD_PINS.keys()) - safe_print("Options: {}".format(', '.join(sorted(boards)))) + safe_print("Options: {}".format(", ".join(sorted(boards)))) while True: board = input(color("bold_white", "(board): ")) @@ -226,69 +272,102 @@ def wizard(path): board = vol.All(vol.Lower, vol.Any(*boards))(board) break except vol.Invalid: - safe_print(color('red', f"Sorry, I don't think the board \"{board}\" exists.")) + safe_print( + color("red", f'Sorry, I don\'t think the board "{board}" exists.') + ) safe_print() sleep(0.25) safe_print() - safe_print("Way to go! You've chosen {} as your board.".format(color('cyan', board))) + safe_print( + "Way to go! You've chosen {} as your board.".format(color("cyan", board)) + ) safe_print() sleep(1) safe_print_step(3, WIFI_BIG) - safe_print("In this step, I'm going to create the configuration for " - "WiFi.") + safe_print("In this step, I'm going to create the configuration for " "WiFi.") safe_print() sleep(1) - safe_print("First, what's the " + color('green', 'SSID') + - f" (the name) of the WiFi network {name} I should connect to?") + safe_print( + "First, what's the " + + color("green", "SSID") + + f" (the name) of the WiFi network {name} I should connect to?" + ) sleep(1.5) - safe_print("For example \"{}\".".format(color('bold_white', "Abraham Linksys"))) + safe_print('For example "{}".'.format(color("bold_white", "Abraham Linksys"))) while True: - ssid = input(color('bold_white', "(ssid): ")) + ssid = input(color("bold_white", "(ssid): ")) try: ssid = cv.ssid(ssid) break except vol.Invalid: - safe_print(color('red', "Unfortunately, \"{}\" doesn't seem to be a valid SSID. " - "Please try again.".format(ssid))) + safe_print( + color( + "red", + 'Unfortunately, "{}" doesn\'t seem to be a valid SSID. ' + "Please try again.".format(ssid), + ) + ) safe_print() sleep(1) - safe_print("Thank you very much! You've just chosen \"{}\" as your SSID." - "".format(color('cyan', ssid))) + safe_print( + 'Thank you very much! You\'ve just chosen "{}" as your SSID.' + "".format(color("cyan", ssid)) + ) safe_print() sleep(0.75) - safe_print("Now please state the " + color('green', 'password') + - " of the WiFi network so that I can connect to it (Leave empty for no password)") + safe_print( + "Now please state the " + + color("green", "password") + + " of the WiFi network so that I can connect to it (Leave empty for no password)" + ) safe_print() - safe_print("For example \"{}\"".format(color('bold_white', 'PASSWORD42'))) + safe_print('For example "{}"'.format(color("bold_white", "PASSWORD42"))) sleep(0.5) - psk = input(color('bold_white', '(PSK): ')) - safe_print("Perfect! WiFi is now set up (you can create static IPs and so on later).") + psk = input(color("bold_white", "(PSK): ")) + safe_print( + "Perfect! WiFi is now set up (you can create static IPs and so on later)." + ) sleep(1.5) safe_print_step(4, OTA_BIG) - safe_print("Almost there! ESPHome can automatically upload custom firmwares over WiFi " - "(over the air) and integrates into Home Assistant with a native API.") - safe_print("This can be insecure if you do not trust the WiFi network. Do you want to set " - "a " + color('green', 'password') + " for connecting to this ESP?") + safe_print( + "Almost there! ESPHome can automatically upload custom firmwares over WiFi " + "(over the air) and integrates into Home Assistant with a native API." + ) + safe_print( + "This can be insecure if you do not trust the WiFi network. Do you want to set " + "a " + color("green", "password") + " for connecting to this ESP?" + ) safe_print() sleep(0.25) safe_print("Press ENTER for no password") - password = input(color('bold_white', '(password): ')) + password = input(color("bold_white", "(password): ")) - wizard_write(path=path, name=name, platform=platform, board=board, - ssid=ssid, psk=psk, password=password) + wizard_write( + path=path, + name=name, + platform=platform, + board=board, + ssid=ssid, + psk=psk, + password=password, + ) safe_print() - safe_print(color('cyan', "DONE! I've now written a new configuration file to ") + - color('bold_cyan', path)) + safe_print( + color("cyan", "DONE! I've now written a new configuration file to ") + + color("bold_cyan", path) + ) safe_print() safe_print("Next steps:") - safe_print(" > Check your Home Assistant \"integrations\" screen. If all goes well, you " - "should see your ESP being discovered automatically.") + safe_print( + ' > Check your Home Assistant "integrations" screen. If all goes well, you ' + "should see your ESP being discovered automatically." + ) safe_print(" > Then follow the rest of the getting started guide:") safe_print(" > https://esphome.io/guides/getting_started_command_line.html") return 0 diff --git a/esphome/writer.py b/esphome/writer.py index 237f0fb4b..ec772b512 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -3,30 +3,46 @@ import os import re from esphome.config import iter_components -from esphome.const import CONF_BOARD_FLASH_MODE, CONF_ESPHOME, CONF_PLATFORMIO_OPTIONS, \ - HEADER_FILE_EXTENSIONS, SOURCE_FILE_EXTENSIONS, __version__, ARDUINO_VERSION_ESP8266, \ - ENV_NOGITIGNORE +from esphome.const import ( + CONF_BOARD_FLASH_MODE, + CONF_ESPHOME, + CONF_PLATFORMIO_OPTIONS, + HEADER_FILE_EXTENSIONS, + SOURCE_FILE_EXTENSIONS, + __version__, + ARDUINO_VERSION_ESP8266, + ENV_NOGITIGNORE, +) from esphome.core import CORE, EsphomeError -from esphome.helpers import mkdir_p, read_file, write_file_if_changed, walk_files, \ - copy_file_if_changed, get_bool_env +from esphome.helpers import ( + mkdir_p, + read_file, + write_file_if_changed, + walk_files, + copy_file_if_changed, + get_bool_env, +) from esphome.storage_json import StorageJSON, storage_path from esphome.pins import ESP8266_FLASH_SIZES, ESP8266_LD_SCRIPTS _LOGGER = logging.getLogger(__name__) -CPP_AUTO_GENERATE_BEGIN = '// ========== AUTO GENERATED CODE BEGIN ===========' -CPP_AUTO_GENERATE_END = '// =========== AUTO GENERATED CODE END ============' -CPP_INCLUDE_BEGIN = '// ========== AUTO GENERATED INCLUDE BLOCK BEGIN ===========' -CPP_INCLUDE_END = '// ========== AUTO GENERATED INCLUDE BLOCK END ===========' -INI_AUTO_GENERATE_BEGIN = '; ========== AUTO GENERATED CODE BEGIN ===========' -INI_AUTO_GENERATE_END = '; =========== AUTO GENERATED CODE END ============' +CPP_AUTO_GENERATE_BEGIN = "// ========== AUTO GENERATED CODE BEGIN ===========" +CPP_AUTO_GENERATE_END = "// =========== AUTO GENERATED CODE END ============" +CPP_INCLUDE_BEGIN = "// ========== AUTO GENERATED INCLUDE BLOCK BEGIN ===========" +CPP_INCLUDE_END = "// ========== AUTO GENERATED INCLUDE BLOCK END ===========" +INI_AUTO_GENERATE_BEGIN = "; ========== AUTO GENERATED CODE BEGIN ===========" +INI_AUTO_GENERATE_END = "; =========== AUTO GENERATED CODE END ============" -CPP_BASE_FORMAT = ("""// Auto generated code by esphome -""", """" +CPP_BASE_FORMAT = ( + """// Auto generated code by esphome +""", + """" void setup() { // ===== DO NOT EDIT ANYTHING BELOW THIS LINE ===== - """, """ + """, + """ // ========= YOU CAN EDIT AFTER THIS LINE ========= App.setup(); } @@ -34,9 +50,11 @@ void setup() { void loop() { App.loop(); } -""") +""", +) -INI_BASE_FORMAT = ("""; Auto generated code by esphome +INI_BASE_FORMAT = ( + """; Auto generated code by esphome [common] lib_deps = @@ -44,13 +62,15 @@ build_flags = upload_flags = ; ===== DO NOT EDIT ANYTHING BELOW THIS LINE ===== -""", """ +""", + """ ; ========= YOU CAN EDIT AFTER THIS LINE ========= -""") +""", +) UPLOAD_SPEED_OVERRIDE = { - 'esp210': 57600, + "esp210": 57600, } @@ -62,10 +82,9 @@ def get_flags(key): def get_include_text(): - include_text = '#include "esphome.h"\n' \ - 'using namespace esphome;\n' + include_text = '#include "esphome.h"\nusing namespace esphome;\n' for _, component, conf in iter_components(CORE.config): - if not hasattr(component, 'includes'): + if not hasattr(component, "includes"): continue includes = component.includes if callable(includes): @@ -73,10 +92,10 @@ def get_include_text(): if includes is None: continue if isinstance(includes, list): - includes = '\n'.join(includes) + includes = "\n".join(includes) if not includes: continue - include_text += includes + '\n' + include_text += includes + "\n" return include_text @@ -86,7 +105,7 @@ def replace_file_content(text, pattern, repl): def migrate_src_version_0_to_1(): - main_cpp = CORE.relative_build_path('src', 'main.cpp') + main_cpp = CORE.relative_build_path("src", "main.cpp") if not os.path.isfile(main_cpp): return @@ -95,22 +114,35 @@ def migrate_src_version_0_to_1(): if CPP_INCLUDE_BEGIN in content: return - content, count = replace_file_content(content, r'\s*delay\((?:16|20)\);', '') + content, count = replace_file_content(content, r"\s*delay\((?:16|20)\);", "") if count != 0: - _LOGGER.info("Migration: Removed %s occurrence of 'delay(16);' in %s", count, main_cpp) + _LOGGER.info( + "Migration: Removed %s occurrence of 'delay(16);' in %s", count, main_cpp + ) - content, count = replace_file_content(content, r'using namespace esphomelib;', '') + content, count = replace_file_content(content, r"using namespace esphomelib;", "") if count != 0: - _LOGGER.info("Migration: Removed %s occurrence of 'using namespace esphomelib;' " - "in %s", count, main_cpp) + _LOGGER.info( + "Migration: Removed %s occurrence of 'using namespace esphomelib;' " + "in %s", + count, + main_cpp, + ) if CPP_INCLUDE_BEGIN not in content: - content, count = replace_file_content(content, r'#include "esphomelib/application.h"', - CPP_INCLUDE_BEGIN + '\n' + CPP_INCLUDE_END) + content, count = replace_file_content( + content, + r'#include "esphomelib/application.h"', + CPP_INCLUDE_BEGIN + "\n" + CPP_INCLUDE_END, + ) if count == 0: - _LOGGER.error("Migration failed. ESPHome 1.10.0 needs to have a new auto-generated " - "include section in the %s file. Please remove %s and let it be " - "auto-generated again.", main_cpp, main_cpp) + _LOGGER.error( + "Migration failed. ESPHome 1.10.0 needs to have a new auto-generated " + "include section in the %s file. Please remove %s and let it be " + "auto-generated again.", + main_cpp, + main_cpp, + ) _LOGGER.info("Migration: Added include section to %s", main_cpp) write_file_if_changed(main_cpp, content) @@ -160,14 +192,14 @@ def update_storage_json(): def format_ini(data): - content = '' + content = "" for key, value in sorted(data.items()): if isinstance(value, (list, set, tuple)): - content += f'{key} =\n' + content += f"{key} =\n" for x in value: - content += f' {x}\n' + content += f" {x}\n" else: - content += f'{key} = {value}\n' + content += f"{key} = {value}\n" return content @@ -197,23 +229,23 @@ def get_ini_content(): build_flags = gather_build_flags() data = { - 'platform': CORE.arduino_version, - 'board': CORE.board, - 'framework': 'arduino', - 'lib_deps': lib_deps + ['${common.lib_deps}'], - 'build_flags': build_flags + ['${common.build_flags}'], - 'upload_speed': UPLOAD_SPEED_OVERRIDE.get(CORE.board, 115200), + "platform": CORE.arduino_version, + "board": CORE.board, + "framework": "arduino", + "lib_deps": lib_deps + ["${common.lib_deps}"], + "build_flags": build_flags + ["${common.build_flags}"], + "upload_speed": UPLOAD_SPEED_OVERRIDE.get(CORE.board, 115200), } if CORE.is_esp32: - data['board_build.partitions'] = "partitions.csv" - partitions_csv = CORE.relative_build_path('partitions.csv') + data["board_build.partitions"] = "partitions.csv" + partitions_csv = CORE.relative_build_path("partitions.csv") write_file_if_changed(partitions_csv, ESP32_LARGE_PARTITIONS_CSV) # pylint: disable=unsubscriptable-object if CONF_BOARD_FLASH_MODE in CORE.config[CONF_ESPHOME]: flash_mode = CORE.config[CONF_ESPHOME][CONF_BOARD_FLASH_MODE] - data['board_build.flash_mode'] = flash_mode + data["board_build.flash_mode"] = flash_mode # Build flags if CORE.is_esp8266 and CORE.board in ESP8266_FLASH_SIZES: @@ -221,11 +253,11 @@ def get_ini_content(): ld_scripts = ESP8266_LD_SCRIPTS[flash_size] versions_with_old_ldscripts = [ - ARDUINO_VERSION_ESP8266['2.4.0'], - ARDUINO_VERSION_ESP8266['2.4.1'], - ARDUINO_VERSION_ESP8266['2.4.2'], + ARDUINO_VERSION_ESP8266["2.4.0"], + ARDUINO_VERSION_ESP8266["2.4.1"], + ARDUINO_VERSION_ESP8266["2.4.2"], ] - if CORE.arduino_version == ARDUINO_VERSION_ESP8266['2.3.0']: + if CORE.arduino_version == ARDUINO_VERSION_ESP8266["2.3.0"]: # No ld script support ld_script = None if CORE.arduino_version in versions_with_old_ldscripts: @@ -235,14 +267,14 @@ def get_ini_content(): ld_script = ld_scripts[1] if ld_script is not None: - data['board_build.ldscript'] = ld_script + data["board_build.ldscript"] = ld_script # Ignore libraries that are not explicitly used, but may # be added by LDF # data['lib_ldf_mode'] = 'chain' data.update(CORE.config[CONF_ESPHOME].get(CONF_PLATFORMIO_OPTIONS, {})) - content = f'[env:{CORE.name}]\n' + content = f"[env:{CORE.name}]\n" content += format_ini(data) return content @@ -251,32 +283,42 @@ def get_ini_content(): def find_begin_end(text, begin_s, end_s): begin_index = text.find(begin_s) if begin_index == -1: - raise EsphomeError("Could not find auto generated code begin in file, either " - "delete the main sketch file or insert the comment again.") + raise EsphomeError( + "Could not find auto generated code begin in file, either " + "delete the main sketch file or insert the comment again." + ) if text.find(begin_s, begin_index + 1) != -1: - raise EsphomeError("Found multiple auto generate code begins, don't know " - "which to chose, please remove one of them.") + raise EsphomeError( + "Found multiple auto generate code begins, don't know " + "which to chose, please remove one of them." + ) end_index = text.find(end_s) if end_index == -1: - raise EsphomeError("Could not find auto generated code end in file, either " - "delete the main sketch file or insert the comment again.") + raise EsphomeError( + "Could not find auto generated code end in file, either " + "delete the main sketch file or insert the comment again." + ) if text.find(end_s, end_index + 1) != -1: - raise EsphomeError("Found multiple auto generate code endings, don't know " - "which to chose, please remove one of them.") + raise EsphomeError( + "Found multiple auto generate code endings, don't know " + "which to chose, please remove one of them." + ) - return text[:begin_index], text[(end_index + len(end_s)):] + return text[:begin_index], text[(end_index + len(end_s)) :] def write_platformio_ini(content): update_storage_json() - path = CORE.relative_build_path('platformio.ini') + path = CORE.relative_build_path("platformio.ini") if os.path.isfile(path): text = read_file(path) - content_format = find_begin_end(text, INI_AUTO_GENERATE_BEGIN, INI_AUTO_GENERATE_END) + content_format = find_begin_end( + text, INI_AUTO_GENERATE_BEGIN, INI_AUTO_GENERATE_END + ) else: content_format = INI_BASE_FORMAT - full_file = content_format[0] + INI_AUTO_GENERATE_BEGIN + '\n' + content + full_file = content_format[0] + INI_AUTO_GENERATE_BEGIN + "\n" + content full_file += INI_AUTO_GENERATE_END + content_format[1] write_file_if_changed(path, full_file) @@ -298,8 +340,8 @@ VERSION_H_FORMAT = """\ #pragma once #define ESPHOME_VERSION "{}" """ -DEFINES_H_TARGET = 'esphome/core/defines.h' -VERSION_H_TARGET = 'esphome/core/version.h' +DEFINES_H_TARGET = "esphome/core/defines.h" +VERSION_H_TARGET = "esphome/core/version.h" ESPHOME_README_TXT = """ THIS DIRECTORY IS AUTO-GENERATED, DO NOT MODIFY @@ -326,18 +368,20 @@ def copy_src_tree(): for target, path in source_files_l: if os.path.splitext(path)[1] in HEADER_FILE_EXTENSIONS: include_l.append(f'#include "{target}"') - include_l.append('') - include_s = '\n'.join(include_l) + include_l.append("") + include_s = "\n".join(include_l) source_files_copy = source_files.copy() source_files_copy.pop(DEFINES_H_TARGET) - for path in walk_files(CORE.relative_src_path('esphome')): + for path in walk_files(CORE.relative_src_path("esphome")): if os.path.splitext(path)[1] not in SOURCE_FILE_EXTENSIONS: # Not a source file, ignore continue # Transform path to target path name - target = os.path.relpath(path, CORE.relative_src_path()).replace(os.path.sep, '/') + target = os.path.relpath(path, CORE.relative_src_path()).replace( + os.path.sep, "/" + ) if target in (DEFINES_H_TARGET, VERSION_H_TARGET): # Ignore defines.h, will be dealt with later continue @@ -350,32 +394,41 @@ def copy_src_tree(): # Now copy new files for target, src_path in source_files_copy.items(): - dst_path = CORE.relative_src_path(*target.split('/')) + dst_path = CORE.relative_src_path(*target.split("/")) copy_file_if_changed(src_path, dst_path) # Finally copy defines - write_file_if_changed(CORE.relative_src_path('esphome', 'core', 'defines.h'), - generate_defines_h()) - write_file_if_changed(CORE.relative_src_path('esphome', 'README.txt'), - ESPHOME_README_TXT) - write_file_if_changed(CORE.relative_src_path('esphome.h'), - ESPHOME_H_FORMAT.format(include_s)) - write_file_if_changed(CORE.relative_src_path('esphome', 'core', 'version.h'), - VERSION_H_FORMAT.format(__version__)) + write_file_if_changed( + CORE.relative_src_path("esphome", "core", "defines.h"), generate_defines_h() + ) + write_file_if_changed( + CORE.relative_src_path("esphome", "README.txt"), ESPHOME_README_TXT + ) + write_file_if_changed( + CORE.relative_src_path("esphome.h"), ESPHOME_H_FORMAT.format(include_s) + ) + write_file_if_changed( + CORE.relative_src_path("esphome", "core", "version.h"), + VERSION_H_FORMAT.format(__version__), + ) def generate_defines_h(): define_content_l = [x.as_macro for x in CORE.defines] define_content_l.sort() - return DEFINES_H_FORMAT.format('\n'.join(define_content_l)) + return DEFINES_H_FORMAT.format("\n".join(define_content_l)) def write_cpp(code_s): - path = CORE.relative_src_path('main.cpp') + path = CORE.relative_src_path("main.cpp") if os.path.isfile(path): text = read_file(path) - code_format = find_begin_end(text, CPP_AUTO_GENERATE_BEGIN, CPP_AUTO_GENERATE_END) - code_format_ = find_begin_end(code_format[0], CPP_INCLUDE_BEGIN, CPP_INCLUDE_END) + code_format = find_begin_end( + text, CPP_AUTO_GENERATE_BEGIN, CPP_AUTO_GENERATE_END + ) + code_format_ = find_begin_end( + code_format[0], CPP_INCLUDE_BEGIN, CPP_INCLUDE_END + ) code_format = (code_format_[0], code_format_[1], code_format[1]) else: code_format = CPP_BASE_FORMAT @@ -384,8 +437,10 @@ def write_cpp(code_s): global_s = '#include "esphome.h"\n' global_s += CORE.cpp_global_section - full_file = code_format[0] + CPP_INCLUDE_BEGIN + '\n' + global_s + CPP_INCLUDE_END - full_file += code_format[1] + CPP_AUTO_GENERATE_BEGIN + '\n' + code_s + CPP_AUTO_GENERATE_END + full_file = code_format[0] + CPP_INCLUDE_BEGIN + "\n" + global_s + CPP_INCLUDE_END + full_file += ( + code_format[1] + CPP_AUTO_GENERATE_BEGIN + "\n" + code_s + CPP_AUTO_GENERATE_END + ) full_file += code_format[2] write_file_if_changed(path, full_file) @@ -417,7 +472,7 @@ GITIGNORE_CONTENT = """# Gitignore settings for ESPHome def write_gitignore(): - path = CORE.relative_config_path('.gitignore') + path = CORE.relative_config_path(".gitignore") if not os.path.isfile(path): - with open(path, 'w') as f: + with open(path, "w") as f: f.write(GITIGNORE_CONTENT) diff --git a/esphome/yaml_util.py b/esphome/yaml_util.py index eb88a8da6..f98bb272b 100644 --- a/esphome/yaml_util.py +++ b/esphome/yaml_util.py @@ -11,8 +11,14 @@ import yaml.constructor from esphome import core from esphome.config_helpers import read_config_file -from esphome.core import EsphomeError, IPAddress, Lambda, MACAddress, TimePeriod, \ - DocumentRange +from esphome.core import ( + EsphomeError, + IPAddress, + Lambda, + MACAddress, + TimePeriod, + DocumentRange, +) from esphome.helpers import add_class_to_obj from esphome.util import OrderedDict, filter_yaml_files @@ -21,7 +27,7 @@ _LOGGER = logging.getLogger(__name__) # Mostly copied from Home Assistant because that code works fine and # let's not reinvent the wheel here -SECRET_YAML = 'secrets.yaml' +SECRET_YAML = "secrets.yaml" _SECRET_CACHE = {} _SECRET_VALUES = {} @@ -29,17 +35,17 @@ _SECRET_VALUES = {} class ESPHomeDataBase: @property def esp_range(self): - return getattr(self, '_esp_range', None) + return getattr(self, "_esp_range", None) @property def content_offset(self): - return getattr(self, '_content_offset', 0) + return getattr(self, "_content_offset", 0) def from_node(self, node): # pylint: disable=attribute-defined-outside-init self._esp_range = DocumentRange.from_marks(node.start_mark, node.end_mark) if isinstance(node, yaml.ScalarNode): - if node.style is not None and node.style in '|>': + if node.style is not None and node.style in "|>": self._content_offset = 1 def from_database(self, database): @@ -125,13 +131,13 @@ class ESPHomeLoader(yaml.SafeLoader): # pylint: disable=too-many-ancestors for key_node, value_node in node.value: # merge key is '<<' - is_merge_key = key_node.tag == 'tag:yaml.org,2002:merge' + is_merge_key = key_node.tag == "tag:yaml.org,2002:merge" # key has no explicit tag set - is_default_tag = key_node.tag == 'tag:yaml.org,2002:value' + is_default_tag = key_node.tag == "tag:yaml.org,2002:value" if is_default_tag: # Default tag for mapping keys is string - key_node.tag = 'tag:yaml.org,2002:str' + key_node.tag = "tag:yaml.org,2002:str" if not is_merge_key: # base case, this is a simple key-value pair @@ -144,7 +150,8 @@ class ESPHomeLoader(yaml.SafeLoader): # pylint: disable=too-many-ancestors except TypeError: # pylint: disable=raise-missing-from raise yaml.constructor.ConstructorError( - f'Invalid key "{key}" (not hashable)', key_node.start_mark) + f'Invalid key "{key}" (not hashable)', key_node.start_mark + ) key = make_data_base(str(key)) key.from_node(key_node) @@ -152,8 +159,10 @@ class ESPHomeLoader(yaml.SafeLoader): # pylint: disable=too-many-ancestors # Check if it is a duplicate key if key in seen_keys: raise yaml.constructor.ConstructorError( - f'Duplicate key "{key}"', key_node.start_mark, - 'NOTE: Previous declaration here:', seen_keys[key], + f'Duplicate key "{key}"', + key_node.start_mark, + "NOTE: Previous declaration here:", + seen_keys[key], ) seen_keys[key] = key_node.start_mark @@ -172,15 +181,22 @@ class ESPHomeLoader(yaml.SafeLoader): # pylint: disable=too-many-ancestors for item in value: if not isinstance(item, dict): raise yaml.constructor.ConstructorError( - "While constructing a mapping", node.start_mark, - "Expected a mapping for merging, but found {}".format(type(item)), - value_node.start_mark) + "While constructing a mapping", + node.start_mark, + "Expected a mapping for merging, but found {}".format( + type(item) + ), + value_node.start_mark, + ) merge_pairs.extend(item.items()) else: raise yaml.constructor.ConstructorError( - "While constructing a mapping", node.start_mark, + "While constructing a mapping", + node.start_mark, "Expected a mapping or list of mappings for merging, " - "but found {}".format(type(value)), value_node.start_mark) + "but found {}".format(type(value)), + value_node.start_mark, + ) if merge_pairs: # We found some merge keys along the way, merge them into base pairs @@ -211,7 +227,7 @@ class ESPHomeLoader(yaml.SafeLoader): # pylint: disable=too-many-ancestors args = node.value.split() # Check for a default value if len(args) > 1: - return os.getenv(args[0], ' '.join(args[1:])) + return os.getenv(args[0], " ".join(args[1:])) if args[0] in os.environ: return os.environ[args[0]] raise yaml.MarkedYAMLError( @@ -242,12 +258,12 @@ class ESPHomeLoader(yaml.SafeLoader): # pylint: disable=too-many-ancestors @_add_data_ref def construct_include_dir_list(self, node): - files = filter_yaml_files(_find_files(self._rel_path(node.value), '*.yaml')) + files = filter_yaml_files(_find_files(self._rel_path(node.value), "*.yaml")) return [_load_yaml_internal(f) for f in files] @_add_data_ref def construct_include_dir_merge_list(self, node): - files = filter_yaml_files(_find_files(self._rel_path(node.value), '*.yaml')) + files = filter_yaml_files(_find_files(self._rel_path(node.value), "*.yaml")) merged_list = [] for fname in files: loaded_yaml = _load_yaml_internal(fname) @@ -257,7 +273,7 @@ class ESPHomeLoader(yaml.SafeLoader): # pylint: disable=too-many-ancestors @_add_data_ref def construct_include_dir_named(self, node): - files = filter_yaml_files(_find_files(self._rel_path(node.value), '*.yaml')) + files = filter_yaml_files(_find_files(self._rel_path(node.value), "*.yaml")) mapping = OrderedDict() for fname in files: filename = os.path.splitext(os.path.basename(fname))[0] @@ -266,7 +282,7 @@ class ESPHomeLoader(yaml.SafeLoader): # pylint: disable=too-many-ancestors @_add_data_ref def construct_include_dir_merge_named(self, node): - files = filter_yaml_files(_find_files(self._rel_path(node.value), '*.yaml')) + files = filter_yaml_files(_find_files(self._rel_path(node.value), "*.yaml")) mapping = OrderedDict() for fname in files: loaded_yaml = _load_yaml_internal(fname) @@ -284,24 +300,36 @@ class ESPHomeLoader(yaml.SafeLoader): # pylint: disable=too-many-ancestors return add_class_to_obj(obj, ESPForceValue) -ESPHomeLoader.add_constructor('tag:yaml.org,2002:int', ESPHomeLoader.construct_yaml_int) -ESPHomeLoader.add_constructor('tag:yaml.org,2002:float', ESPHomeLoader.construct_yaml_float) -ESPHomeLoader.add_constructor('tag:yaml.org,2002:binary', ESPHomeLoader.construct_yaml_binary) -ESPHomeLoader.add_constructor('tag:yaml.org,2002:omap', ESPHomeLoader.construct_yaml_omap) -ESPHomeLoader.add_constructor('tag:yaml.org,2002:str', ESPHomeLoader.construct_yaml_str) -ESPHomeLoader.add_constructor('tag:yaml.org,2002:seq', ESPHomeLoader.construct_yaml_seq) -ESPHomeLoader.add_constructor('tag:yaml.org,2002:map', ESPHomeLoader.construct_yaml_map) -ESPHomeLoader.add_constructor('!env_var', ESPHomeLoader.construct_env_var) -ESPHomeLoader.add_constructor('!secret', ESPHomeLoader.construct_secret) -ESPHomeLoader.add_constructor('!include', ESPHomeLoader.construct_include) -ESPHomeLoader.add_constructor('!include_dir_list', ESPHomeLoader.construct_include_dir_list) -ESPHomeLoader.add_constructor('!include_dir_merge_list', - ESPHomeLoader.construct_include_dir_merge_list) -ESPHomeLoader.add_constructor('!include_dir_named', ESPHomeLoader.construct_include_dir_named) -ESPHomeLoader.add_constructor('!include_dir_merge_named', - ESPHomeLoader.construct_include_dir_merge_named) -ESPHomeLoader.add_constructor('!lambda', ESPHomeLoader.construct_lambda) -ESPHomeLoader.add_constructor('!force', ESPHomeLoader.construct_force) +ESPHomeLoader.add_constructor("tag:yaml.org,2002:int", ESPHomeLoader.construct_yaml_int) +ESPHomeLoader.add_constructor( + "tag:yaml.org,2002:float", ESPHomeLoader.construct_yaml_float +) +ESPHomeLoader.add_constructor( + "tag:yaml.org,2002:binary", ESPHomeLoader.construct_yaml_binary +) +ESPHomeLoader.add_constructor( + "tag:yaml.org,2002:omap", ESPHomeLoader.construct_yaml_omap +) +ESPHomeLoader.add_constructor("tag:yaml.org,2002:str", ESPHomeLoader.construct_yaml_str) +ESPHomeLoader.add_constructor("tag:yaml.org,2002:seq", ESPHomeLoader.construct_yaml_seq) +ESPHomeLoader.add_constructor("tag:yaml.org,2002:map", ESPHomeLoader.construct_yaml_map) +ESPHomeLoader.add_constructor("!env_var", ESPHomeLoader.construct_env_var) +ESPHomeLoader.add_constructor("!secret", ESPHomeLoader.construct_secret) +ESPHomeLoader.add_constructor("!include", ESPHomeLoader.construct_include) +ESPHomeLoader.add_constructor( + "!include_dir_list", ESPHomeLoader.construct_include_dir_list +) +ESPHomeLoader.add_constructor( + "!include_dir_merge_list", ESPHomeLoader.construct_include_dir_merge_list +) +ESPHomeLoader.add_constructor( + "!include_dir_named", ESPHomeLoader.construct_include_dir_named +) +ESPHomeLoader.add_constructor( + "!include_dir_merge_named", ESPHomeLoader.construct_include_dir_merge_named +) +ESPHomeLoader.add_constructor("!lambda", ESPHomeLoader.construct_lambda) +ESPHomeLoader.add_constructor("!force", ESPHomeLoader.construct_force) def load_yaml(fname): @@ -324,13 +352,14 @@ def _load_yaml_internal(fname): def dump(dict_): """Dump YAML to a string and remove null.""" - return yaml.dump(dict_, default_flow_style=False, allow_unicode=True, - Dumper=ESPHomeDumper) + return yaml.dump( + dict_, default_flow_style=False, allow_unicode=True, Dumper=ESPHomeDumper + ) def _is_file_valid(name): """Decide if a file is valid.""" - return not name.startswith('.') + return not name.startswith(".") def _find_files(directory, pattern): @@ -357,7 +386,7 @@ class ESPHomeDumper(yaml.SafeDumper): # pylint: disable=too-many-ancestors if self.alias_key is not None: self.represented_objects[self.alias_key] = node best_style = True - if hasattr(mapping, 'items'): + if hasattr(mapping, "items"): mapping = list(mapping.items()) for item_key, item_value in mapping: node_key = self.represent_data(item_key) @@ -375,29 +404,31 @@ class ESPHomeDumper(yaml.SafeDumper): # pylint: disable=too-many-ancestors return node def represent_secret(self, value): - return self.represent_scalar(tag='!secret', value=_SECRET_VALUES[str(value)]) + return self.represent_scalar(tag="!secret", value=_SECRET_VALUES[str(value)]) def represent_stringify(self, value): if is_secret(value): return self.represent_secret(value) - return self.represent_scalar(tag='tag:yaml.org,2002:str', value=str(value)) + return self.represent_scalar(tag="tag:yaml.org,2002:str", value=str(value)) # pylint: disable=arguments-differ def represent_bool(self, value): - return self.represent_scalar('tag:yaml.org,2002:bool', 'true' if value else 'false') + return self.represent_scalar( + "tag:yaml.org,2002:bool", "true" if value else "false" + ) def represent_int(self, value): if is_secret(value): return self.represent_secret(value) - return self.represent_scalar(tag='tag:yaml.org,2002:int', value=str(value)) + return self.represent_scalar(tag="tag:yaml.org,2002:int", value=str(value)) def represent_float(self, value): if is_secret(value): return self.represent_secret(value) if math.isnan(value): - value = '.nan' + value = ".nan" elif math.isinf(value): - value = '.inf' if value > 0 else '-.inf' + value = ".inf" if value > 0 else "-.inf" else: value = str(repr(value)).lower() # Note that in some cases `repr(data)` represents a float number @@ -407,14 +438,14 @@ class ESPHomeDumper(yaml.SafeDumper): # pylint: disable=too-many-ancestors # Unfortunately, this is not a valid float representation according # to the definition of the `!!float` tag. We fix this by adding # '.0' before the 'e' symbol. - if '.' not in value and 'e' in value: - value = value.replace('e', '.0e', 1) - return self.represent_scalar(tag='tag:yaml.org,2002:float', value=value) + if "." not in value and "e" in value: + value = value.replace("e", ".0e", 1) + return self.represent_scalar(tag="tag:yaml.org,2002:float", value=value) def represent_lambda(self, value): if is_secret(value.value): return self.represent_secret(value.value) - return self.represent_scalar(tag='!lambda', value=value.value, style='|') + return self.represent_scalar(tag="!lambda", value=value.value, style="|") def represent_id(self, value): if is_secret(value.id): @@ -423,12 +454,11 @@ class ESPHomeDumper(yaml.SafeDumper): # pylint: disable=too-many-ancestors ESPHomeDumper.add_multi_representer( - dict, - lambda dumper, value: dumper.represent_mapping('tag:yaml.org,2002:map', value) + dict, lambda dumper, value: dumper.represent_mapping("tag:yaml.org,2002:map", value) ) ESPHomeDumper.add_multi_representer( list, - lambda dumper, value: dumper.represent_sequence('tag:yaml.org,2002:seq', value) + lambda dumper, value: dumper.represent_sequence("tag:yaml.org,2002:seq", value), ) ESPHomeDumper.add_multi_representer(bool, ESPHomeDumper.represent_bool) ESPHomeDumper.add_multi_representer(str, ESPHomeDumper.represent_stringify) diff --git a/esphome/zeroconf.py b/esphome/zeroconf.py index a8ca5b3c5..a44c7c911 100644 --- a/esphome/zeroconf.py +++ b/esphome/zeroconf.py @@ -20,7 +20,7 @@ _LISTENER_TIME = 200 # Some DNS constants -_MDNS_ADDR = '224.0.0.251' +_MDNS_ADDR = "224.0.0.251" _MDNS_PORT = 5353 _MAX_MSG_ABSOLUTE = 8966 @@ -96,7 +96,7 @@ class QuietLogger: logger = log.debug if logger_data is not None: logger(*logger_data) - logger('Exception occurred:', exc_info=True) + logger("Exception occurred:", exc_info=True) @classmethod def log_warning_once(cls, *args): @@ -129,9 +129,11 @@ class DNSQuestion(DNSEntry): def answered_by(self, rec): """Returns true if the question is answered by the record""" - return (self.class_ == rec.class_ and - (self.type == rec.type or self.type == _TYPE_ANY) and - self.name == rec.name) + return ( + self.class_ == rec.class_ + and (self.type == rec.type or self.type == _TYPE_ANY) + and self.name == rec.name + ) class DNSRecord(DNSEntry): @@ -202,26 +204,32 @@ class DNSIncoming(QuietLogger): self.valid = True except (IndexError, struct.error, IncomingDecodeError): - self.log_exception_warning(( - 'Choked at offset %d while unpacking %r', self.offset, data)) + self.log_exception_warning( + ("Choked at offset %d while unpacking %r", self.offset, data) + ) def unpack(self, format_): length = struct.calcsize(format_) - info = struct.unpack( - format_, self.data[self.offset:self.offset + length]) + info = struct.unpack(format_, self.data[self.offset : self.offset + length]) self.offset += length return info def read_header(self): """Reads header portion of packet""" - (self.id, self.flags, self.num_questions, self.num_answers, - self.num_authorities, self.num_additionals) = self.unpack(b'!6H') + ( + self.id, + self.flags, + self.num_questions, + self.num_answers, + self.num_authorities, + self.num_additionals, + ) = self.unpack(b"!6H") def read_questions(self): """Reads questions section of packet""" for _ in range(self.num_questions): name = self.read_name() - type_, class_ = self.unpack(b'!HH') + type_, class_ = self.unpack(b"!HH") question = DNSQuestion(name, type_, class_) self.questions.append(question) @@ -234,13 +242,13 @@ class DNSIncoming(QuietLogger): def read_string(self, length): """Reads a string of a given length from the packet""" - info = self.data[self.offset:self.offset + length] + info = self.data[self.offset : self.offset + length] self.offset += length return info def read_unsigned_short(self): """Reads an unsigned short from the packet""" - return self.unpack(b'!H')[0] + return self.unpack(b"!H")[0] def read_others(self): """Reads the answers, authorities and additionals section of the @@ -248,18 +256,15 @@ class DNSIncoming(QuietLogger): n = self.num_answers + self.num_authorities + self.num_additionals for _ in range(n): domain = self.read_name() - type_, class_, ttl, length = self.unpack(b'!HHiH') + type_, class_, ttl, length = self.unpack(b"!HHiH") rec = None if type_ == _TYPE_A: - rec = DNSAddress( - domain, type_, class_, ttl, self.read_string(4)) + rec = DNSAddress(domain, type_, class_, ttl, self.read_string(4)) elif type_ == _TYPE_TXT: - rec = DNSText( - domain, type_, class_, ttl, self.read_string(length)) + rec = DNSText(domain, type_, class_, ttl, self.read_string(length)) elif type_ == _TYPE_AAAA: - rec = DNSAddress( - domain, type_, class_, ttl, self.read_string(16)) + rec = DNSAddress(domain, type_, class_, ttl, self.read_string(16)) else: # Try to ignore types we don't know about # Skip the payload for the resource record so the next @@ -279,11 +284,11 @@ class DNSIncoming(QuietLogger): def read_utf(self, offset, length): """Reads a UTF-8 string of a given length from the packet""" - return str(self.data[offset:offset + length], 'utf-8', 'replace') + return str(self.data[offset : offset + length], "utf-8", "replace") def read_name(self): """Reads a domain name from the packet""" - result = '' + result = "" off = self.offset next_ = -1 first = off @@ -295,15 +300,14 @@ class DNSIncoming(QuietLogger): break t = length & 0xC0 if t == 0x00: - result = ''.join((result, self.read_utf(off, length) + '.')) + result = "".join((result, self.read_utf(off, length) + ".")) off += length elif t == 0xC0: if next_ < 0: next_ = off + 1 off = ((length & 0x3F) << 8) | self.data[off] if off >= first: - raise IncomingDecodeError( - f"Bad domain name (circular) at {off}") + raise IncomingDecodeError(f"Bad domain name (circular) at {off}") first = off else: raise IncomingDecodeError(f"Bad domain name at {off}") @@ -341,20 +345,20 @@ class DNSOutgoing: def write_byte(self, value): """Writes a single byte to the packet""" - self.pack(b'!c', int2byte(value)) + self.pack(b"!c", int2byte(value)) def insert_short(self, index, value): """Inserts an unsigned short in a certain position in the packet""" - self.data.insert(index, struct.pack(b'!H', value)) + self.data.insert(index, struct.pack(b"!H", value)) self.size += 2 def write_short(self, value): """Writes an unsigned short to the packet""" - self.pack(b'!H', value) + self.pack(b"!H", value) def write_int(self, value): """Writes an unsigned integer to the packet""" - self.pack(b'!I', int(value)) + self.pack(b"!I", int(value)) def write_string(self, value): """Writes a string to the packet""" @@ -364,7 +368,7 @@ class DNSOutgoing: def write_utf(self, s): """Writes a UTF-8 string of a given length to the packet""" - utfstr = s.encode('utf-8') + utfstr = s.encode("utf-8") length = len(utfstr) self.write_byte(length) self.write_string(utfstr) @@ -377,12 +381,12 @@ class DNSOutgoing: def write_name(self, name): # split name into each label - parts = name.split('.') + parts = name.split(".") if not parts[-1]: parts.pop() # construct each suffix - name_suffices = ['.'.join(parts[i:]) for i in range(len(parts))] + name_suffices = [".".join(parts[i:]) for i in range(len(parts))] # look for an existing name or suffix for count, sub_name in enumerate(name_suffices): @@ -392,9 +396,11 @@ class DNSOutgoing: count = len(name_suffices) # note the new names we are saving into the packet - name_length = len(name.encode('utf-8')) + name_length = len(name.encode("utf-8")) for suffix in name_suffices[:count]: - self.names[suffix] = self.size + name_length - len(suffix.encode('utf-8')) - 1 + self.names[suffix] = ( + self.size + name_length - len(suffix.encode("utf-8")) - 1 + ) # write the new names out. for part in parts[:count]: @@ -427,12 +433,12 @@ class DNSOutgoing: self.insert_short(0, len(self.questions)) self.insert_short(0, self.flags) # _FLAGS_QR_QUERY self.insert_short(0, 0) - return b''.join(self.data) + return b"".join(self.data) class Engine(threading.Thread): def __init__(self, zc): - threading.Thread.__init__(self, name='zeroconf-Engine') + threading.Thread.__init__(self, name="zeroconf-Engine") self.daemon = True self.zc = zc self.readers = {} @@ -488,7 +494,7 @@ class Listener(QuietLogger): self.log_exception_warning() return - log.debug('Received from %r:%r: %r ', addr, port, data) + log.debug("Received from %r:%r: %r ", addr, port, data) self.data = data msg = DNSIncoming(data) @@ -530,8 +536,7 @@ class HostResolver(RecordUpdateListener): return False if next_ <= now: out = DNSOutgoing(_FLAGS_QR_QUERY) - out.add_question( - DNSQuestion(self.name, _TYPE_A, _CLASS_IN)) + out.add_question(DNSQuestion(self.name, _TYPE_A, _CLASS_IN)) zc.send(out) next_ = now + delay delay *= 2 @@ -592,10 +597,12 @@ class DashboardStatus(RecordUpdateListener, threading.Thread): while not self.stop_event.is_set(): self.purge_cache() for host in self.query_hosts: - if all(record.is_expired(time.time()) for record in self.cache.get(host, [])): + if all( + record.is_expired(time.time()) + for record in self.cache.get(host, []) + ): out = DNSOutgoing(_FLAGS_QR_QUERY) - out.add_question( - DNSQuestion(host, _TYPE_A, _CLASS_IN)) + out.add_question(DNSQuestion(host, _TYPE_A, _CLASS_IN)) self.zc.send(out) self.query_event.wait() self.query_event.clear() @@ -603,12 +610,15 @@ class DashboardStatus(RecordUpdateListener, threading.Thread): def get_all_addresses(): - return list({ - addr.ip - for iface in ifaddr.get_adapters() - for addr in iface.ips - if addr.is_IPv4 and addr.network_prefix != 32 # Host only netmask 255.255.255.255 - }) + return list( + { + addr.ip + for iface in ifaddr.get_adapters() + for addr in iface.ips + if addr.is_IPv4 + and addr.network_prefix != 32 # Host only netmask 255.255.255.255 + } + ) def new_socket(): @@ -636,12 +646,12 @@ def new_socket(): # OpenBSD needs the ttl and loop values for the IP_MULTICAST_TTL and # IP_MULTICAST_LOOP socket options as an unsigned char. - ttl = struct.pack(b'B', 255) + ttl = struct.pack(b"B", 255) s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl) - loop = struct.pack(b'B', 1) + loop = struct.pack(b"B", 1) s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, loop) - s.bind(('', _MDNS_PORT)) + s.bind(("", _MDNS_PORT)) return s @@ -659,24 +669,28 @@ class Zeroconf(QuietLogger): try: _value = socket.inet_aton(_MDNS_ADDR) + socket.inet_aton(i) self._listen_socket.setsockopt( - socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, _value) + socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, _value + ) except OSError as e: _errno = e.args[0] if _errno == errno.EADDRINUSE: log.info( - 'Address in use when adding %s to multicast group, ' - 'it is expected to happen on some systems', i, + "Address in use when adding %s to multicast group, " + "it is expected to happen on some systems", + i, ) elif _errno == errno.EADDRNOTAVAIL: log.info( - 'Address not available when adding %s to multicast ' - 'group, it is expected to happen on some systems', i, + "Address not available when adding %s to multicast " + "group, it is expected to happen on some systems", + i, ) continue elif _errno == errno.EINVAL: log.info( - 'Interface of %s does not support multicast, ' - 'it is expected in WSL', i + "Interface of %s does not support multicast, " + "it is expected in WSL", + i, ) continue @@ -685,7 +699,8 @@ class Zeroconf(QuietLogger): respond_socket = new_socket() respond_socket.setsockopt( - socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(i)) + socket.IPPROTO_IP, socket.IP_MULTICAST_IF, socket.inet_aton(i) + ) self._respond_sockets.append(respond_socket) @@ -728,7 +743,7 @@ class Zeroconf(QuietLogger): self.listeners.remove(listener) self.notify_all() except Exception as e: # pylint: disable=broad-except - log.exception('Unknown error, possibly benign: %r', e) + log.exception("Unknown error, possibly benign: %r", e) def update_record(self, now, rec): """Used to notify listeners of new information that has updated @@ -747,7 +762,7 @@ class Zeroconf(QuietLogger): def send(self, out): """Sends an outgoing packet.""" packet = out.packet() - log.debug('Sending %r (%d bytes) as %r...', out, len(packet), packet) + log.debug("Sending %r (%d bytes) as %r...", out, len(packet), packet) for s in self._respond_sockets: if self._GLOBAL_DONE: return @@ -759,8 +774,9 @@ class Zeroconf(QuietLogger): else: if bytes_sent != len(packet): self.log_warning_once( - '!!! sent %d out of %d bytes to %r' % ( - bytes_sent, len(packet), s)) + "!!! sent %d out of %d bytes to %r" + % (bytes_sent, len(packet), s) + ) def close(self): """Ends the background threads, and prevent this instance from diff --git a/pylintrc b/pylintrc index 00ffdc9f9..8f2e9a735 100644 --- a/pylintrc +++ b/pylintrc @@ -3,6 +3,7 @@ reports=no ignore=api_pb2.py disable= + format, missing-docstring, fixme, unused-argument, diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..7a75060c8 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[tool.black] +target-version = ["py36", "py37", "py38"] +exclude = 'generated' diff --git a/requirements_test.txt b/requirements_test.txt index d7f8bf50a..10c838a42 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -1,8 +1,10 @@ pylint==2.7.2 flake8==3.8.4 +black==20.8b1 pillow>4.0.0 cryptography>=2.0.0,<4 pexpect==4.8.0 +pre-commit # Unit tests pytest==6.2.2 diff --git a/script/api_protobuf/api_options_pb2.py b/script/api_protobuf/api_options_pb2.py index e690a2c5d..f5297c062 100644 --- a/script/api_protobuf/api_options_pb2.py +++ b/script/api_protobuf/api_options_pb2.py @@ -2,12 +2,14 @@ # source: api_options.proto import sys -_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) + +_b = sys.version_info[0] < 3 and (lambda x: x) or (lambda x: x.encode("latin1")) from google.protobuf.internal import enum_type_wrapper from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database + # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() @@ -17,37 +19,38 @@ from google.protobuf import descriptor_pb2 as google_dot_protobuf_dot_descriptor DESCRIPTOR = _descriptor.FileDescriptor( - name='api_options.proto', - package='', - syntax='proto2', - serialized_options=None, - serialized_pb=_b('\n\x11\x61pi_options.proto\x1a google/protobuf/descriptor.proto\"\x06\n\x04void*F\n\rAPISourceType\x12\x0f\n\x0bSOURCE_BOTH\x10\x00\x12\x11\n\rSOURCE_SERVER\x10\x01\x12\x11\n\rSOURCE_CLIENT\x10\x02:E\n\x16needs_setup_connection\x12\x1e.google.protobuf.MethodOptions\x18\x8e\x08 \x01(\x08:\x04true:C\n\x14needs_authentication\x12\x1e.google.protobuf.MethodOptions\x18\x8f\x08 \x01(\x08:\x04true:/\n\x02id\x12\x1f.google.protobuf.MessageOptions\x18\x8c\x08 \x01(\r:\x01\x30:M\n\x06source\x12\x1f.google.protobuf.MessageOptions\x18\x8d\x08 \x01(\x0e\x32\x0e.APISourceType:\x0bSOURCE_BOTH:/\n\x05ifdef\x12\x1f.google.protobuf.MessageOptions\x18\x8e\x08 \x01(\t:3\n\x03log\x12\x1f.google.protobuf.MessageOptions\x18\x8f\x08 \x01(\x08:\x04true:9\n\x08no_delay\x12\x1f.google.protobuf.MessageOptions\x18\x90\x08 \x01(\x08:\x05\x66\x61lse') - , - dependencies=[google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR,]) + name="api_options.proto", + package="", + syntax="proto2", + serialized_options=None, + serialized_pb=_b( + '\n\x11\x61pi_options.proto\x1a google/protobuf/descriptor.proto"\x06\n\x04void*F\n\rAPISourceType\x12\x0f\n\x0bSOURCE_BOTH\x10\x00\x12\x11\n\rSOURCE_SERVER\x10\x01\x12\x11\n\rSOURCE_CLIENT\x10\x02:E\n\x16needs_setup_connection\x12\x1e.google.protobuf.MethodOptions\x18\x8e\x08 \x01(\x08:\x04true:C\n\x14needs_authentication\x12\x1e.google.protobuf.MethodOptions\x18\x8f\x08 \x01(\x08:\x04true:/\n\x02id\x12\x1f.google.protobuf.MessageOptions\x18\x8c\x08 \x01(\r:\x01\x30:M\n\x06source\x12\x1f.google.protobuf.MessageOptions\x18\x8d\x08 \x01(\x0e\x32\x0e.APISourceType:\x0bSOURCE_BOTH:/\n\x05ifdef\x12\x1f.google.protobuf.MessageOptions\x18\x8e\x08 \x01(\t:3\n\x03log\x12\x1f.google.protobuf.MessageOptions\x18\x8f\x08 \x01(\x08:\x04true:9\n\x08no_delay\x12\x1f.google.protobuf.MessageOptions\x18\x90\x08 \x01(\x08:\x05\x66\x61lse' + ), + dependencies=[ + google_dot_protobuf_dot_descriptor__pb2.DESCRIPTOR, + ], +) _APISOURCETYPE = _descriptor.EnumDescriptor( - name='APISourceType', - full_name='APISourceType', - filename=None, - file=DESCRIPTOR, - values=[ - _descriptor.EnumValueDescriptor( - name='SOURCE_BOTH', index=0, number=0, - serialized_options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='SOURCE_SERVER', index=1, number=1, - serialized_options=None, - type=None), - _descriptor.EnumValueDescriptor( - name='SOURCE_CLIENT', index=2, number=2, - serialized_options=None, - type=None), - ], - containing_type=None, - serialized_options=None, - serialized_start=63, - serialized_end=133, + name="APISourceType", + full_name="APISourceType", + filename=None, + file=DESCRIPTOR, + values=[ + _descriptor.EnumValueDescriptor( + name="SOURCE_BOTH", index=0, number=0, serialized_options=None, type=None + ), + _descriptor.EnumValueDescriptor( + name="SOURCE_SERVER", index=1, number=1, serialized_options=None, type=None + ), + _descriptor.EnumValueDescriptor( + name="SOURCE_CLIENT", index=2, number=2, serialized_options=None, type=None + ), + ], + containing_type=None, + serialized_options=None, + serialized_start=63, + serialized_end=133, ) _sym_db.RegisterEnumDescriptor(_APISOURCETYPE) @@ -58,105 +61,186 @@ SOURCE_CLIENT = 2 NEEDS_SETUP_CONNECTION_FIELD_NUMBER = 1038 needs_setup_connection = _descriptor.FieldDescriptor( - name='needs_setup_connection', full_name='needs_setup_connection', index=0, - number=1038, type=8, cpp_type=7, label=1, - has_default_value=True, default_value=True, - message_type=None, enum_type=None, containing_type=None, - is_extension=True, extension_scope=None, - serialized_options=None, file=DESCRIPTOR) + name="needs_setup_connection", + full_name="needs_setup_connection", + index=0, + number=1038, + type=8, + cpp_type=7, + label=1, + has_default_value=True, + default_value=True, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=True, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, +) NEEDS_AUTHENTICATION_FIELD_NUMBER = 1039 needs_authentication = _descriptor.FieldDescriptor( - name='needs_authentication', full_name='needs_authentication', index=1, - number=1039, type=8, cpp_type=7, label=1, - has_default_value=True, default_value=True, - message_type=None, enum_type=None, containing_type=None, - is_extension=True, extension_scope=None, - serialized_options=None, file=DESCRIPTOR) + name="needs_authentication", + full_name="needs_authentication", + index=1, + number=1039, + type=8, + cpp_type=7, + label=1, + has_default_value=True, + default_value=True, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=True, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, +) ID_FIELD_NUMBER = 1036 id = _descriptor.FieldDescriptor( - name='id', full_name='id', index=2, - number=1036, type=13, cpp_type=3, label=1, - has_default_value=True, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=True, extension_scope=None, - serialized_options=None, file=DESCRIPTOR) + name="id", + full_name="id", + index=2, + number=1036, + type=13, + cpp_type=3, + label=1, + has_default_value=True, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=True, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, +) SOURCE_FIELD_NUMBER = 1037 source = _descriptor.FieldDescriptor( - name='source', full_name='source', index=3, - number=1037, type=14, cpp_type=8, label=1, - has_default_value=True, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=True, extension_scope=None, - serialized_options=None, file=DESCRIPTOR) + name="source", + full_name="source", + index=3, + number=1037, + type=14, + cpp_type=8, + label=1, + has_default_value=True, + default_value=0, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=True, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, +) IFDEF_FIELD_NUMBER = 1038 ifdef = _descriptor.FieldDescriptor( - name='ifdef', full_name='ifdef', index=4, - number=1038, type=9, cpp_type=9, label=1, - has_default_value=False, default_value=_b("").decode('utf-8'), - message_type=None, enum_type=None, containing_type=None, - is_extension=True, extension_scope=None, - serialized_options=None, file=DESCRIPTOR) + name="ifdef", + full_name="ifdef", + index=4, + number=1038, + type=9, + cpp_type=9, + label=1, + has_default_value=False, + default_value=_b("").decode("utf-8"), + message_type=None, + enum_type=None, + containing_type=None, + is_extension=True, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, +) LOG_FIELD_NUMBER = 1039 log = _descriptor.FieldDescriptor( - name='log', full_name='log', index=5, - number=1039, type=8, cpp_type=7, label=1, - has_default_value=True, default_value=True, - message_type=None, enum_type=None, containing_type=None, - is_extension=True, extension_scope=None, - serialized_options=None, file=DESCRIPTOR) + name="log", + full_name="log", + index=5, + number=1039, + type=8, + cpp_type=7, + label=1, + has_default_value=True, + default_value=True, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=True, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, +) NO_DELAY_FIELD_NUMBER = 1040 no_delay = _descriptor.FieldDescriptor( - name='no_delay', full_name='no_delay', index=6, - number=1040, type=8, cpp_type=7, label=1, - has_default_value=True, default_value=False, - message_type=None, enum_type=None, containing_type=None, - is_extension=True, extension_scope=None, - serialized_options=None, file=DESCRIPTOR) + name="no_delay", + full_name="no_delay", + index=6, + number=1040, + type=8, + cpp_type=7, + label=1, + has_default_value=True, + default_value=False, + message_type=None, + enum_type=None, + containing_type=None, + is_extension=True, + extension_scope=None, + serialized_options=None, + file=DESCRIPTOR, +) _VOID = _descriptor.Descriptor( - name='void', - full_name='void', - filename=None, - file=DESCRIPTOR, - containing_type=None, - fields=[ - ], - extensions=[ - ], - nested_types=[], - enum_types=[ - ], - serialized_options=None, - is_extendable=False, - syntax='proto2', - extension_ranges=[], - oneofs=[ - ], - serialized_start=55, - serialized_end=61, + name="void", + full_name="void", + filename=None, + file=DESCRIPTOR, + containing_type=None, + fields=[], + extensions=[], + nested_types=[], + enum_types=[], + serialized_options=None, + is_extendable=False, + syntax="proto2", + extension_ranges=[], + oneofs=[], + serialized_start=55, + serialized_end=61, ) -DESCRIPTOR.message_types_by_name['void'] = _VOID -DESCRIPTOR.enum_types_by_name['APISourceType'] = _APISOURCETYPE -DESCRIPTOR.extensions_by_name['needs_setup_connection'] = needs_setup_connection -DESCRIPTOR.extensions_by_name['needs_authentication'] = needs_authentication -DESCRIPTOR.extensions_by_name['id'] = id -DESCRIPTOR.extensions_by_name['source'] = source -DESCRIPTOR.extensions_by_name['ifdef'] = ifdef -DESCRIPTOR.extensions_by_name['log'] = log -DESCRIPTOR.extensions_by_name['no_delay'] = no_delay +DESCRIPTOR.message_types_by_name["void"] = _VOID +DESCRIPTOR.enum_types_by_name["APISourceType"] = _APISOURCETYPE +DESCRIPTOR.extensions_by_name["needs_setup_connection"] = needs_setup_connection +DESCRIPTOR.extensions_by_name["needs_authentication"] = needs_authentication +DESCRIPTOR.extensions_by_name["id"] = id +DESCRIPTOR.extensions_by_name["source"] = source +DESCRIPTOR.extensions_by_name["ifdef"] = ifdef +DESCRIPTOR.extensions_by_name["log"] = log +DESCRIPTOR.extensions_by_name["no_delay"] = no_delay _sym_db.RegisterFileDescriptor(DESCRIPTOR) -void = _reflection.GeneratedProtocolMessageType('void', (_message.Message,), dict( - DESCRIPTOR = _VOID, - __module__ = 'api_options_pb2' - # @@protoc_insertion_point(class_scope:void) - )) +void = _reflection.GeneratedProtocolMessageType( + "void", + (_message.Message,), + dict( + DESCRIPTOR=_VOID, + __module__="api_options_pb2" + # @@protoc_insertion_point(class_scope:void) + ), +) _sym_db.RegisterMessage(void) -google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension(needs_setup_connection) -google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension(needs_authentication) +google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension( + needs_setup_connection +) +google_dot_protobuf_dot_descriptor__pb2.MethodOptions.RegisterExtension( + needs_authentication +) google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(id) source.enum_type = _APISOURCETYPE google_dot_protobuf_dot_descriptor__pb2.MessageOptions.RegisterExtension(source) diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index e78eff76c..f86145df2 100644 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -27,39 +27,39 @@ from subprocess import call import api_options_pb2 as pb import google.protobuf.descriptor_pb2 as descriptor -file_header = '// This file was automatically generated with a tool.\n' -file_header += '// See scripts/api_protobuf/api_protobuf.py\n' +file_header = "// This file was automatically generated with a tool.\n" +file_header += "// See scripts/api_protobuf/api_protobuf.py\n" cwd = Path(__file__).resolve().parent -root = cwd.parent.parent / 'esphome' / 'components' / 'api' -prot = root / 'api.protoc' -call(['protoc', '-o', str(prot), '-I', str(root), 'api.proto']) +root = cwd.parent.parent / "esphome" / "components" / "api" +prot = root / "api.protoc" +call(["protoc", "-o", str(prot), "-I", str(root), "api.proto"]) content = prot.read_bytes() d = descriptor.FileDescriptorSet.FromString(content) -def indent_list(text, padding=' '): +def indent_list(text, padding=" "): return [padding + line for line in text.splitlines()] -def indent(text, padding=' '): - return '\n'.join(indent_list(text, padding)) +def indent(text, padding=" "): + return "\n".join(indent_list(text, padding)) def camel_to_snake(name): # https://stackoverflow.com/a/1176023 - s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name) - return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower() + s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name) + return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower() -class TypeInfo(): +class TypeInfo: def __init__(self, field): self._field = field @property def default_value(self): - return '' + return "" @property def name(self): @@ -87,11 +87,11 @@ class TypeInfo(): @property def reference_type(self): - return f'{self.cpp_type} ' + return f"{self.cpp_type} " @property def const_reference_type(self): - return f'{self.cpp_type} ' + return f"{self.cpp_type} " @property def public_content(self) -> str: @@ -103,18 +103,20 @@ class TypeInfo(): @property def class_member(self) -> str: - return f'{self.cpp_type} {self.field_name}{{{self.default_value}}}; // NOLINT' + return f"{self.cpp_type} {self.field_name}{{{self.default_value}}}; // NOLINT" @property def decode_varint_content(self) -> str: content = self.decode_varint if content is None: return None - return dedent(f'''\ + return dedent( + f"""\ case {self.number}: {{ this->{self.field_name} = {content}; return true; - }}''') + }}""" + ) decode_varint = None @@ -123,11 +125,13 @@ class TypeInfo(): content = self.decode_length if content is None: return None - return dedent(f'''\ + return dedent( + f"""\ case {self.number}: {{ this->{self.field_name} = {content}; return true; - }}''') + }}""" + ) decode_length = None @@ -136,11 +140,13 @@ class TypeInfo(): content = self.decode_32bit if content is None: return None - return dedent(f'''\ + return dedent( + f"""\ case {self.number}: {{ this->{self.field_name} = {content}; return true; - }}''') + }}""" + ) decode_32bit = None @@ -149,24 +155,26 @@ class TypeInfo(): content = self.decode_64bit if content is None: return None - return dedent(f'''\ + return dedent( + f"""\ case {self.number}: {{ this->{self.field_name} = {content}; return true; - }}''') + }}""" + ) decode_64bit = None @property def encode_content(self): - return f'buffer.{self.encode_func}({self.number}, this->{self.field_name});' + return f"buffer.{self.encode_func}({self.number}, this->{self.field_name});" encode_func = None @property def dump_content(self): o = f'out.append(" {self.name}: ");\n' - o += self.dump(f'this->{self.field_name}') + '\n' + o += self.dump(f"this->{self.field_name}") + "\n" o += f'out.append("\\n");\n' return o @@ -186,115 +194,115 @@ def register_type(name): @register_type(1) class DoubleType(TypeInfo): - cpp_type = 'double' - default_value = '0.0' - decode_64bit = 'value.as_double()' - encode_func = 'encode_double' + cpp_type = "double" + default_value = "0.0" + decode_64bit = "value.as_double()" + encode_func = "encode_double" def dump(self, name): o = f'sprintf(buffer, "%g", {name});\n' - o += f'out.append(buffer);' + o += f"out.append(buffer);" return o @register_type(2) class FloatType(TypeInfo): - cpp_type = 'float' - default_value = '0.0f' - decode_32bit = 'value.as_float()' - encode_func = 'encode_float' + cpp_type = "float" + default_value = "0.0f" + decode_32bit = "value.as_float()" + encode_func = "encode_float" def dump(self, name): o = f'sprintf(buffer, "%g", {name});\n' - o += f'out.append(buffer);' + o += f"out.append(buffer);" return o @register_type(3) class Int64Type(TypeInfo): - cpp_type = 'int64_t' - default_value = '0' - decode_varint = 'value.as_int64()' - encode_func = 'encode_int64' + cpp_type = "int64_t" + default_value = "0" + decode_varint = "value.as_int64()" + encode_func = "encode_int64" def dump(self, name): o = f'sprintf(buffer, "%ll", {name});\n' - o += f'out.append(buffer);' + o += f"out.append(buffer);" return o @register_type(4) class UInt64Type(TypeInfo): - cpp_type = 'uint64_t' - default_value = '0' - decode_varint = 'value.as_uint64()' - encode_func = 'encode_uint64' + cpp_type = "uint64_t" + default_value = "0" + decode_varint = "value.as_uint64()" + encode_func = "encode_uint64" def dump(self, name): o = f'sprintf(buffer, "%ull", {name});\n' - o += f'out.append(buffer);' + o += f"out.append(buffer);" return o @register_type(5) class Int32Type(TypeInfo): - cpp_type = 'int32_t' - default_value = '0' - decode_varint = 'value.as_int32()' - encode_func = 'encode_int32' + cpp_type = "int32_t" + default_value = "0" + decode_varint = "value.as_int32()" + encode_func = "encode_int32" def dump(self, name): o = f'sprintf(buffer, "%d", {name});\n' - o += f'out.append(buffer);' + o += f"out.append(buffer);" return o @register_type(6) class Fixed64Type(TypeInfo): - cpp_type = 'uint64_t' - default_value = '0' - decode_64bit = 'value.as_fixed64()' - encode_func = 'encode_fixed64' + cpp_type = "uint64_t" + default_value = "0" + decode_64bit = "value.as_fixed64()" + encode_func = "encode_fixed64" def dump(self, name): o = f'sprintf(buffer, "%ull", {name});\n' - o += f'out.append(buffer);' + o += f"out.append(buffer);" return o @register_type(7) class Fixed32Type(TypeInfo): - cpp_type = 'uint32_t' - default_value = '0' - decode_32bit = 'value.as_fixed32()' - encode_func = 'encode_fixed32' + cpp_type = "uint32_t" + default_value = "0" + decode_32bit = "value.as_fixed32()" + encode_func = "encode_fixed32" def dump(self, name): o = f'sprintf(buffer, "%u", {name});\n' - o += f'out.append(buffer);' + o += f"out.append(buffer);" return o @register_type(8) class BoolType(TypeInfo): - cpp_type = 'bool' - default_value = 'false' - decode_varint = 'value.as_bool()' - encode_func = 'encode_bool' + cpp_type = "bool" + default_value = "false" + decode_varint = "value.as_bool()" + encode_func = "encode_bool" def dump(self, name): - o = f'out.append(YESNO({name}));' + o = f"out.append(YESNO({name}));" return o @register_type(9) class StringType(TypeInfo): - cpp_type = 'std::string' - default_value = '' - reference_type = 'std::string &' - const_reference_type = 'const std::string &' - decode_length = 'value.as_string()' - encode_func = 'encode_string' + cpp_type = "std::string" + default_value = "" + reference_type = "std::string &" + const_reference_type = "const std::string &" + decode_length = "value.as_string()" + encode_func = "encode_string" def dump(self, name): o = f'out.append("\'").append({name}).append("\'");' @@ -307,37 +315,37 @@ class MessageType(TypeInfo): def cpp_type(self): return self._field.type_name[1:] - default_value = '' + default_value = "" @property def reference_type(self): - return f'{self.cpp_type} &' + return f"{self.cpp_type} &" @property def const_reference_type(self): - return f'const {self.cpp_type} &' + return f"const {self.cpp_type} &" @property def encode_func(self): - return f'encode_message<{self.cpp_type}>' + return f"encode_message<{self.cpp_type}>" @property def decode_length(self): - return f'value.as_message<{self.cpp_type}>()' + return f"value.as_message<{self.cpp_type}>()" def dump(self, name): - o = f'{name}.dump_to(out);' + o = f"{name}.dump_to(out);" return o @register_type(12) class BytesType(TypeInfo): - cpp_type = 'std::string' - default_value = '' - reference_type = 'std::string &' - const_reference_type = 'const std::string &' - decode_length = 'value.as_string()' - encode_func = 'encode_string' + cpp_type = "std::string" + default_value = "" + reference_type = "std::string &" + const_reference_type = "const std::string &" + decode_length = "value.as_string()" + encode_func = "encode_string" def dump(self, name): o = f'out.append("\'").append({name}).append("\'");' @@ -346,14 +354,14 @@ class BytesType(TypeInfo): @register_type(13) class UInt32Type(TypeInfo): - cpp_type = 'uint32_t' - default_value = '0' - decode_varint = 'value.as_uint32()' - encode_func = 'encode_uint32' + cpp_type = "uint32_t" + default_value = "0" + decode_varint = "value.as_uint32()" + encode_func = "encode_uint32" def dump(self, name): o = f'sprintf(buffer, "%u", {name});\n' - o += f'out.append(buffer);' + o += f"out.append(buffer);" return o @@ -361,72 +369,72 @@ class UInt32Type(TypeInfo): class EnumType(TypeInfo): @property def cpp_type(self): - return f'enums::{self._field.type_name[1:]}' + return f"enums::{self._field.type_name[1:]}" @property def decode_varint(self): - return f'value.as_enum<{self.cpp_type}>()' + return f"value.as_enum<{self.cpp_type}>()" - default_value = '' + default_value = "" @property def encode_func(self): - return f'encode_enum<{self.cpp_type}>' + return f"encode_enum<{self.cpp_type}>" def dump(self, name): - o = f'out.append(proto_enum_to_string<{self.cpp_type}>({name}));' + o = f"out.append(proto_enum_to_string<{self.cpp_type}>({name}));" return o @register_type(15) class SFixed32Type(TypeInfo): - cpp_type = 'int32_t' - default_value = '0' - decode_32bit = 'value.as_sfixed32()' - encode_func = 'encode_sfixed32' + cpp_type = "int32_t" + default_value = "0" + decode_32bit = "value.as_sfixed32()" + encode_func = "encode_sfixed32" def dump(self, name): o = f'sprintf(buffer, "%d", {name});\n' - o += f'out.append(buffer);' + o += f"out.append(buffer);" return o @register_type(16) class SFixed64Type(TypeInfo): - cpp_type = 'int64_t' - default_value = '0' - decode_64bit = 'value.as_sfixed64()' - encode_func = 'encode_sfixed64' + cpp_type = "int64_t" + default_value = "0" + decode_64bit = "value.as_sfixed64()" + encode_func = "encode_sfixed64" def dump(self, name): o = f'sprintf(buffer, "%ll", {name});\n' - o += f'out.append(buffer);' + o += f"out.append(buffer);" return o @register_type(17) class SInt32Type(TypeInfo): - cpp_type = 'int32_t' - default_value = '0' - decode_varint = 'value.as_sint32()' - encode_func = 'encode_sint32' + cpp_type = "int32_t" + default_value = "0" + decode_varint = "value.as_sint32()" + encode_func = "encode_sint32" def dump(self, name): o = f'sprintf(buffer, "%d", {name});\n' - o += f'out.append(buffer);' + o += f"out.append(buffer);" return o @register_type(18) class SInt64Type(TypeInfo): - cpp_type = 'int64_t' - default_value = '0' - decode_varint = 'value.as_sint64()' - encode_func = 'encode_sin64' + cpp_type = "int64_t" + default_value = "0" + decode_varint = "value.as_sint64()" + encode_func = "encode_sin64" def dump(self): o = f'sprintf(buffer, "%ll", {name});\n' - o += f'out.append(buffer);' + o += f"out.append(buffer);" return o @@ -437,59 +445,67 @@ class RepeatedTypeInfo(TypeInfo): @property def cpp_type(self): - return f'std::vector<{self._ti.cpp_type}>' + return f"std::vector<{self._ti.cpp_type}>" @property def reference_type(self): - return f'{self.cpp_type} &' + return f"{self.cpp_type} &" @property def const_reference_type(self): - return f'const {self.cpp_type} &' + return f"const {self.cpp_type} &" @property def decode_varint_content(self) -> str: content = self._ti.decode_varint if content is None: return None - return dedent(f'''\ + return dedent( + f"""\ case {self.number}: {{ this->{self.field_name}.push_back({content}); return true; - }}''') + }}""" + ) @property def decode_length_content(self) -> str: content = self._ti.decode_length if content is None: return None - return dedent(f'''\ + return dedent( + f"""\ case {self.number}: {{ this->{self.field_name}.push_back({content}); return true; - }}''') + }}""" + ) @property def decode_32bit_content(self) -> str: content = self._ti.decode_32bit if content is None: return None - return dedent(f'''\ + return dedent( + f"""\ case {self.number}: {{ this->{self.field_name}.push_back({content}); return true; - }}''') + }}""" + ) @property def decode_64bit_content(self) -> str: content = self._ti.decode_64bit if content is None: return None - return dedent(f'''\ + return dedent( + f"""\ case {self.number}: {{ this->{self.field_name}.push_back({content}); return true; - }}''') + }}""" + ) @property def _ti_is_bool(self): @@ -507,9 +523,9 @@ class RepeatedTypeInfo(TypeInfo): def dump_content(self): o = f'for (const auto {"" if self._ti_is_bool else "&"}it : this->{self.field_name}) {{\n' o += f' out.append(" {self.name}: ");\n' - o += indent(self._ti.dump('it')) + '\n' + o += indent(self._ti.dump("it")) + "\n" o += f' out.append("\\n");\n' - o += f'}}\n' + o += f"}}\n" return o @@ -517,8 +533,8 @@ def build_enum_type(desc): name = desc.name out = f"enum {name} : uint32_t {{\n" for v in desc.value: - out += f' {v.name} = {v.number},\n' - out += '};\n' + out += f" {v.name} = {v.number},\n" + out += "};\n" cpp = f"template<>\n" cpp += f"const char *proto_enum_to_string(enums::{name} value) {{\n" @@ -526,8 +542,8 @@ def build_enum_type(desc): for v in desc.value: cpp += f' case enums::{v.name}: return "{v.name}";\n' cpp += f' default: return "UNKNOWN";\n' - cpp += f' }}\n' - cpp += f'}}\n' + cpp += f" }}\n" + cpp += f"}}\n" return out, cpp @@ -562,80 +578,80 @@ def build_message_type(desc): if ti.dump_content: dump.append(ti.dump_content) - cpp = '' + cpp = "" if decode_varint: - decode_varint.append('default:\n return false;') - o = f'bool {desc.name}::decode_varint(uint32_t field_id, ProtoVarInt value) {{\n' - o += ' switch (field_id) {\n' - o += indent("\n".join(decode_varint), ' ') + '\n' - o += ' }\n' - o += '}\n' + decode_varint.append("default:\n return false;") + o = f"bool {desc.name}::decode_varint(uint32_t field_id, ProtoVarInt value) {{\n" + o += " switch (field_id) {\n" + o += indent("\n".join(decode_varint), " ") + "\n" + o += " }\n" + o += "}\n" cpp += o - prot = 'bool decode_varint(uint32_t field_id, ProtoVarInt value) override;' + prot = "bool decode_varint(uint32_t field_id, ProtoVarInt value) override;" protected_content.insert(0, prot) if decode_length: - decode_length.append('default:\n return false;') - o = f'bool {desc.name}::decode_length(uint32_t field_id, ProtoLengthDelimited value) {{\n' - o += ' switch (field_id) {\n' - o += indent("\n".join(decode_length), ' ') + '\n' - o += ' }\n' - o += '}\n' + decode_length.append("default:\n return false;") + o = f"bool {desc.name}::decode_length(uint32_t field_id, ProtoLengthDelimited value) {{\n" + o += " switch (field_id) {\n" + o += indent("\n".join(decode_length), " ") + "\n" + o += " }\n" + o += "}\n" cpp += o - prot = 'bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;' + prot = "bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;" protected_content.insert(0, prot) if decode_32bit: - decode_32bit.append('default:\n return false;') - o = f'bool {desc.name}::decode_32bit(uint32_t field_id, Proto32Bit value) {{\n' - o += ' switch (field_id) {\n' - o += indent("\n".join(decode_32bit), ' ') + '\n' - o += ' }\n' - o += '}\n' + decode_32bit.append("default:\n return false;") + o = f"bool {desc.name}::decode_32bit(uint32_t field_id, Proto32Bit value) {{\n" + o += " switch (field_id) {\n" + o += indent("\n".join(decode_32bit), " ") + "\n" + o += " }\n" + o += "}\n" cpp += o - prot = 'bool decode_32bit(uint32_t field_id, Proto32Bit value) override;' + prot = "bool decode_32bit(uint32_t field_id, Proto32Bit value) override;" protected_content.insert(0, prot) if decode_64bit: - decode_64bit.append('default:\n return false;') - o = f'bool {desc.name}::decode_64bit(uint32_t field_id, Proto64bit value) {{\n' - o += ' switch (field_id) {\n' - o += indent("\n".join(decode_64bit), ' ') + '\n' - o += ' }\n' - o += '}\n' + decode_64bit.append("default:\n return false;") + o = f"bool {desc.name}::decode_64bit(uint32_t field_id, Proto64bit value) {{\n" + o += " switch (field_id) {\n" + o += indent("\n".join(decode_64bit), " ") + "\n" + o += " }\n" + o += "}\n" cpp += o - prot = 'bool decode_64bit(uint32_t field_id, Proto64bit value) override;' + prot = "bool decode_64bit(uint32_t field_id, Proto64bit value) override;" protected_content.insert(0, prot) o = f"void {desc.name}::encode(ProtoWriteBuffer buffer) const {{\n" - o += indent('\n'.join(encode)) + '\n' - o += '}\n' + o += indent("\n".join(encode)) + "\n" + o += "}\n" cpp += o - prot = 'void encode(ProtoWriteBuffer buffer) const override;' + prot = "void encode(ProtoWriteBuffer buffer) const override;" public_content.append(prot) o = f"void {desc.name}::dump_to(std::string &out) const {{\n" if dump: o += f" char buffer[64];\n" o += f' out.append("{desc.name} {{\\n");\n' - o += indent('\n'.join(dump)) + '\n' + o += indent("\n".join(dump)) + "\n" o += f' out.append("}}");\n' else: o += f' out.append("{desc.name} {{}}");\n' - o += '}\n' + o += "}\n" cpp += o - prot = 'void dump_to(std::string &out) const override;' + prot = "void dump_to(std::string &out) const override;" public_content.append(prot) out = f"class {desc.name} : public ProtoMessage {{\n" - out += ' public:\n' - out += indent('\n'.join(public_content)) + '\n' - out += ' protected:\n' - out += indent('\n'.join(protected_content)) + '\n' + out += " public:\n" + out += indent("\n".join(public_content)) + "\n" + out += " protected:\n" + out += indent("\n".join(protected_content)) + "\n" out += "};\n" return out, cpp file = d.file[0] content = file_header -content += '''\ +content += """\ #pragma once #include "proto.h" @@ -643,26 +659,26 @@ content += '''\ namespace esphome { namespace api { -''' +""" cpp = file_header -cpp += '''\ +cpp += """\ #include "api_pb2.h" #include "esphome/core/log.h" namespace esphome { namespace api { -''' +""" -content += 'namespace enums {\n\n' +content += "namespace enums {\n\n" for enum in file.enum_type: s, c = build_enum_type(enum) content += s cpp += c -content += '\n} // namespace enums\n\n' +content += "\n} // namespace enums\n\n" mt = file.message_type @@ -671,21 +687,21 @@ for m in mt: content += s cpp += c -content += '''\ +content += """\ } // namespace api } // namespace esphome -''' -cpp += '''\ +""" +cpp += """\ } // namespace api } // namespace esphome -''' +""" -with open(root / 'api_pb2.h', 'w') as f: +with open(root / "api_pb2.h", "w") as f: f.write(content) -with open(root / 'api_pb2.cpp', 'w') as f: +with open(root / "api_pb2.cpp", "w") as f: f.write(cpp) SOURCE_BOTH = 0 @@ -694,7 +710,7 @@ SOURCE_CLIENT = 2 RECEIVE_CASES = {} -class_name = 'APIServerConnectionBase' +class_name = "APIServerConnectionBase" ifdefs = {} @@ -716,50 +732,50 @@ def build_service_message_type(mt): ifdef = get_opt(mt, pb.ifdef) log = get_opt(mt, pb.log, True) nodelay = get_opt(mt, pb.no_delay, False) - hout = '' - cout = '' + hout = "" + cout = "" if ifdef is not None: ifdefs[str(mt.name)] = ifdef - hout += f'#ifdef {ifdef}\n' - cout += f'#ifdef {ifdef}\n' + hout += f"#ifdef {ifdef}\n" + cout += f"#ifdef {ifdef}\n" if source in (SOURCE_BOTH, SOURCE_SERVER): # Generate send - func = f'send_{snake}' - hout += f'bool {func}(const {mt.name} &msg);\n' - cout += f'bool {class_name}::{func}(const {mt.name} &msg) {{\n' + func = f"send_{snake}" + hout += f"bool {func}(const {mt.name} &msg);\n" + cout += f"bool {class_name}::{func}(const {mt.name} &msg) {{\n" if log: cout += f' ESP_LOGVV(TAG, "{func}: %s", msg.dump().c_str());\n' # cout += f' this->set_nodelay({str(nodelay).lower()});\n' - cout += f' return this->send_message_<{mt.name}>(msg, {id_});\n' - cout += f'}}\n' + cout += f" return this->send_message_<{mt.name}>(msg, {id_});\n" + cout += f"}}\n" if source in (SOURCE_BOTH, SOURCE_CLIENT): # Generate receive - func = f'on_{snake}' - hout += f'virtual void {func}(const {mt.name} &value){{}};\n' - case = '' + func = f"on_{snake}" + hout += f"virtual void {func}(const {mt.name} &value){{}};\n" + case = "" if ifdef is not None: - case += f'#ifdef {ifdef}\n' - case += f'{mt.name} msg;\n' - case += f'msg.decode(msg_data, msg_size);\n' + case += f"#ifdef {ifdef}\n" + case += f"{mt.name} msg;\n" + case += f"msg.decode(msg_data, msg_size);\n" if log: case += f'ESP_LOGVV(TAG, "{func}: %s", msg.dump().c_str());\n' - case += f'this->{func}(msg);\n' + case += f"this->{func}(msg);\n" if ifdef is not None: - case += f'#endif\n' - case += 'break;' + case += f"#endif\n" + case += "break;" RECEIVE_CASES[id_] = case if ifdef is not None: - hout += f'#endif\n' - cout += f'#endif\n' + hout += f"#endif\n" + cout += f"#endif\n" return hout, cout hpp = file_header -hpp += '''\ +hpp += """\ #pragma once #include "api_pb2.h" @@ -768,10 +784,10 @@ hpp += '''\ namespace esphome { namespace api { -''' +""" cpp = file_header -cpp += '''\ +cpp += """\ #include "api_pb2_service.h" #include "esphome/core/log.h" @@ -780,113 +796,113 @@ namespace api { static const char *TAG = "api.service"; -''' +""" -hpp += f'class {class_name} : public ProtoService {{\n' -hpp += ' public:\n' +hpp += f"class {class_name} : public ProtoService {{\n" +hpp += " public:\n" for mt in file.message_type: obj = build_service_message_type(mt) if obj is None: continue hout, cout = obj - hpp += indent(hout) + '\n' + hpp += indent(hout) + "\n" cpp += cout cases = list(RECEIVE_CASES.items()) cases.sort() -hpp += ' protected:\n' -hpp += f' bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override;\n' -out = f'bool {class_name}::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) {{\n' -out += f' switch(msg_type) {{\n' +hpp += " protected:\n" +hpp += f" bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override;\n" +out = f"bool {class_name}::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) {{\n" +out += f" switch(msg_type) {{\n" for i, case in cases: - c = f'case {i}: {{\n' - c += indent(case) + '\n' - c += f'}}' - out += indent(c, ' ') + '\n' -out += ' default: \n' -out += ' return false;\n' -out += ' }\n' -out += ' return true;\n' -out += '}\n' + c = f"case {i}: {{\n" + c += indent(case) + "\n" + c += f"}}" + out += indent(c, " ") + "\n" +out += " default: \n" +out += " return false;\n" +out += " }\n" +out += " return true;\n" +out += "}\n" cpp += out -hpp += '};\n' +hpp += "};\n" serv = file.service[0] -class_name = 'APIServerConnection' -hpp += '\n' -hpp += f'class {class_name} : public {class_name}Base {{\n' -hpp += ' public:\n' -hpp_protected = '' -cpp += '\n' +class_name = "APIServerConnection" +hpp += "\n" +hpp += f"class {class_name} : public {class_name}Base {{\n" +hpp += " public:\n" +hpp_protected = "" +cpp += "\n" m = serv.method[0] for m in serv.method: func = m.name inp = m.input_type[1:] ret = m.output_type[1:] - is_void = ret == 'void' + is_void = ret == "void" snake = camel_to_snake(inp) - on_func = f'on_{snake}' + on_func = f"on_{snake}" needs_conn = get_opt(m, pb.needs_setup_connection, True) needs_auth = get_opt(m, pb.needs_authentication, True) ifdef = ifdefs.get(inp, None) if ifdef is not None: - hpp += f'#ifdef {ifdef}\n' - hpp_protected += f'#ifdef {ifdef}\n' - cpp += f'#ifdef {ifdef}\n' + hpp += f"#ifdef {ifdef}\n" + hpp_protected += f"#ifdef {ifdef}\n" + cpp += f"#ifdef {ifdef}\n" - hpp_protected += f' void {on_func}(const {inp} &msg) override;\n' - hpp += f' virtual {ret} {func}(const {inp} &msg) = 0;\n' - cpp += f'void {class_name}::{on_func}(const {inp} &msg) {{\n' - body = '' + hpp_protected += f" void {on_func}(const {inp} &msg) override;\n" + hpp += f" virtual {ret} {func}(const {inp} &msg) = 0;\n" + cpp += f"void {class_name}::{on_func}(const {inp} &msg) {{\n" + body = "" if needs_conn: - body += 'if (!this->is_connection_setup()) {\n' - body += ' this->on_no_setup_connection();\n' - body += ' return;\n' - body += '}\n' + body += "if (!this->is_connection_setup()) {\n" + body += " this->on_no_setup_connection();\n" + body += " return;\n" + body += "}\n" if needs_auth: - body += 'if (!this->is_authenticated()) {\n' - body += ' this->on_unauthenticated_access();\n' - body += ' return;\n' - body += '}\n' + body += "if (!this->is_authenticated()) {\n" + body += " this->on_unauthenticated_access();\n" + body += " return;\n" + body += "}\n" if is_void: - body += f'this->{func}(msg);\n' + body += f"this->{func}(msg);\n" else: - body += f'{ret} ret = this->{func}(msg);\n' + body += f"{ret} ret = this->{func}(msg);\n" ret_snake = camel_to_snake(ret) - body += f'if (!this->send_{ret_snake}(ret)) {{\n' - body += f' this->on_fatal_error();\n' - body += '}\n' - cpp += indent(body) + '\n' + '}\n' + body += f"if (!this->send_{ret_snake}(ret)) {{\n" + body += f" this->on_fatal_error();\n" + body += "}\n" + cpp += indent(body) + "\n" + "}\n" if ifdef is not None: - hpp += f'#endif\n' - hpp_protected += f'#endif\n' - cpp += f'#endif\n' + hpp += f"#endif\n" + hpp_protected += f"#endif\n" + cpp += f"#endif\n" -hpp += ' protected:\n' +hpp += " protected:\n" hpp += hpp_protected -hpp += '};\n' +hpp += "};\n" -hpp += '''\ +hpp += """\ } // namespace api } // namespace esphome -''' -cpp += '''\ +""" +cpp += """\ } // namespace api } // namespace esphome -''' +""" -with open(root / 'api_pb2_service.h', 'w') as f: +with open(root / "api_pb2_service.h", "w") as f: f.write(hpp) -with open(root / 'api_pb2_service.cpp', 'w') as f: +with open(root / "api_pb2_service.cpp", "w") as f: f.write(cpp) prot.unlink() diff --git a/script/build_codeowners.py b/script/build_codeowners.py index f21e9ca2a..a1e8d6904 100755 --- a/script/build_codeowners.py +++ b/script/build_codeowners.py @@ -9,13 +9,14 @@ from esphome.config import get_component, get_platform from esphome.core import CORE parser = argparse.ArgumentParser() -parser.add_argument('--check', help="Check if the CODEOWNERS file is up to date.", - action='store_true') +parser.add_argument( + "--check", help="Check if the CODEOWNERS file is up to date.", action="store_true" +) args = parser.parse_args() # The root directory of the repo root = Path(__file__).parent.parent -components_dir = root / 'esphome' / 'components' +components_dir = root / "esphome" / "components" BASE = """ # This file is generated by script/build_codeowners.py @@ -43,16 +44,18 @@ codeowners = defaultdict(list) for path in components_dir.iterdir(): if not path.is_dir(): continue - if not (path / '__init__.py').is_file(): + if not (path / "__init__.py").is_file(): continue name = path.name comp = get_component(name) if comp is None: - print(f'Cannot find component {name}. Make sure current path is pip installed ESPHome') + print( + f"Cannot find component {name}. Make sure current path is pip installed ESPHome" + ) sys.exit(1) - codeowners[f'esphome/components/{name}/*'].extend(comp.codeowners) + codeowners[f"esphome/components/{name}/*"].extend(comp.codeowners) for platform_path in path.iterdir(): platform_name = platform_path.stem @@ -62,15 +65,17 @@ for path in components_dir.iterdir(): if platform_path.is_dir(): # Sub foldered platforms get their own line - if not (platform_path / '__init__.py').is_file(): + if not (platform_path / "__init__.py").is_file(): continue - codeowners[f'esphome/components/{name}/{platform_name}/*'].extend(platform.codeowners) + codeowners[f"esphome/components/{name}/{platform_name}/*"].extend( + platform.codeowners + ) continue # Non-subfoldered platforms add to codeowners at component level - if not platform_path.is_file() or platform_path.name == '__init__.py': + if not platform_path.is_file() or platform_path.name == "__init__.py": continue - codeowners[f'esphome/components/{name}/*'].extend(platform.codeowners) + codeowners[f"esphome/components/{name}/*"].extend(platform.codeowners) for path, owners in sorted(codeowners.items()): @@ -78,16 +83,18 @@ for path, owners in sorted(codeowners.items()): if not owners: continue for owner in owners: - if not owner.startswith('@'): - print(f"Codeowner {owner} for integration {path} must start with an '@' symbol!") + if not owner.startswith("@"): + print( + f"Codeowner {owner} for integration {path} must start with an '@' symbol!" + ) sys.exit(1) parts.append(f"{path} {' '.join(owners)}") # End newline -parts.append('') -content = '\n'.join(parts) -codeowners_file = root / 'CODEOWNERS' +parts.append("") +content = "\n".join(parts) +codeowners_file = root / "CODEOWNERS" if args.check: if codeowners_file.read_text() != content: diff --git a/script/build_compile_commands.py b/script/build_compile_commands.py index f0fc48ad9..4ac14f08b 100755 --- a/script/build_compile_commands.py +++ b/script/build_compile_commands.py @@ -12,5 +12,5 @@ def main(): print("Done.") -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/bump-docker-base-version.py b/script/bump-docker-base-version.py index 178643cea..765a330ce 100755 --- a/script/bump-docker-base-version.py +++ b/script/bump-docker-base-version.py @@ -17,36 +17,32 @@ def sub(path, pattern, repl, expected_count=1): def write_version(version: str): for p in [ - ".github/workflows/ci-docker.yml", - ".github/workflows/release-dev.yml", - ".github/workflows/release.yml" + ".github/workflows/ci-docker.yml", + ".github/workflows/release-dev.yml", + ".github/workflows/release.yml", ]: - sub( - p, - r'base_version=".*"', - f'base_version="{version}"' - ) + sub(p, r'base_version=".*"', f'base_version="{version}"') sub( "docker/Dockerfile", r"ARG BUILD_FROM=esphome/esphome-base-amd64:.*", - f"ARG BUILD_FROM=esphome/esphome-base-amd64:{version}" + f"ARG BUILD_FROM=esphome/esphome-base-amd64:{version}", ) sub( "docker/Dockerfile.dev", r"FROM esphome/esphome-base-amd64:.*", - f"FROM esphome/esphome-base-amd64:{version}" + f"FROM esphome/esphome-base-amd64:{version}", ) sub( "docker/Dockerfile.lint", r"FROM esphome/esphome-lint-base:.*", - f"FROM esphome/esphome-lint-base:{version}" + f"FROM esphome/esphome-lint-base:{version}", ) def main(): parser = argparse.ArgumentParser() - parser.add_argument('new_version', type=str) + parser.add_argument("new_version", type=str) args = parser.parse_args() version = args.new_version diff --git a/script/bump-version.py b/script/bump-version.py index 56062ac5c..54e8c9575 100755 --- a/script/bump-version.py +++ b/script/bump-version.py @@ -16,30 +16,27 @@ class Version: dev: bool = False def __str__(self): - return f'{self.major}.{self.minor}.{self.full_patch}' + return f"{self.major}.{self.minor}.{self.full_patch}" @property def full_patch(self): - res = f'{self.patch}' + res = f"{self.patch}" if self.beta > 0: - res += f'b{self.beta}' + res += f"b{self.beta}" if self.dev: - res += '-dev' + res += "-dev" return res @classmethod def parse(cls, value): - match = re.match(r'(\d+).(\d+).(\d+)(b\d+)?(-dev)?', value) + match = re.match(r"(\d+).(\d+).(\d+)(b\d+)?(-dev)?", value) assert match is not None major = int(match[1]) minor = int(match[2]) patch = int(match[3]) beta = int(match[4][1:]) if match[4] else 0 dev = bool(match[5]) - return Version( - major=major, minor=minor, patch=patch, - beta=beta, dev=dev - ) + return Version(major=major, minor=minor, patch=patch, beta=beta, dev=dev) def sub(path, pattern, repl, expected_count=1): @@ -54,25 +51,21 @@ def sub(path, pattern, repl, expected_count=1): def write_version(version: Version): sub( - 'esphome/const.py', - r"^MAJOR_VERSION = \d+$", - f"MAJOR_VERSION = {version.major}" + "esphome/const.py", r"^MAJOR_VERSION = \d+$", f"MAJOR_VERSION = {version.major}" ) sub( - 'esphome/const.py', - r"^MINOR_VERSION = \d+$", - f"MINOR_VERSION = {version.minor}" + "esphome/const.py", r"^MINOR_VERSION = \d+$", f"MINOR_VERSION = {version.minor}" ) sub( - 'esphome/const.py', + "esphome/const.py", r"^PATCH_VERSION = .*$", - f"PATCH_VERSION = '{version.full_patch}'" + f"PATCH_VERSION = '{version.full_patch}'", ) def main(): parser = argparse.ArgumentParser() - parser.add_argument('new_version', type=str) + parser.add_argument("new_version", type=str) args = parser.parse_args() version = Version.parse(args.new_version) diff --git a/script/ci-custom.py b/script/ci-custom.py index ab2beadf8..8ebf6eb24 100755 --- a/script/ci-custom.py +++ b/script/ci-custom.py @@ -14,6 +14,7 @@ import argparse sys.path.append(os.path.dirname(__file__)) from helpers import git_ls_files, filter_changed + def find_all(a_str, sub): if not a_str.find(sub): # Optimization: If str is not in whole text, then do not try @@ -30,18 +31,21 @@ def find_all(a_str, sub): parser = argparse.ArgumentParser() -parser.add_argument('files', nargs='*', default=[], - help='files to be processed (regex on path)') -parser.add_argument('-c', '--changed', action='store_true', - help='Only run on changed files') -parser.add_argument('--print-slowest', action='store_true', - help='Print the slowest checks') +parser.add_argument( + "files", nargs="*", default=[], help="files to be processed (regex on path)" +) +parser.add_argument( + "-c", "--changed", action="store_true", help="Only run on changed files" +) +parser.add_argument( + "--print-slowest", action="store_true", help="Print the slowest checks" +) args = parser.parse_args() EXECUTABLE_BIT = git_ls_files() files = list(EXECUTABLE_BIT.keys()) # Match against re -file_name_re = re.compile('|'.join(args.files)) +file_name_re = re.compile("|".join(args.files)) files = [p for p in files if file_name_re.search(p)] if args.changed: @@ -49,11 +53,32 @@ if args.changed: files.sort() -file_types = ('.h', '.c', '.cpp', '.tcc', '.yaml', '.yml', '.ini', '.txt', '.ico', '.svg', - '.py', '.html', '.js', '.md', '.sh', '.css', '.proto', '.conf', '.cfg', - '.woff', '.woff2', '') -cpp_include = ('*.h', '*.c', '*.cpp', '*.tcc') -ignore_types = ('.ico', '.woff', '.woff2', '') +file_types = ( + ".h", + ".c", + ".cpp", + ".tcc", + ".yaml", + ".yml", + ".ini", + ".txt", + ".ico", + ".svg", + ".py", + ".html", + ".js", + ".md", + ".sh", + ".css", + ".proto", + ".conf", + ".cfg", + ".woff", + ".woff2", + "", +) +cpp_include = ("*.h", "*.c", "*.cpp", "*.tcc") +ignore_types = (".ico", ".woff", ".woff2", "") LINT_FILE_CHECKS = [] LINT_CONTENT_CHECKS = [] @@ -61,9 +86,9 @@ LINT_POST_CHECKS = [] def run_check(lint_obj, fname, *args): - include = lint_obj['include'] - exclude = lint_obj['exclude'] - func = lint_obj['func'] + include = lint_obj["include"] + exclude = lint_obj["exclude"] + func = lint_obj["func"] if include is not None: for incl in include: if fnmatch.fnmatch(fname, incl): @@ -85,21 +110,24 @@ def run_checks(lints, fname, *args): print(f"Check {lint['func'].__name__} on file {fname} failed:") raise duration = time.process_time() - start - lint.setdefault('durations', []).append(duration) + lint.setdefault("durations", []).append(duration) def _add_check(checks, func, include=None, exclude=None): - checks.append({ - 'include': include, - 'exclude': exclude or [], - 'func': func, - }) + checks.append( + { + "include": include, + "exclude": exclude or [], + "func": func, + } + ) def lint_file_check(**kwargs): def decorator(func): _add_check(LINT_FILE_CHECKS, func, **kwargs) return func + return decorator @@ -107,6 +135,7 @@ def lint_content_check(**kwargs): def decorator(func): _add_check(LINT_CONTENT_CHECKS, func, **kwargs) return func + return decorator @@ -116,7 +145,7 @@ def lint_post_check(func): def lint_re_check(regex, **kwargs): - flags = kwargs.pop('flags', re.MULTILINE) + flags = kwargs.pop("flags", re.MULTILINE) prog = re.compile(regex, flags) decor = lint_content_check(**kwargs) @@ -125,18 +154,19 @@ def lint_re_check(regex, **kwargs): def new_func(fname, content): errors = [] for match in prog.finditer(content): - if 'NOLINT' in match.group(0): + if "NOLINT" in match.group(0): continue lineno = content.count("\n", 0, match.start()) + 1 - substr = content[:match.start()] - col = len(substr) - substr.rfind('\n') + substr = content[: match.start()] + col = len(substr) - substr.rfind("\n") err = func(fname, match) if err is None: continue - errors.append((lineno, col+1, err)) + errors.append((lineno, col + 1, err)) return errors return decor(new_func) + return decorator @@ -152,73 +182,99 @@ def lint_content_find_check(find, **kwargs): errors = [] for line, col in find_all(content, find_): err = func(fname) - errors.append((line+1, col+1, err)) + errors.append((line + 1, col + 1, err)) return errors + return decor(new_func) + return decorator -@lint_file_check(include=['*.ino']) +@lint_file_check(include=["*.ino"]) def lint_ino(fname): return "This file extension (.ino) is not allowed. Please use either .cpp or .h" -@lint_file_check(exclude=[f'*{f}' for f in file_types] + [ - '.clang-*', '.dockerignore', '.editorconfig', '*.gitignore', 'LICENSE', 'pylintrc', - 'MANIFEST.in', 'docker/Dockerfile*', 'docker/rootfs/*', 'script/*', -]) +@lint_file_check( + exclude=[f"*{f}" for f in file_types] + + [ + ".clang-*", + ".dockerignore", + ".editorconfig", + "*.gitignore", + "LICENSE", + "pylintrc", + "MANIFEST.in", + "docker/Dockerfile*", + "docker/rootfs/*", + "script/*", + ] +) def lint_ext_check(fname): - return "This file extension is not a registered file type. If this is an error, please " \ - "update the script/ci-custom.py script." + return ( + "This file extension is not a registered file type. If this is an error, please " + "update the script/ci-custom.py script." + ) -@lint_file_check(exclude=[ - 'docker/rootfs/*', 'script/*', 'setup.py' -]) +@lint_file_check(exclude=["docker/rootfs/*", "script/*", "setup.py"]) def lint_executable_bit(fname): ex = EXECUTABLE_BIT[fname] if ex != 100644: - return 'File has invalid executable bit {}. If running from a windows machine please ' \ - 'see disabling executable bit in git.'.format(ex) + return ( + "File has invalid executable bit {}. If running from a windows machine please " + "see disabling executable bit in git.".format(ex) + ) return None -@lint_content_find_check('\t', exclude=[ - 'esphome/dashboard/static/ace.js', 'esphome/dashboard/static/ext-searchbox.js', -]) +@lint_content_find_check( + "\t", + exclude=[ + "esphome/dashboard/static/ace.js", + "esphome/dashboard/static/ext-searchbox.js", + ], +) def lint_tabs(fname): return "File contains tab character. Please convert tabs to spaces." -@lint_content_find_check('\r') +@lint_content_find_check("\r") def lint_newline(fname): return "File contains windows newline. Please set your editor to unix newline mode." -@lint_content_check(exclude=['*.svg']) +@lint_content_check(exclude=["*.svg"]) def lint_end_newline(fname, content): - if content and not content.endswith('\n'): + if content and not content.endswith("\n"): return "File does not end with a newline, please add an empty line at the end of the file." return None -CPP_RE_EOL = r'\s*?(?://.*?)?$' +CPP_RE_EOL = r"\s*?(?://.*?)?$" def highlight(s): - return f'\033[36m{s}\033[0m' + return f"\033[36m{s}\033[0m" -@lint_re_check(r'^#define\s+([a-zA-Z0-9_]+)\s+([0-9bx]+)' + CPP_RE_EOL, - include=cpp_include, exclude=['esphome/core/log.h']) +@lint_re_check( + r"^#define\s+([a-zA-Z0-9_]+)\s+([0-9bx]+)" + CPP_RE_EOL, + include=cpp_include, + exclude=["esphome/core/log.h"], +) def lint_no_defines(fname, match): - s = highlight('static const uint8_t {} = {};'.format(match.group(1), match.group(2))) - return ("#define macros for integer constants are not allowed, please use " - "{} style instead (replace uint8_t with the appropriate " - "datatype). See also Google style guide.".format(s)) + s = highlight( + "static const uint8_t {} = {};".format(match.group(1), match.group(2)) + ) + return ( + "#define macros for integer constants are not allowed, please use " + "{} style instead (replace uint8_t with the appropriate " + "datatype). See also Google style guide.".format(s) + ) -@lint_re_check(r'^\s*delay\((\d+)\);' + CPP_RE_EOL, include=cpp_include) +@lint_re_check(r"^\s*delay\((\d+)\);" + CPP_RE_EOL, include=cpp_include) def lint_no_long_delays(fname, match): duration_ms = int(match.group(1)) if duration_ms < 50: @@ -232,7 +288,7 @@ def lint_no_long_delays(fname, match): ) -@lint_content_check(include=['esphome/const.py']) +@lint_content_check(include=["esphome/const.py"]) def lint_const_ordered(fname, content): """Lint that value in const.py are ordered. @@ -240,54 +296,67 @@ def lint_const_ordered(fname, content): """ lines = content.splitlines() errors = [] - for start in ['CONF_', 'ICON_', 'UNIT_']: - matching = [(i+1, line) for i, line in enumerate(lines) if line.startswith(start)] - ordered = list(sorted(matching, key=lambda x: x[1].replace('_', ' '))) + for start in ["CONF_", "ICON_", "UNIT_"]: + matching = [ + (i + 1, line) for i, line in enumerate(lines) if line.startswith(start) + ] + ordered = list(sorted(matching, key=lambda x: x[1].replace("_", " "))) ordered = [(mi, ol) for (mi, _), (_, ol) in zip(matching, ordered)] for (mi, ml), (oi, ol) in zip(matching, ordered): if ml == ol: continue target = next(i for i, l in ordered if l == ml) target_text = next(l for i, l in matching if target == i) - errors.append((mi, 1, - f"Constant {highlight(ml)} is not ordered, please make sure all " - f"constants are ordered. See line {mi} (should go to line {target}, " - f"{target_text})")) + errors.append( + ( + mi, + 1, + f"Constant {highlight(ml)} is not ordered, please make sure all " + f"constants are ordered. See line {mi} (should go to line {target}, " + f"{target_text})", + ) + ) return errors -@lint_re_check(r'^\s*CONF_([A-Z_0-9a-z]+)\s+=\s+[\'"](.*?)[\'"]\s*?$', include=['*.py']) +@lint_re_check(r'^\s*CONF_([A-Z_0-9a-z]+)\s+=\s+[\'"](.*?)[\'"]\s*?$', include=["*.py"]) def lint_conf_matches(fname, match): const = match.group(1) value = match.group(2) const_norm = const.lower() - value_norm = value.replace('.', '_') + value_norm = value.replace(".", "_") if const_norm == value_norm: return None - return ("Constant {} does not match value {}! Please make sure the constant's name matches its " - "value!" - "".format(highlight('CONF_' + const), highlight(value))) + return ( + "Constant {} does not match value {}! Please make sure the constant's name matches its " + "value!" + "".format(highlight("CONF_" + const), highlight(value)) + ) CONF_RE = r'^(CONF_[a-zA-Z0-9_]+)\s*=\s*[\'"].*?[\'"]\s*?$' -with codecs.open('esphome/const.py', 'r', encoding='utf-8') as f_handle: +with codecs.open("esphome/const.py", "r", encoding="utf-8") as f_handle: constants_content = f_handle.read() CONSTANTS = [m.group(1) for m in re.finditer(CONF_RE, constants_content, re.MULTILINE)] CONSTANTS_USES = collections.defaultdict(list) -@lint_re_check(CONF_RE, include=['*.py'], exclude=['esphome/const.py']) +@lint_re_check(CONF_RE, include=["*.py"], exclude=["esphome/const.py"]) def lint_conf_from_const_py(fname, match): name = match.group(1) if name not in CONSTANTS: CONSTANTS_USES[name].append(fname) return None - return ("Constant {} has already been defined in const.py - please import the constant from " - "const.py directly.".format(highlight(name))) + return ( + "Constant {} has already been defined in const.py - please import the constant from " + "const.py directly.".format(highlight(name)) + ) -RAW_PIN_ACCESS_RE = r'^\s(pinMode|digitalWrite|digitalRead)\((.*)->get_pin\(\),\s*([^)]+).*\)' +RAW_PIN_ACCESS_RE = ( + r"^\s(pinMode|digitalWrite|digitalRead)\((.*)->get_pin\(\),\s*([^)]+).*\)" +) @lint_re_check(RAW_PIN_ACCESS_RE, include=cpp_include) @@ -296,33 +365,49 @@ def lint_no_raw_pin_access(fname, match): pin = match.group(2) mode = match.group(3) new_func = { - 'pinMode': 'pin_mode', - 'digitalWrite': 'digital_write', - 'digitalRead': 'digital_read', + "pinMode": "pin_mode", + "digitalWrite": "digital_write", + "digitalRead": "digital_read", }[func] - new_code = highlight(f'{pin}->{new_func}({mode})') - return (f"Don't use raw {func} calls. Instead, use the `->{new_func}` function: {new_code}") + new_code = highlight(f"{pin}->{new_func}({mode})") + return f"Don't use raw {func} calls. Instead, use the `->{new_func}` function: {new_code}" # Functions from Arduino framework that are forbidden to use directly ARDUINO_FORBIDDEN = [ - 'digitalWrite', 'digitalRead', 'pinMode', - 'shiftOut', 'shiftIn', - 'radians', 'degrees', - 'interrupts', 'noInterrupts', - 'lowByte', 'highByte', - 'bitRead', 'bitSet', 'bitClear', 'bitWrite', - 'bit', 'analogRead', 'analogWrite', - 'pulseIn', 'pulseInLong', - 'tone', + "digitalWrite", + "digitalRead", + "pinMode", + "shiftOut", + "shiftIn", + "radians", + "degrees", + "interrupts", + "noInterrupts", + "lowByte", + "highByte", + "bitRead", + "bitSet", + "bitClear", + "bitWrite", + "bit", + "analogRead", + "analogWrite", + "pulseIn", + "pulseInLong", + "tone", ] -ARDUINO_FORBIDDEN_RE = r'[^\w\d](' + r'|'.join(ARDUINO_FORBIDDEN) + r')\(.*' +ARDUINO_FORBIDDEN_RE = r"[^\w\d](" + r"|".join(ARDUINO_FORBIDDEN) + r")\(.*" -@lint_re_check(ARDUINO_FORBIDDEN_RE, include=cpp_include, exclude=[ - 'esphome/components/mqtt/custom_mqtt_device.h', - 'esphome/core/esphal.*', -]) +@lint_re_check( + ARDUINO_FORBIDDEN_RE, + include=cpp_include, + exclude=[ + "esphome/components/mqtt/custom_mqtt_device.h", + "esphome/core/esphal.*", + ], +) def lint_no_arduino_framework_functions(fname, match): nolint = highlight("// NOLINT") return ( @@ -334,9 +419,13 @@ def lint_no_arduino_framework_functions(fname, match): ) -@lint_re_check(r'[^\w\d]byte\s+[\w\d]+\s*=', include=cpp_include, exclude={ - 'esphome/components/tuya/tuya.h', -}) +@lint_re_check( + r"[^\w\d]byte\s+[\w\d]+\s*=", + include=cpp_include, + exclude={ + "esphome/components/tuya/tuya.h", + }, +) def lint_no_byte_datatype(fname, match): return ( f"The datatype {highlight('byte')} is not allowed to be used in ESPHome. " @@ -350,112 +439,143 @@ def lint_constants_usage(): for constant, uses in CONSTANTS_USES.items(): if len(uses) < 4: continue - errors.append("Constant {} is defined in {} files. Please move all definitions of the " - "constant to const.py (Uses: {})" - "".format(highlight(constant), len(uses), ', '.join(uses))) + errors.append( + "Constant {} is defined in {} files. Please move all definitions of the " + "constant to const.py (Uses: {})" + "".format(highlight(constant), len(uses), ", ".join(uses)) + ) return errors def relative_cpp_search_text(fname, content): - parts = fname.split('/') + parts = fname.split("/") integration = parts[2] return f'#include "esphome/components/{integration}' -@lint_content_find_check(relative_cpp_search_text, include=['esphome/components/*.cpp']) +@lint_content_find_check(relative_cpp_search_text, include=["esphome/components/*.cpp"]) def lint_relative_cpp_import(fname): - return ("Component contains absolute import - Components must always use " - "relative imports.\n" - "Change:\n" - ' #include "esphome/components/abc/abc.h"\n' - 'to:\n' - ' #include "abc.h"\n\n') + return ( + "Component contains absolute import - Components must always use " + "relative imports.\n" + "Change:\n" + ' #include "esphome/components/abc/abc.h"\n' + "to:\n" + ' #include "abc.h"\n\n' + ) def relative_py_search_text(fname, content): - parts = fname.split('/') + parts = fname.split("/") integration = parts[2] - return f'esphome.components.{integration}' + return f"esphome.components.{integration}" -@lint_content_find_check(relative_py_search_text, include=['esphome/components/*.py'], - exclude=['esphome/components/web_server/__init__.py']) +@lint_content_find_check( + relative_py_search_text, + include=["esphome/components/*.py"], + exclude=["esphome/components/web_server/__init__.py"], +) def lint_relative_py_import(fname): - return ("Component contains absolute import - Components must always use " - "relative imports within the integration.\n" - "Change:\n" - ' from esphome.components.abc import abc_ns"\n' - 'to:\n' - ' from . import abc_ns\n\n') + return ( + "Component contains absolute import - Components must always use " + "relative imports within the integration.\n" + "Change:\n" + ' from esphome.components.abc import abc_ns"\n' + "to:\n" + " from . import abc_ns\n\n" + ) -@lint_content_check(include=['esphome/components/*.h', 'esphome/components/*.cpp', - 'esphome/components/*.tcc']) +@lint_content_check( + include=[ + "esphome/components/*.h", + "esphome/components/*.cpp", + "esphome/components/*.tcc", + ] +) def lint_namespace(fname, content): - expected_name = re.match(r'^esphome/components/([^/]+)/.*', - fname.replace(os.path.sep, '/')).group(1) - search = f'namespace {expected_name}' + expected_name = re.match( + r"^esphome/components/([^/]+)/.*", fname.replace(os.path.sep, "/") + ).group(1) + search = f"namespace {expected_name}" if search in content: return None - return 'Invalid namespace found in C++ file. All integration C++ files should put all ' \ - 'functions in a separate namespace that matches the integration\'s name. ' \ - 'Please make sure the file contains {}'.format(highlight(search)) + return ( + "Invalid namespace found in C++ file. All integration C++ files should put all " + "functions in a separate namespace that matches the integration's name. " + "Please make sure the file contains {}".format(highlight(search)) + ) -@lint_content_find_check('"esphome.h"', include=cpp_include, exclude=['tests/custom.h']) +@lint_content_find_check('"esphome.h"', include=cpp_include, exclude=["tests/custom.h"]) def lint_esphome_h(fname): - return ("File contains reference to 'esphome.h' - This file is " - "auto-generated and should only be used for *custom* " - "components. Please replace with references to the direct files.") + return ( + "File contains reference to 'esphome.h' - This file is " + "auto-generated and should only be used for *custom* " + "components. Please replace with references to the direct files." + ) -@lint_content_check(include=['*.h']) +@lint_content_check(include=["*.h"]) def lint_pragma_once(fname, content): - if '#pragma once' not in content: - return ("Header file contains no 'pragma once' header guard. Please add a " - "'#pragma once' line at the top of the file.") + if "#pragma once" not in content: + return ( + "Header file contains no 'pragma once' header guard. Please add a " + "'#pragma once' line at the top of the file." + ) return None -@lint_re_check(r'(whitelist|blacklist|slave)', - exclude=['script/ci-custom.py'], flags=re.IGNORECASE | re.MULTILINE) +@lint_re_check( + r"(whitelist|blacklist|slave)", + exclude=["script/ci-custom.py"], + flags=re.IGNORECASE | re.MULTILINE, +) def lint_inclusive_language(fname, match): # From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=49decddd39e5f6132ccd7d9fdc3d7c470b0061bb - return ("Avoid the use of whitelist/blacklist/slave.\n" - "Recommended replacements for 'master / slave' are:\n" - " '{primary,main} / {secondary,replica,subordinate}\n" - " '{initiator,requester} / {target,responder}'\n" - " '{controller,host} / {device,worker,proxy}'\n" - " 'leader / follower'\n" - " 'director / performer'\n" - "\n" - "Recommended replacements for 'blacklist/whitelist' are:\n" - " 'denylist / allowlist'\n" - " 'blocklist / passlist'") + return ( + "Avoid the use of whitelist/blacklist/slave.\n" + "Recommended replacements for 'master / slave' are:\n" + " '{primary,main} / {secondary,replica,subordinate}\n" + " '{initiator,requester} / {target,responder}'\n" + " '{controller,host} / {device,worker,proxy}'\n" + " 'leader / follower'\n" + " 'director / performer'\n" + "\n" + "Recommended replacements for 'blacklist/whitelist' are:\n" + " 'denylist / allowlist'\n" + " 'blocklist / passlist'" + ) - -@lint_content_find_check('ESP_LOG', include=['*.h', '*.tcc'], exclude=[ - 'esphome/components/binary_sensor/binary_sensor.h', - 'esphome/components/cover/cover.h', - 'esphome/components/display/display_buffer.h', - 'esphome/components/i2c/i2c.h', - 'esphome/components/mqtt/mqtt_component.h', - 'esphome/components/output/binary_output.h', - 'esphome/components/output/float_output.h', - 'esphome/components/sensor/sensor.h', - 'esphome/components/stepper/stepper.h', - 'esphome/components/switch/switch.h', - 'esphome/components/text_sensor/text_sensor.h', - 'esphome/components/climate/climate.h', - 'esphome/core/component.h', - 'esphome/core/esphal.h', - 'esphome/core/log.h', - 'tests/custom.h', -]) +@lint_content_find_check( + "ESP_LOG", + include=["*.h", "*.tcc"], + exclude=[ + "esphome/components/binary_sensor/binary_sensor.h", + "esphome/components/cover/cover.h", + "esphome/components/display/display_buffer.h", + "esphome/components/i2c/i2c.h", + "esphome/components/mqtt/mqtt_component.h", + "esphome/components/output/binary_output.h", + "esphome/components/output/float_output.h", + "esphome/components/sensor/sensor.h", + "esphome/components/stepper/stepper.h", + "esphome/components/switch/switch.h", + "esphome/components/text_sensor/text_sensor.h", + "esphome/components/climate/climate.h", + "esphome/core/component.h", + "esphome/core/esphal.h", + "esphome/core/log.h", + "tests/custom.h", + ], +) def lint_log_in_header(fname): - return ('Found reference to ESP_LOG in header file. Using ESP_LOG* in header files ' - 'is currently not possible - please move the definition to a source file (.cpp)') + return ( + "Found reference to ESP_LOG in header file. Using ESP_LOG* in header files " + "is currently not possible - please move the definition to a source file (.cpp)" + ) errors = collections.defaultdict(list) @@ -488,14 +608,17 @@ for fname in files: if ext in ignore_types: continue try: - with codecs.open(fname, 'r', encoding='utf-8') as f_handle: + with codecs.open(fname, "r", encoding="utf-8") as f_handle: content = f_handle.read() except UnicodeDecodeError: - add_errors(fname, "File is not readable as UTF-8. Please set your editor to UTF-8 mode.") + add_errors( + fname, + "File is not readable as UTF-8. Please set your editor to UTF-8 mode.", + ) continue run_checks(LINT_CONTENT_CHECKS, fname, fname, content) -run_checks(LINT_POST_CHECKS, 'POST') +run_checks(LINT_POST_CHECKS, "POST") for f, errs in sorted(errors.items()): print(f"\033[0;32m************* File \033[1;32m{f}\033[0m") @@ -506,8 +629,8 @@ for f, errs in sorted(errors.items()): if args.print_slowest: lint_times = [] for lint in LINT_FILE_CHECKS + LINT_CONTENT_CHECKS + LINT_POST_CHECKS: - durations = lint.get('durations', []) - lint_times.append((sum(durations), len(durations), lint['func'].__name__)) + durations = lint.get("durations", []) + lint_times.append((sum(durations), len(durations), lint["func"].__name__)) lint_times.sort(key=lambda x: -x[0]) for i in range(min(len(lint_times), 10)): dur, invocations, name = lint_times[i] diff --git a/script/helpers.py b/script/helpers.py index e0aaee871..5b1b7ba91 100644 --- a/script/helpers.py +++ b/script/helpers.py @@ -5,15 +5,15 @@ import re import subprocess import sys -root_path = os.path.abspath(os.path.normpath(os.path.join(__file__, '..', '..'))) -basepath = os.path.join(root_path, 'esphome') -temp_header_file = os.path.join(root_path, '.temp-clang-tidy.cpp') +root_path = os.path.abspath(os.path.normpath(os.path.join(__file__, "..", ".."))) +basepath = os.path.join(root_path, "esphome") +temp_header_file = os.path.join(root_path, ".temp-clang-tidy.cpp") def shlex_quote(s): if not s: return "''" - if re.search(r'[^\w@%+=:,./-]', s) is None: + if re.search(r"[^\w@%+=:,./-]", s) is None: return s return "'" + s.replace("'", "'\"'\"'") + "'" @@ -24,63 +24,71 @@ def build_all_include(): # Otherwise header-only integrations would not be tested by clang-tidy headers = [] for path in walk_files(basepath): - filetypes = ('.h',) + filetypes = (".h",) ext = os.path.splitext(path)[1] if ext in filetypes: path = os.path.relpath(path, root_path) - include_p = path.replace(os.path.sep, '/') + include_p = path.replace(os.path.sep, "/") headers.append(f'#include "{include_p}"') headers.sort() - headers.append('') - content = '\n'.join(headers) - with codecs.open(temp_header_file, 'w', encoding='utf-8') as f: + headers.append("") + content = "\n".join(headers) + with codecs.open(temp_header_file, "w", encoding="utf-8") as f: f.write(content) def build_compile_commands(): - gcc_flags_json = os.path.join(root_path, '.gcc-flags.json') + gcc_flags_json = os.path.join(root_path, ".gcc-flags.json") if not os.path.isfile(gcc_flags_json): print("Could not find {} file which is required for clang-tidy.") - print('Please run "pio init --ide atom" in the root esphome folder to generate that file.') + print( + 'Please run "pio init --ide atom" in the root esphome folder to generate that file.' + ) sys.exit(1) - with codecs.open(gcc_flags_json, 'r', encoding='utf-8') as f: + with codecs.open(gcc_flags_json, "r", encoding="utf-8") as f: gcc_flags = json.load(f) - exec_path = gcc_flags['execPath'] - include_paths = gcc_flags['gccIncludePaths'].split(',') - includes = [f'-I{p}' for p in include_paths] - cpp_flags = gcc_flags['gccDefaultCppFlags'].split(' ') - defines = [flag for flag in cpp_flags if flag.startswith('-D')] + exec_path = gcc_flags["execPath"] + include_paths = gcc_flags["gccIncludePaths"].split(",") + includes = [f"-I{p}" for p in include_paths] + cpp_flags = gcc_flags["gccDefaultCppFlags"].split(" ") + defines = [flag for flag in cpp_flags if flag.startswith("-D")] command = [exec_path] command.extend(includes) command.extend(defines) - command.append('-std=gnu++11') - command.append('-Wall') - command.append('-Wno-delete-non-virtual-dtor') - command.append('-Wno-unused-variable') - command.append('-Wunreachable-code') + command.append("-std=gnu++11") + command.append("-Wall") + command.append("-Wno-delete-non-virtual-dtor") + command.append("-Wno-unused-variable") + command.append("-Wunreachable-code") source_files = [] for path in walk_files(basepath): - filetypes = ('.cpp',) + filetypes = (".cpp",) ext = os.path.splitext(path)[1] if ext in filetypes: source_files.append(os.path.abspath(path)) source_files.append(temp_header_file) source_files.sort() - compile_commands = [{ - 'directory': root_path, - 'command': ' '.join(shlex_quote(x) for x in (command + ['-o', p + '.o', '-c', p])), - 'file': p - } for p in source_files] - compile_commands_json = os.path.join(root_path, 'compile_commands.json') + compile_commands = [ + { + "directory": root_path, + "command": " ".join( + shlex_quote(x) for x in (command + ["-o", p + ".o", "-c", p]) + ), + "file": p, + } + for p in source_files + ] + compile_commands_json = os.path.join(root_path, "compile_commands.json") if os.path.isfile(compile_commands_json): - with codecs.open(compile_commands_json, 'r', encoding='utf-8') as f: + with codecs.open(compile_commands_json, "r", encoding="utf-8") as f: try: if json.load(f) == compile_commands: return + # pylint: disable=bare-except except: pass - with codecs.open(compile_commands_json, 'w', encoding='utf-8') as f: + with codecs.open(compile_commands_json, "w", encoding="utf-8") as f: json.dump(compile_commands, f, indent=2) @@ -93,7 +101,13 @@ def walk_files(path): def get_output(*args): proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, err = proc.communicate() - return output.decode('utf-8') + return output.decode("utf-8") + + +def get_err(*args): + proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + output, err = proc.communicate() + return err.decode("utf-8") def splitlines_no_ends(string): @@ -101,18 +115,19 @@ def splitlines_no_ends(string): def changed_files(): - check_remotes = ['upstream', 'origin'] - check_remotes.extend(splitlines_no_ends(get_output('git', 'remote'))) + check_remotes = ["upstream", "origin"] + check_remotes.extend(splitlines_no_ends(get_output("git", "remote"))) for remote in check_remotes: - command = ['git', 'merge-base', f'refs/remotes/{remote}/dev', 'HEAD'] + command = ["git", "merge-base", f"refs/remotes/{remote}/dev", "HEAD"] try: merge_base = splitlines_no_ends(get_output(*command))[0] break + # pylint: disable=bare-except except: pass else: raise ValueError("Git not configured") - command = ['git', 'diff', merge_base, '--name-only'] + command = ["git", "diff", merge_base, "--name-only"] changed = splitlines_no_ends(get_output(*command)) changed = [os.path.relpath(f, os.getcwd()) for f in changed] changed.sort() @@ -131,10 +146,8 @@ def filter_changed(files): def git_ls_files(): - command = ['git', 'ls-files', '-s'] + command = ["git", "ls-files", "-s"] proc = subprocess.Popen(command, stdout=subprocess.PIPE) output, err = proc.communicate() - lines = [x.split() for x in output.decode('utf-8').splitlines()] - return { - s[3].strip(): int(s[0]) for s in lines - } + lines = [x.split() for x in output.decode("utf-8").splitlines()] + return {s[3].strip(): int(s[0]) for s in lines} diff --git a/script/lint-python b/script/lint-python index 491511526..41885b967 100755 --- a/script/lint-python +++ b/script/lint-python @@ -1,15 +1,14 @@ #!/usr/bin/env python3 from __future__ import print_function +from helpers import get_output, get_err, git_ls_files, filter_changed import argparse -import collections import os import re import sys sys.path.append(os.path.dirname(__file__)) -from helpers import get_output, git_ls_files, filter_changed curfile = None @@ -22,26 +21,28 @@ def print_error(file, lineno, msg): print("\033[0;32m************* File \033[1;32m{}\033[0m".format(file)) curfile = file - print(u'{}:{} - {}'.format(file, lineno, msg)) + print("{}:{} - {}".format(file, lineno, msg)) def main(): parser = argparse.ArgumentParser() - parser.add_argument('files', nargs='*', default=[], - help='files to be processed (regex on path)') - parser.add_argument('-c', '--changed', action='store_true', - help='Only run on changed files') + parser.add_argument( + "files", nargs="*", default=[], help="files to be processed (regex on path)" + ) + parser.add_argument( + "-c", "--changed", action="store_true", help="Only run on changed files" + ) args = parser.parse_args() files = [] for path in git_ls_files(): - filetypes = ('.py',) + filetypes = (".py",) ext = os.path.splitext(path)[1] - if ext in filetypes and path.startswith('esphome'): + if ext in filetypes and path.startswith("esphome"): path = os.path.relpath(path, os.getcwd()) files.append(path) # Match against re - file_name_re = re.compile('|'.join(args.files)) + file_name_re = re.compile("|".join(args.files)) files = [p for p in files if file_name_re.search(p)] if args.changed: @@ -52,34 +53,45 @@ def main(): sys.exit(0) errors = 0 - cmd = ['flake8'] + files + + cmd = ["black", "--verbose", "--check"] + files + print("Running black...") + log = get_err(*cmd) + for line in log.splitlines(): + WOULD_REFORMAT = "would reformat" + if line.startswith(WOULD_REFORMAT): + file_ = line[len(WOULD_REFORMAT) + 1 :] + print_error(file_, None, "Please format this file with the black formatter") + errors += 1 + + cmd = ["flake8"] + files print("Running flake8...") log = get_output(*cmd) for line in log.splitlines(): - line = line.split(':', 4) + line = line.split(":", 4) if len(line) < 4: continue file_ = line[0] linno = line[1] - msg = (':'.join(line[3:])).strip() + msg = (":".join(line[3:])).strip() print_error(file_, linno, msg) errors += 1 - cmd = ['pylint', '-f', 'parseable', '--persistent=n'] + files + cmd = ["pylint", "-f", "parseable", "--persistent=n"] + files print("Running pylint...") log = get_output(*cmd) for line in log.splitlines(): - line = line.split(':', 3) + line = line.split(":", 3) if len(line) < 3: continue file_ = line[0] linno = line[1] - msg = (':'.join(line[2:])).strip() + msg = (":".join(line[2:])).strip() print_error(file_, linno, msg) errors += 1 sys.exit(errors) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/script/setup b/script/setup index d70a44ee4..199b46891 100755 --- a/script/setup +++ b/script/setup @@ -6,3 +6,5 @@ set -e cd "$(dirname "$0")/.." pip3 install -r requirements.txt -r requirements_test.txt pip3 install -e . + +pre-commit install diff --git a/setup.cfg b/setup.cfg index 32a60839a..755cef47c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -17,6 +17,45 @@ Topic :: Home Automation [flake8] max-line-length = 120 +# Following 4 for black compatibility +# E501: line too long +# W503: Line break occurred before a binary operator +# E203: Whitespace before ':' +# D202 No blank lines allowed after function docstring + +# TODO fix flake8 +# D100 Missing docstring in public module +# D101 Missing docstring in public class +# D102 Missing docstring in public method +# D103 Missing docstring in public function +# D104 Missing docstring in public package +# D105 Missing docstring in magic method +# D107 Missing docstring in __init__ +# D200 One-line docstring should fit on one line with quotes +# D205 1 blank line required between summary line and description +# D209 Multi-line docstring closing quotes should be on a separate line +# D400 First line should end with a period +# D401 First line should be in imperative mood + +ignore = + E501, + W503, + E203, + D202, + + D100, + D101, + D102, + D103, + D104, + D105, + D107, + D200, + D205, + D209, + D400, + D401, + exclude = api_pb2.py [bdist_wheel] diff --git a/tests/component_tests/binary_sensor/test_binary_sensor.py b/tests/component_tests/binary_sensor/test_binary_sensor.py index 72c0dc1cd..8da93a476 100644 --- a/tests/component_tests/binary_sensor/test_binary_sensor.py +++ b/tests/component_tests/binary_sensor/test_binary_sensor.py @@ -1,4 +1,4 @@ -""" Tests for the binary sensor component """ +"""Tests for the binary sensor component.""" def test_binary_sensor_is_setup(generate_main): @@ -8,7 +8,9 @@ def test_binary_sensor_is_setup(generate_main): # Given # When - main_cpp = generate_main("tests/component_tests/binary_sensor/test_binary_sensor.yaml") + main_cpp = generate_main( + "tests/component_tests/binary_sensor/test_binary_sensor.yaml" + ) # Then assert "new gpio::GPIOBinarySensor();" in main_cpp @@ -22,10 +24,12 @@ def test_binary_sensor_sets_mandatory_fields(generate_main): # Given # When - main_cpp = generate_main("tests/component_tests/binary_sensor/test_binary_sensor.yaml") + main_cpp = generate_main( + "tests/component_tests/binary_sensor/test_binary_sensor.yaml" + ) # Then - assert "bs_1->set_name(\"test bs1\");" in main_cpp + assert 'bs_1->set_name("test bs1");' in main_cpp assert "bs_1->set_pin(new GPIOPin" in main_cpp @@ -36,7 +40,9 @@ def test_binary_sensor_config_value_internal_set(generate_main): # Given # When - main_cpp = generate_main("tests/component_tests/binary_sensor/test_binary_sensor.yaml") + main_cpp = generate_main( + "tests/component_tests/binary_sensor/test_binary_sensor.yaml" + ) # Then assert "bs_1->set_internal(true);" in main_cpp diff --git a/tests/component_tests/sensor/test_sensor.py b/tests/component_tests/sensor/test_sensor.py index e82a02400..35ce1f4e1 100644 --- a/tests/component_tests/sensor/test_sensor.py +++ b/tests/component_tests/sensor/test_sensor.py @@ -1,4 +1,4 @@ -""" Tests for the sensor component """ +"""Tests for the sensor component.""" def test_sensor_device_class_set(generate_main): @@ -11,4 +11,4 @@ def test_sensor_device_class_set(generate_main): main_cpp = generate_main("tests/component_tests/sensor/test_sensor.yaml") # Then - assert "s_1->set_device_class(\"voltage\");" in main_cpp + assert 's_1->set_device_class("voltage");' in main_cpp diff --git a/tests/unit_tests/conftest.py b/tests/unit_tests/conftest.py index adef39a0b..41d0f3dad 100644 --- a/tests/unit_tests/conftest.py +++ b/tests/unit_tests/conftest.py @@ -27,4 +27,3 @@ def fixture_path() -> Path: Location of all fixture files. """ return here / "fixtures" - diff --git a/tests/unit_tests/strategies.py b/tests/unit_tests/strategies.py index f4763f047..4bc0482f5 100644 --- a/tests/unit_tests/strategies.py +++ b/tests/unit_tests/strategies.py @@ -12,4 +12,6 @@ def mac_addr_strings(): This consists of six strings representing integers [0..255], without zero-padding, joined by dots. """ - return st.builds("{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}".format, *(6 * [st.integers(0, 255)])) + return st.builds( + "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}".format, *(6 * [st.integers(0, 255)]) + ) diff --git a/tests/unit_tests/test_codegen.py b/tests/unit_tests/test_codegen.py index 931e191de..9f402465f 100644 --- a/tests/unit_tests/test_codegen.py +++ b/tests/unit_tests/test_codegen.py @@ -4,23 +4,75 @@ from esphome import codegen as cg # Test interface remains the same. -@pytest.mark.parametrize("attr", ( - # from cpp_generator - "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 cpp_helpers - "gpio_pin_expression", "register_component", "build_registry_entry", - "build_registry_list", "extract_registry_entry_config", "register_parented", - "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", - # from cpp_types - "PollingComponent", "Application", "optional", "arduino_json_ns", "JsonObject", - "JsonObjectRef", "JsonObjectConstRef", "Controller", "GPIOPin" -)) +@pytest.mark.parametrize( + "attr", + ( + # from cpp_generator + "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 cpp_helpers + "gpio_pin_expression", + "register_component", + "build_registry_entry", + "build_registry_list", + "extract_registry_entry_config", + "register_parented", + "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", + # from cpp_types + "PollingComponent", + "Application", + "optional", + "arduino_json_ns", + "JsonObject", + "JsonObjectRef", + "JsonObjectConstRef", + "Controller", + "GPIOPin", + ), +) def test_exists(attr): assert hasattr(cg, attr) diff --git a/tests/unit_tests/test_config_validation.py b/tests/unit_tests/test_config_validation.py index 846df71a9..949d4251e 100644 --- a/tests/unit_tests/test_config_validation.py +++ b/tests/unit_tests/test_config_validation.py @@ -2,7 +2,7 @@ import pytest import string from hypothesis import given, example -from hypothesis.strategies import one_of, text, integers, booleans, builds +from hypothesis.strategies import one_of, text, integers, builds from esphome import config_validation from esphome.config_validation import Invalid @@ -24,7 +24,7 @@ def test_alphanumeric__valid(value): @pytest.mark.parametrize("value", ("£23", "Foo!")) def test_alphanumeric__invalid(value): with pytest.raises(Invalid): - actual = config_validation.alphanumeric(value) + config_validation.alphanumeric(value) @given(value=text(alphabet=string.ascii_lowercase + string.digits + "_-")) @@ -34,9 +34,7 @@ def test_valid_name__valid(value): assert actual == value -@pytest.mark.parametrize("value", ( - "foo bar", "FooBar", "foo::bar" -)) +@pytest.mark.parametrize("value", ("foo bar", "FooBar", "foo::bar")) def test_valid_name__invalid(value): with pytest.raises(Invalid): config_validation.valid_name(value) @@ -49,9 +47,7 @@ def test_string__valid(value): assert actual == str(value) -@pytest.mark.parametrize("value", ( - {}, [], True, False, None -)) +@pytest.mark.parametrize("value", ({}, [], True, False, None)) def test_string__invalid(value): with pytest.raises(Invalid): config_validation.string(value) @@ -83,23 +79,17 @@ def test_icon__invalid(): config_validation.icon("foo") -@pytest.mark.parametrize("value", ( - "True", "YES", "on", "enAblE", True -)) +@pytest.mark.parametrize("value", ("True", "YES", "on", "enAblE", True)) def test_boolean__valid_true(value): assert config_validation.boolean(value) is True -@pytest.mark.parametrize("value", ( - "False", "NO", "off", "disAblE", False -)) +@pytest.mark.parametrize("value", ("False", "NO", "off", "disAblE", False)) def test_boolean__valid_false(value): assert config_validation.boolean(value) is False -@pytest.mark.parametrize("value", ( - None, 1, 0, "foo" -)) +@pytest.mark.parametrize("value", (None, 1, 0, "foo")) def test_boolean__invalid(value): with pytest.raises(Invalid, match="Expected boolean value"): config_validation.boolean(value) diff --git a/tests/unit_tests/test_core.py b/tests/unit_tests/test_core.py index 27b64ec3d..fd3f17127 100644 --- a/tests/unit_tests/test_core.py +++ b/tests/unit_tests/test_core.py @@ -8,13 +8,16 @@ from esphome import core, const class TestHexInt: - @pytest.mark.parametrize("value, expected", ( - (1, "0x01"), - (255, "0xFF"), - (128, "0x80"), - (256, "0x100"), - (-1, "-0x01"), # TODO: this currently fails - )) + @pytest.mark.parametrize( + "value, expected", + ( + (1, "0x01"), + (255, "0xFF"), + (128, "0x80"), + (256, "0x100"), + (-1, "-0x01"), # TODO: this currently fails + ), + ) def test_str(self, value, expected): target = core.HexInt(value) @@ -68,18 +71,14 @@ class TestMACAddress: assert actual.text == "0xDEADBEEF00FFULL" -@pytest.mark.parametrize("value", ( - 1, 2, -1, 0, 1.0, -1.0, 42.0009, -42.0009 -)) +@pytest.mark.parametrize("value", (1, 2, -1, 0, 1.0, -1.0, 42.0009, -42.0009)) def test_is_approximately_integer__in_range(value): actual = core.is_approximately_integer(value) assert actual is True -@pytest.mark.parametrize("value", ( - 42.01, -42.01, 1.5 -)) +@pytest.mark.parametrize("value", (42.01, -42.01, 1.5)) def test_is_approximately_integer__not_in_range(value): actual = core.is_approximately_integer(value) @@ -87,26 +86,29 @@ def test_is_approximately_integer__not_in_range(value): class TestTimePeriod: - @pytest.mark.parametrize("kwargs, expected", ( - ({}, {}), - ({"microseconds": 1}, {"microseconds": 1}), - ({"microseconds": 1.0001}, {"microseconds": 1}), - ({"milliseconds": 2}, {"milliseconds": 2}), - ({"milliseconds": 2.0001}, {"milliseconds": 2}), - ({"milliseconds": 2.01}, {"milliseconds": 2, "microseconds": 10}), - ({"seconds": 3}, {"seconds": 3}), - ({"seconds": 3.0001}, {"seconds": 3}), - ({"seconds": 3.01}, {"seconds": 3, "milliseconds": 10}), - ({"minutes": 4}, {"minutes": 4}), - ({"minutes": 4.0001}, {"minutes": 4}), - ({"minutes": 4.1}, {"minutes": 4, "seconds": 6}), - ({"hours": 5}, {"hours": 5}), - ({"hours": 5.0001}, {"hours": 5}), - ({"hours": 5.1}, {"hours": 5, "minutes": 6}), - ({"days": 6}, {"days": 6}), - ({"days": 6.0001}, {"days": 6}), - ({"days": 6.1}, {"days": 6, "hours": 2, "minutes": 24}), - )) + @pytest.mark.parametrize( + "kwargs, expected", + ( + ({}, {}), + ({"microseconds": 1}, {"microseconds": 1}), + ({"microseconds": 1.0001}, {"microseconds": 1}), + ({"milliseconds": 2}, {"milliseconds": 2}), + ({"milliseconds": 2.0001}, {"milliseconds": 2}), + ({"milliseconds": 2.01}, {"milliseconds": 2, "microseconds": 10}), + ({"seconds": 3}, {"seconds": 3}), + ({"seconds": 3.0001}, {"seconds": 3}), + ({"seconds": 3.01}, {"seconds": 3, "milliseconds": 10}), + ({"minutes": 4}, {"minutes": 4}), + ({"minutes": 4.0001}, {"minutes": 4}), + ({"minutes": 4.1}, {"minutes": 4, "seconds": 6}), + ({"hours": 5}, {"hours": 5}), + ({"hours": 5.0001}, {"hours": 5}), + ({"hours": 5.1}, {"hours": 5, "minutes": 6}), + ({"days": 6}, {"days": 6}), + ({"days": 6.0001}, {"days": 6}), + ({"days": 6.1}, {"days": 6, "hours": 2, "minutes": 24}), + ), + ) def test_init(self, kwargs, expected): target = core.TimePeriod(**kwargs) @@ -118,26 +120,29 @@ class TestTimePeriod: with pytest.raises(ValueError, match="Maximum precision is microseconds"): core.TimePeriod(microseconds=1.1) - @pytest.mark.parametrize("kwargs, expected", ( - ({}, "0s"), - ({"microseconds": 1}, "1us"), - ({"microseconds": 1.0001}, "1us"), - ({"milliseconds": 2}, "2ms"), - ({"milliseconds": 2.0001}, "2ms"), - ({"milliseconds": 2.01}, "2010us"), - ({"seconds": 3}, "3s"), - ({"seconds": 3.0001}, "3s"), - ({"seconds": 3.01}, "3010ms"), - ({"minutes": 4}, "4min"), - ({"minutes": 4.0001}, "4min"), - ({"minutes": 4.1}, "246s"), - ({"hours": 5}, "5h"), - ({"hours": 5.0001}, "5h"), - ({"hours": 5.1}, "306min"), - ({"days": 6}, "6d"), - ({"days": 6.0001}, "6d"), - ({"days": 6.1}, "8784min"), - )) + @pytest.mark.parametrize( + "kwargs, expected", + ( + ({}, "0s"), + ({"microseconds": 1}, "1us"), + ({"microseconds": 1.0001}, "1us"), + ({"milliseconds": 2}, "2ms"), + ({"milliseconds": 2.0001}, "2ms"), + ({"milliseconds": 2.01}, "2010us"), + ({"seconds": 3}, "3s"), + ({"seconds": 3.0001}, "3s"), + ({"seconds": 3.01}, "3010ms"), + ({"minutes": 4}, "4min"), + ({"minutes": 4.0001}, "4min"), + ({"minutes": 4.1}, "246s"), + ({"hours": 5}, "5h"), + ({"hours": 5.0001}, "5h"), + ({"hours": 5.1}, "306min"), + ({"days": 6}, "6d"), + ({"days": 6.0001}, "6d"), + ({"days": 6.1}, "8784min"), + ), + ) def test_str(self, kwargs, expected): target = core.TimePeriod(**kwargs) @@ -145,61 +150,59 @@ class TestTimePeriod: assert actual == expected - @pytest.mark.parametrize("comparison, other, expected", ( - ("__eq__", core.TimePeriod(microseconds=900), False), - ("__eq__", core.TimePeriod(milliseconds=1), True), - ("__eq__", core.TimePeriod(microseconds=1100), False), - ("__eq__", 1000, NotImplemented), - ("__eq__", "1000", NotImplemented), - ("__eq__", True, NotImplemented), - ("__eq__", object(), NotImplemented), - ("__eq__", None, NotImplemented), - - ("__ne__", core.TimePeriod(microseconds=900), True), - ("__ne__", core.TimePeriod(milliseconds=1), False), - ("__ne__", core.TimePeriod(microseconds=1100), True), - ("__ne__", 1000, NotImplemented), - ("__ne__", "1000", NotImplemented), - ("__ne__", True, NotImplemented), - ("__ne__", object(), NotImplemented), - ("__ne__", None, NotImplemented), - - ("__lt__", core.TimePeriod(microseconds=900), False), - ("__lt__", core.TimePeriod(milliseconds=1), False), - ("__lt__", core.TimePeriod(microseconds=1100), True), - ("__lt__", 1000, NotImplemented), - ("__lt__", "1000", NotImplemented), - ("__lt__", True, NotImplemented), - ("__lt__", object(), NotImplemented), - ("__lt__", None, NotImplemented), - - ("__gt__", core.TimePeriod(microseconds=900), True), - ("__gt__", core.TimePeriod(milliseconds=1), False), - ("__gt__", core.TimePeriod(microseconds=1100), False), - ("__gt__", 1000, NotImplemented), - ("__gt__", "1000", NotImplemented), - ("__gt__", True, NotImplemented), - ("__gt__", object(), NotImplemented), - ("__gt__", None, NotImplemented), - - ("__le__", core.TimePeriod(microseconds=900), False), - ("__le__", core.TimePeriod(milliseconds=1), True), - ("__le__", core.TimePeriod(microseconds=1100), True), - ("__le__", 1000, NotImplemented), - ("__le__", "1000", NotImplemented), - ("__le__", True, NotImplemented), - ("__le__", object(), NotImplemented), - ("__le__", None, NotImplemented), - - ("__ge__", core.TimePeriod(microseconds=900), True), - ("__ge__", core.TimePeriod(milliseconds=1), True), - ("__ge__", core.TimePeriod(microseconds=1100), False), - ("__ge__", 1000, NotImplemented), - ("__ge__", "1000", NotImplemented), - ("__ge__", True, NotImplemented), - ("__ge__", object(), NotImplemented), - ("__ge__", None, NotImplemented), - )) + @pytest.mark.parametrize( + "comparison, other, expected", + ( + ("__eq__", core.TimePeriod(microseconds=900), False), + ("__eq__", core.TimePeriod(milliseconds=1), True), + ("__eq__", core.TimePeriod(microseconds=1100), False), + ("__eq__", 1000, NotImplemented), + ("__eq__", "1000", NotImplemented), + ("__eq__", True, NotImplemented), + ("__eq__", object(), NotImplemented), + ("__eq__", None, NotImplemented), + ("__ne__", core.TimePeriod(microseconds=900), True), + ("__ne__", core.TimePeriod(milliseconds=1), False), + ("__ne__", core.TimePeriod(microseconds=1100), True), + ("__ne__", 1000, NotImplemented), + ("__ne__", "1000", NotImplemented), + ("__ne__", True, NotImplemented), + ("__ne__", object(), NotImplemented), + ("__ne__", None, NotImplemented), + ("__lt__", core.TimePeriod(microseconds=900), False), + ("__lt__", core.TimePeriod(milliseconds=1), False), + ("__lt__", core.TimePeriod(microseconds=1100), True), + ("__lt__", 1000, NotImplemented), + ("__lt__", "1000", NotImplemented), + ("__lt__", True, NotImplemented), + ("__lt__", object(), NotImplemented), + ("__lt__", None, NotImplemented), + ("__gt__", core.TimePeriod(microseconds=900), True), + ("__gt__", core.TimePeriod(milliseconds=1), False), + ("__gt__", core.TimePeriod(microseconds=1100), False), + ("__gt__", 1000, NotImplemented), + ("__gt__", "1000", NotImplemented), + ("__gt__", True, NotImplemented), + ("__gt__", object(), NotImplemented), + ("__gt__", None, NotImplemented), + ("__le__", core.TimePeriod(microseconds=900), False), + ("__le__", core.TimePeriod(milliseconds=1), True), + ("__le__", core.TimePeriod(microseconds=1100), True), + ("__le__", 1000, NotImplemented), + ("__le__", "1000", NotImplemented), + ("__le__", True, NotImplemented), + ("__le__", object(), NotImplemented), + ("__le__", None, NotImplemented), + ("__ge__", core.TimePeriod(microseconds=900), True), + ("__ge__", core.TimePeriod(milliseconds=1), True), + ("__ge__", core.TimePeriod(microseconds=1100), False), + ("__ge__", 1000, NotImplemented), + ("__ge__", "1000", NotImplemented), + ("__ge__", True, NotImplemented), + ("__ge__", object(), NotImplemented), + ("__ge__", None, NotImplemented), + ), + ) def test_comparison(self, comparison, other, expected): target = core.TimePeriod(microseconds=1000) @@ -238,19 +241,19 @@ class TestLambda: "it.strftime(64, 0, ", "my_font", "", - ", TextAlign::TOP_CENTER, \"%H:%M:%S\", ", + ', TextAlign::TOP_CENTER, "%H:%M:%S", ', "esptime", ".", "now());\nit.printf(64, 16, ", "my_font2", "", - ", TextAlign::TOP_CENTER, \"%.1f°C (%.1f%%)\", ", + ', TextAlign::TOP_CENTER, "%.1f°C (%.1f%%)", ', "office_tmp", ".", "state, ", "office_hmd", ".", - "state);\n \nint x = 4; " + "state);\n \nint x = 4; ", ] def test_requires_ids(self): @@ -296,24 +299,33 @@ class TestID: def target(self): return core.ID(None, is_declaration=True, type="binary_sensor::Example") - @pytest.mark.parametrize("id, is_manual, expected", ( - ("foo", None, True), - (None, None, False), - ("foo", True, True), - ("foo", False, False), - (None, True, True), - )) + @pytest.mark.parametrize( + "id, is_manual, expected", + ( + ("foo", None, True), + (None, None, False), + ("foo", True, True), + ("foo", False, False), + (None, True, True), + ), + ) def test_init__resolve_is_manual(self, id, is_manual, expected): target = core.ID(id, is_manual=is_manual) assert target.is_manual == expected - @pytest.mark.parametrize("registered_ids, expected", ( - ([], "binary_sensor_example"), - (["binary_sensor_example"], "binary_sensor_example_2"), - (["foo"], "binary_sensor_example"), - (["binary_sensor_example", "foo", "binary_sensor_example_2"], "binary_sensor_example_3"), - )) + @pytest.mark.parametrize( + "registered_ids, expected", + ( + ([], "binary_sensor_example"), + (["binary_sensor_example"], "binary_sensor_example_2"), + (["foo"], "binary_sensor_example"), + ( + ["binary_sensor_example", "foo", "binary_sensor_example_2"], + "binary_sensor_example_3", + ), + ), + ) def test_resolve(self, target, registered_ids, expected): actual = target.resolve(registered_ids) @@ -326,18 +338,23 @@ class TestID: actual = target.copy() assert actual is not target - assert all(getattr(actual, n) == getattr(target, n) - for n in ("id", "is_declaration", "type", "is_manual")) + assert all( + getattr(actual, n) == getattr(target, n) + for n in ("id", "is_declaration", "type", "is_manual") + ) - @pytest.mark.parametrize("comparison, other, expected", ( - ("__eq__", core.ID(id="foo"), True), - ("__eq__", core.ID(id="bar"), False), - ("__eq__", 1000, NotImplemented), - ("__eq__", "1000", NotImplemented), - ("__eq__", True, NotImplemented), - ("__eq__", object(), NotImplemented), - ("__eq__", None, NotImplemented), - )) + @pytest.mark.parametrize( + "comparison, other, expected", + ( + ("__eq__", core.ID(id="foo"), True), + ("__eq__", core.ID(id="bar"), False), + ("__eq__", 1000, NotImplemented), + ("__eq__", "1000", NotImplemented), + ("__eq__", True, NotImplemented), + ("__eq__", object(), NotImplemented), + ("__eq__", None, NotImplemented), + ), + ) def test_comparison(self, comparison, other, expected): target = core.ID(id="foo") @@ -384,14 +401,17 @@ class TestDocumentRange: class TestDefine: - @pytest.mark.parametrize("name, value, prop, expected", ( - ("ANSWER", None, "as_build_flag", "-DANSWER"), - ("ANSWER", None, "as_macro", "#define ANSWER"), - ("ANSWER", None, "as_tuple", ("ANSWER", None)), - ("ANSWER", 42, "as_build_flag", "-DANSWER=42"), - ("ANSWER", 42, "as_macro", "#define ANSWER 42"), - ("ANSWER", 42, "as_tuple", ("ANSWER", 42)), - )) + @pytest.mark.parametrize( + "name, value, prop, expected", + ( + ("ANSWER", None, "as_build_flag", "-DANSWER"), + ("ANSWER", None, "as_macro", "#define ANSWER"), + ("ANSWER", None, "as_tuple", ("ANSWER", None)), + ("ANSWER", 42, "as_build_flag", "-DANSWER=42"), + ("ANSWER", 42, "as_macro", "#define ANSWER 42"), + ("ANSWER", 42, "as_tuple", ("ANSWER", 42)), + ), + ) def test_properties(self, name, value, prop, expected): target = core.Define(name, value) @@ -399,18 +419,21 @@ class TestDefine: assert actual == expected - @pytest.mark.parametrize("comparison, other, expected", ( - ("__eq__", core.Define(name="FOO", value=42), True), - ("__eq__", core.Define(name="FOO", value=13), False), - ("__eq__", core.Define(name="FOO"), False), - ("__eq__", core.Define(name="BAR", value=42), False), - ("__eq__", core.Define(name="BAR"), False), - ("__eq__", 1000, NotImplemented), - ("__eq__", "1000", NotImplemented), - ("__eq__", True, NotImplemented), - ("__eq__", object(), NotImplemented), - ("__eq__", None, NotImplemented), - )) + @pytest.mark.parametrize( + "comparison, other, expected", + ( + ("__eq__", core.Define(name="FOO", value=42), True), + ("__eq__", core.Define(name="FOO", value=13), False), + ("__eq__", core.Define(name="FOO"), False), + ("__eq__", core.Define(name="BAR", value=42), False), + ("__eq__", core.Define(name="BAR"), False), + ("__eq__", 1000, NotImplemented), + ("__eq__", "1000", NotImplemented), + ("__eq__", True, NotImplemented), + ("__eq__", object(), NotImplemented), + ("__eq__", None, NotImplemented), + ), + ) def test_comparison(self, comparison, other, expected): target = core.Define(name="FOO", value=42) @@ -420,12 +443,15 @@ class TestDefine: class TestLibrary: - @pytest.mark.parametrize("name, value, prop, expected", ( - ("mylib", None, "as_lib_dep", "mylib"), - ("mylib", None, "as_tuple", ("mylib", None)), - ("mylib", "1.2.3", "as_lib_dep", "mylib@1.2.3"), - ("mylib", "1.2.3", "as_tuple", ("mylib", "1.2.3")), - )) + @pytest.mark.parametrize( + "name, value, prop, expected", + ( + ("mylib", None, "as_lib_dep", "mylib"), + ("mylib", None, "as_tuple", ("mylib", None)), + ("mylib", "1.2.3", "as_lib_dep", "mylib@1.2.3"), + ("mylib", "1.2.3", "as_tuple", ("mylib", "1.2.3")), + ), + ) def test_properties(self, name, value, prop, expected): target = core.Library(name, value) @@ -433,16 +459,19 @@ class TestLibrary: assert actual == expected - @pytest.mark.parametrize("comparison, other, expected", ( - ("__eq__", core.Library(name="libfoo", version="1.2.3"), True), - ("__eq__", core.Library(name="libfoo", version="1.2.4"), False), - ("__eq__", core.Library(name="libbar", version="1.2.3"), False), - ("__eq__", 1000, NotImplemented), - ("__eq__", "1000", NotImplemented), - ("__eq__", True, NotImplemented), - ("__eq__", object(), NotImplemented), - ("__eq__", None, NotImplemented), - )) + @pytest.mark.parametrize( + "comparison, other, expected", + ( + ("__eq__", core.Library(name="libfoo", version="1.2.3"), True), + ("__eq__", core.Library(name="libfoo", version="1.2.4"), False), + ("__eq__", core.Library(name="libbar", version="1.2.3"), False), + ("__eq__", 1000, NotImplemented), + ("__eq__", "1000", NotImplemented), + ("__eq__", True, NotImplemented), + ("__eq__", object(), NotImplemented), + ("__eq__", None, NotImplemented), + ), + ) def test_comparison(self, comparison, other, expected): target = core.Library(name="libfoo", version="1.2.3") diff --git a/tests/unit_tests/test_cpp_generator.py b/tests/unit_tests/test_cpp_generator.py index b130124b5..5a8087ffa 100644 --- a/tests/unit_tests/test_cpp_generator.py +++ b/tests/unit_tests/test_cpp_generator.py @@ -9,18 +9,18 @@ from esphome import cpp_types as ct class TestExpressions: - @pytest.mark.parametrize("target, expected", ( - (cg.RawExpression("foo && bar"), "foo && bar"), - - (cg.AssignmentExpression(None, None, "foo", "bar", None), 'foo = "bar"'), - (cg.AssignmentExpression(ct.float_, "*", "foo", 1, None), 'float *foo = 1'), - (cg.AssignmentExpression(ct.float_, "", "foo", 1, None), 'float foo = 1'), - - (cg.VariableDeclarationExpression(ct.int32, "*", "foo"), "int32_t *foo"), - (cg.VariableDeclarationExpression(ct.int32, "", "foo"), "int32_t foo"), - - (cg.ParameterExpression(ct.std_string, "foo"), "std::string foo"), - )) + @pytest.mark.parametrize( + "target, expected", + ( + (cg.RawExpression("foo && bar"), "foo && bar"), + (cg.AssignmentExpression(None, None, "foo", "bar", None), 'foo = "bar"'), + (cg.AssignmentExpression(ct.float_, "*", "foo", 1, None), "float *foo = 1"), + (cg.AssignmentExpression(ct.float_, "", "foo", 1, None), "float foo = 1"), + (cg.VariableDeclarationExpression(ct.int32, "*", "foo"), "int32_t *foo"), + (cg.VariableDeclarationExpression(ct.int32, "", "foo"), "int32_t foo"), + (cg.ParameterExpression(ct.std_string, "foo"), "std::string foo"), + ), + ) def test_str__simple(self, target: cg.Expression, expected: str): actual = str(target) @@ -67,10 +67,7 @@ class TestTemplateArguments: class TestCallExpression: def test_str__no_template_args(self): - target = cg.CallExpression( - cg.RawExpression("my_function"), - 1, "2", False - ) + target = cg.CallExpression(cg.RawExpression("my_function"), 1, "2", False) actual = str(target) @@ -80,7 +77,9 @@ class TestCallExpression: target = cg.CallExpression( cg.RawExpression("my_function"), cg.TemplateArguments(int, float), - 1, "2", False + 1, + "2", + False, ) actual = str(target) @@ -100,36 +99,32 @@ class TestStructInitializer: actual = str(target) - assert actual == 'foo::MyStruct{\n' \ - ' .state = "on",\n' \ - ' .min_length = 1,\n' \ - ' .max_length = 5,\n' \ - '}' + assert ( + actual == "foo::MyStruct{\n" + ' .state = "on",\n' + " .min_length = 1,\n" + " .max_length = 5,\n" + "}" + ) class TestArrayInitializer: def test_str__empty(self): - target = cg.ArrayInitializer( - None, None - ) + target = cg.ArrayInitializer(None, None) actual = str(target) assert actual == "{}" def test_str__not_multiline(self): - target = cg.ArrayInitializer( - 1, 2, 3, 4 - ) + target = cg.ArrayInitializer(1, 2, 3, 4) actual = str(target) assert actual == "{1, 2, 3, 4}" def test_str__multiline(self): - target = cg.ArrayInitializer( - 1, 2, 3, 4, multiline=True - ) + target = cg.ArrayInitializer(1, 2, 3, 4, multiline=True) actual = str(target) @@ -169,7 +164,7 @@ class TestLambdaExpression: def test_str__with_return(self): target = cg.LambdaExpression( - ("return (foo == 5) && (bar < 10));", ), + ("return (foo == 5) && (bar < 10));",), cg.ParameterListExpression((int, "foo"), (float, "bar")), "=", bool, @@ -185,27 +180,26 @@ class TestLambdaExpression: class TestLiterals: - @pytest.mark.parametrize("target, expected", ( - (cg.StringLiteral("foo"), '"foo"'), - - (cg.IntLiteral(0), "0"), - (cg.IntLiteral(42), "42"), - (cg.IntLiteral(4304967295), "4304967295ULL"), - (cg.IntLiteral(2150483647), "2150483647UL"), - (cg.IntLiteral(-2150083647), "-2150083647LL"), - - (cg.BoolLiteral(True), "true"), - (cg.BoolLiteral(False), "false"), - - (cg.HexIntLiteral(0), "0x00"), - (cg.HexIntLiteral(42), "0x2A"), - (cg.HexIntLiteral(682), "0x2AA"), - - (cg.FloatLiteral(0.0), "0.0f"), - (cg.FloatLiteral(4.2), "4.2f"), - (cg.FloatLiteral(1.23456789), "1.23456789f"), - (cg.FloatLiteral(math.nan), "NAN"), - )) + @pytest.mark.parametrize( + "target, expected", + ( + (cg.StringLiteral("foo"), '"foo"'), + (cg.IntLiteral(0), "0"), + (cg.IntLiteral(42), "42"), + (cg.IntLiteral(4304967295), "4304967295ULL"), + (cg.IntLiteral(2150483647), "2150483647UL"), + (cg.IntLiteral(-2150083647), "-2150083647LL"), + (cg.BoolLiteral(True), "true"), + (cg.BoolLiteral(False), "false"), + (cg.HexIntLiteral(0), "0x00"), + (cg.HexIntLiteral(42), "0x2A"), + (cg.HexIntLiteral(682), "0x2AA"), + (cg.FloatLiteral(0.0), "0.0f"), + (cg.FloatLiteral(4.2), "4.2f"), + (cg.FloatLiteral(1.23456789), "1.23456789f"), + (cg.FloatLiteral(math.nan), "NAN"), + ), + ) def test_str__simple(self, target: cg.Literal, expected: str): actual = str(target) @@ -216,7 +210,9 @@ FAKE_ENUM_VALUE = cg.EnumValue() FAKE_ENUM_VALUE.enum_value = "foo" -@pytest.mark.parametrize("obj, expected_type", ( +@pytest.mark.parametrize( + "obj, expected_type", + ( (cg.RawExpression("foo"), cg.RawExpression), (FAKE_ENUM_VALUE, cg.StringLiteral), (True, cg.BoolLiteral), @@ -230,49 +226,59 @@ FAKE_ENUM_VALUE.enum_value = "foo" (cg.TimePeriodMinutes(minutes=42), cg.IntLiteral), ((1, 2, 3), cg.ArrayInitializer), ([1, 2, 3], cg.ArrayInitializer), -)) + ), +) def test_safe_exp__allowed_values(obj, expected_type): actual = cg.safe_exp(obj) assert isinstance(actual, expected_type) -@pytest.mark.parametrize("obj, expected_type", ( +@pytest.mark.parametrize( + "obj, expected_type", + ( (bool, ct.bool_), (int, ct.int32), (float, ct.float_), -)) + ), +) def test_safe_exp__allowed_types(obj, expected_type): actual = cg.safe_exp(obj) assert actual is expected_type -@pytest.mark.parametrize("obj, expected_error", ( +@pytest.mark.parametrize( + "obj, expected_error", + ( (cg.ID("foo"), "Object foo is an ID."), ((x for x in "foo"), r"Object <.*> is a coroutine."), (None, "Object is not an expression"), -)) + ), +) def test_safe_exp__invalid_values(obj, expected_error): with pytest.raises(ValueError, match=expected_error): cg.safe_exp(obj) class TestStatements: - @pytest.mark.parametrize("target, expected", ( - (cg.RawStatement("foo && bar"), "foo && bar"), - - (cg.ExpressionStatement("foo"), '"foo";'), - (cg.ExpressionStatement(42), '42;'), - - (cg.LineComment("The point of foo is..."), "// The point of foo is..."), - (cg.LineComment("Help help\nI'm being repressed"), "// Help help\n// I'm being repressed"), - + @pytest.mark.parametrize( + "target, expected", ( - cg.ProgmemAssignmentExpression(ct.uint16, "foo", "bar", None), - 'static const uint16_t foo[] PROGMEM = "bar"' - ) - )) + (cg.RawStatement("foo && bar"), "foo && bar"), + (cg.ExpressionStatement("foo"), '"foo";'), + (cg.ExpressionStatement(42), "42;"), + (cg.LineComment("The point of foo is..."), "// The point of foo is..."), + ( + cg.LineComment("Help help\nI'm being repressed"), + "// Help help\n// I'm being repressed", + ), + ( + cg.ProgmemAssignmentExpression(ct.uint16, "foo", "bar", None), + 'static const uint16_t foo[] PROGMEM = "bar"', + ), + ), + ) def test_str__simple(self, target: cg.Statement, expected: str): actual = str(target) diff --git a/tests/unit_tests/test_cpp_helpers.py b/tests/unit_tests/test_cpp_helpers.py index d8f32e7a5..c6f37f6b5 100644 --- a/tests/unit_tests/test_cpp_helpers.py +++ b/tests/unit_tests/test_cpp_helpers.py @@ -15,11 +15,9 @@ def test_gpio_pin_expression__conf_is_none(monkeypatch): def test_gpio_pin_expression__new_pin(monkeypatch): - target = ch.gpio_pin_expression({ - const.CONF_NUMBER: 42, - const.CONF_MODE: "input", - const.CONF_INVERTED: False - }) + target = ch.gpio_pin_expression( + {const.CONF_NUMBER: 42, const.CONF_MODE: "input", const.CONF_INVERTED: False} + ) actual = next(target) @@ -71,10 +69,13 @@ def test_register_component__with_setup_priority(monkeypatch): add_mock = Mock() monkeypatch.setattr(ch, "add", add_mock) - target = ch.register_component(var, { - const.CONF_SETUP_PRIORITY: "123", - const.CONF_UPDATE_INTERVAL: "456", - }) + target = ch.register_component( + var, + { + const.CONF_SETUP_PRIORITY: "123", + const.CONF_UPDATE_INTERVAL: "456", + }, + ) actual = next(target) diff --git a/tests/unit_tests/test_helpers.py b/tests/unit_tests/test_helpers.py index 6e89a05bc..00a6b0813 100644 --- a/tests/unit_tests/test_helpers.py +++ b/tests/unit_tests/test_helpers.py @@ -6,69 +6,89 @@ from hypothesis.provisional import ip_addresses from esphome import helpers -@pytest.mark.parametrize("preferred_string, current_strings, expected", ( - ("foo", [], "foo"), - # TODO: Should this actually start at 1? - ("foo", ["foo"], "foo_2"), - ("foo", ("foo",), "foo_2"), - ("foo", ("foo", "foo_2"), "foo_3"), - ("foo", ("foo", "foo_2", "foo_2"), "foo_3"), -)) +@pytest.mark.parametrize( + "preferred_string, current_strings, expected", + ( + ("foo", [], "foo"), + # TODO: Should this actually start at 1? + ("foo", ["foo"], "foo_2"), + ("foo", ("foo",), "foo_2"), + ("foo", ("foo", "foo_2"), "foo_3"), + ("foo", ("foo", "foo_2", "foo_2"), "foo_3"), + ), +) def test_ensure_unique_string(preferred_string, current_strings, expected): actual = helpers.ensure_unique_string(preferred_string, current_strings) assert actual == expected -@pytest.mark.parametrize("text, expected", ( - ("foo", "foo"), - ("foo\nbar", "foo\nbar"), - ("foo\nbar\neek", "foo\n bar\neek"), -)) +@pytest.mark.parametrize( + "text, expected", + ( + ("foo", "foo"), + ("foo\nbar", "foo\nbar"), + ("foo\nbar\neek", "foo\n bar\neek"), + ), +) def test_indent_all_but_first_and_last(text, expected): actual = helpers.indent_all_but_first_and_last(text) assert actual == expected -@pytest.mark.parametrize("text, expected", ( - ("foo", [" foo"]), - ("foo\nbar", [" foo", " bar"]), - ("foo\nbar\neek", [" foo", " bar", " eek"]), -)) +@pytest.mark.parametrize( + "text, expected", + ( + ("foo", [" foo"]), + ("foo\nbar", [" foo", " bar"]), + ("foo\nbar\neek", [" foo", " bar", " eek"]), + ), +) def test_indent_list(text, expected): actual = helpers.indent_list(text) assert actual == expected -@pytest.mark.parametrize("text, expected", ( - ("foo", " foo"), - ("foo\nbar", " foo\n bar"), - ("foo\nbar\neek", " foo\n bar\n eek"), -)) +@pytest.mark.parametrize( + "text, expected", + ( + ("foo", " foo"), + ("foo\nbar", " foo\n bar"), + ("foo\nbar\neek", " foo\n bar\n eek"), + ), +) def test_indent(text, expected): actual = helpers.indent(text) assert actual == expected -@pytest.mark.parametrize("string, expected", ( - ("foo", '"foo"'), - ("foo\nbar", '"foo\\012bar"'), - ("foo\\bar", '"foo\\134bar"'), - ('foo "bar"', '"foo \\042bar\\042"'), - ('foo 🐍', '"foo \\360\\237\\220\\215"'), -)) +@pytest.mark.parametrize( + "string, expected", + ( + ("foo", '"foo"'), + ("foo\nbar", '"foo\\012bar"'), + ("foo\\bar", '"foo\\134bar"'), + ('foo "bar"', '"foo \\042bar\\042"'), + ("foo 🐍", '"foo \\360\\237\\220\\215"'), + ), +) def test_cpp_string_escape(string, expected): actual = helpers.cpp_string_escape(string) assert actual == expected -@pytest.mark.parametrize("host", ( - "127.0.0", "localhost", "127.0.0.b", -)) +@pytest.mark.parametrize( + "host", + ( + "127.0.0", + "localhost", + "127.0.0.b", + ), +) def test_is_ip_address__invalid(host): actual = helpers.is_ip_address(host) @@ -82,13 +102,16 @@ def test_is_ip_address__valid(value): assert actual is True -@pytest.mark.parametrize("var, value, default, expected", ( - ("FOO", None, False, False), - ("FOO", None, True, True), - ("FOO", "", False, False), - ("FOO", "Yes", False, True), - ("FOO", "123", False, True), -)) +@pytest.mark.parametrize( + "var, value, default, expected", + ( + ("FOO", None, False, False), + ("FOO", None, True, True), + ("FOO", "", False, False), + ("FOO", "Yes", False, True), + ("FOO", "123", False, True), + ), +) def test_get_bool_env(monkeypatch, var, value, default, expected): if value is None: monkeypatch.delenv(var, raising=False) @@ -100,10 +123,7 @@ def test_get_bool_env(monkeypatch, var, value, default, expected): assert actual == expected -@pytest.mark.parametrize("value, expected", ( - (None, False), - ("Yes", True) -)) +@pytest.mark.parametrize("value, expected", ((None, False), ("Yes", True))) def test_is_hassio(monkeypatch, value, expected): if value is None: monkeypatch.delenv("ESPHOME_IS_HASSIO", raising=False) @@ -185,20 +205,23 @@ class Test_copy_file_if_changed: assert src.read_text() == dst.read_text() -@pytest.mark.parametrize("file1, file2, expected", ( - # Same file - ("file-a.txt", "file-a.txt", True), - # Different files, different size - ("file-a.txt", "file-b_1.txt", False), - # Different files, same size - ("file-a.txt", "file-c.txt", False), - # Same files - ("file-b_1.txt", "file-b_2.txt", True), - # Not a file - ("file-a.txt", "", False), - # File doesn't exist - ("file-a.txt", "file-d.txt", False), -)) +@pytest.mark.parametrize( + "file1, file2, expected", + ( + # Same file + ("file-a.txt", "file-a.txt", True), + # Different files, different size + ("file-a.txt", "file-b_1.txt", False), + # Different files, same size + ("file-a.txt", "file-c.txt", False), + # Same files + ("file-b_1.txt", "file-b_2.txt", True), + # Not a file + ("file-a.txt", "", False), + # File doesn't exist + ("file-a.txt", "file-d.txt", False), + ), +) def test_file_compare(fixture_path, file1, file2, expected): path1 = fixture_path / "helpers" / file1 path2 = fixture_path / "helpers" / file2 diff --git a/tests/unit_tests/test_pins.py b/tests/unit_tests/test_pins.py index 7d68181ad..6bc6f4d76 100644 --- a/tests/unit_tests/test_pins.py +++ b/tests/unit_tests/test_pins.py @@ -15,12 +15,12 @@ from esphome import pins MOCK_ESP8266_BOARD_ID = "_mock_esp8266" -MOCK_ESP8266_PINS = {'X0': 16, 'X1': 5, 'X2': 4, 'LED': 2} +MOCK_ESP8266_PINS = {"X0": 16, "X1": 5, "X2": 4, "LED": 2} MOCK_ESP8266_BOARD_ALIAS_ID = "_mock_esp8266_alias" MOCK_ESP8266_FLASH_SIZE = pins.FLASH_SIZE_2_MB MOCK_ESP32_BOARD_ID = "_mock_esp32" -MOCK_ESP32_PINS = {'Y0': 12, 'Y1': 8, 'Y2': 3, 'LED': 9, "A0": 8} +MOCK_ESP32_PINS = {"Y0": 12, "Y1": 8, "Y2": 3, "LED": 9, "A0": 8} MOCK_ESP32_BOARD_ALIAS_ID = "_mock_esp32_alias" UNKNOWN_PLATFORM = "STM32" @@ -68,10 +68,13 @@ def core_esp32(core): class Test_lookup_pin: - @pytest.mark.parametrize("value, expected", ( + @pytest.mark.parametrize( + "value, expected", + ( ("X1", 5), ("MOSI", 13), - )) + ), + ) def test_valid_esp8266_pin(self, core_esp8266, value, expected): actual = pins._lookup_pin(value) @@ -84,11 +87,14 @@ class Test_lookup_pin: assert actual == 4 - @pytest.mark.parametrize("value, expected", ( + @pytest.mark.parametrize( + "value, expected", + ( ("Y1", 8), ("A0", 8), ("MOSI", 23), - )) + ), + ) def test_valid_esp32_pin(self, core_esp32, value, expected): actual = pins._lookup_pin(value) @@ -102,7 +108,9 @@ class Test_lookup_pin: assert actual == 3 def test_invalid_pin(self, core_esp8266): - with pytest.raises(Invalid, match="Cannot resolve pin name 'X42' for board _mock_esp8266."): + with pytest.raises( + Invalid, match="Cannot resolve pin name 'X42' for board _mock_esp8266." + ): pins._lookup_pin("X42") def test_unsupported_platform(self, core): @@ -113,13 +121,16 @@ class Test_lookup_pin: class Test_translate_pin: - @pytest.mark.parametrize("value, expected", ( + @pytest.mark.parametrize( + "value, expected", + ( (2, 2), ("3", 3), ("GPIO4", 4), ("TX", 1), ("Y0", 12), - )) + ), + ) def test_valid_values(self, core_esp32, value, expected): actual = pins._translate_pin(value) @@ -137,7 +148,9 @@ class Test_validate_gpio_pin: assert actual == 22 - @pytest.mark.parametrize("value, match", ( + @pytest.mark.parametrize( + "value, match", + ( (-1, "ESP32: Invalid pin number: -1"), (40, "ESP32: Invalid pin number: 40"), (6, "This pin cannot be used on ESP32s and"), @@ -150,7 +163,8 @@ class Test_validate_gpio_pin: (29, "The pin GPIO29 is not usable on ESP32s"), (30, "The pin GPIO30 is not usable on ESP32s"), (31, "The pin GPIO31 is not usable on ESP32s"), - )) + ), + ) def test_esp32_invalid_pin(self, core_esp32, value, match): with pytest.raises(Invalid, match=match): pins.validate_gpio_pin(value) @@ -168,14 +182,17 @@ class Test_validate_gpio_pin: assert actual == 12 - @pytest.mark.parametrize("value, match", ( + @pytest.mark.parametrize( + "value, match", + ( (-1, "ESP8266: Invalid pin number: -1"), (18, "ESP8266: Invalid pin number: 18"), (6, "This pin cannot be used on ESP8266s and"), (7, "This pin cannot be used on ESP8266s and"), (8, "This pin cannot be used on ESP8266s and"), (11, "This pin cannot be used on ESP8266s and"), - )) + ), + ) def test_esp8266_invalid_pin(self, core_esp8266, value, match): with pytest.raises(Invalid, match=match): pins.validate_gpio_pin(value) @@ -196,18 +213,19 @@ class Test_validate_gpio_pin: class Test_input_pin: - @pytest.mark.parametrize("value, expected", ( - ("X0", 16), - )) + @pytest.mark.parametrize("value, expected", (("X0", 16),)) def test_valid_esp8266_values(self, core_esp8266, value, expected): actual = pins.input_pin(value) assert actual == expected - @pytest.mark.parametrize("value, expected", ( + @pytest.mark.parametrize( + "value, expected", + ( ("Y0", 12), (17, 17), - )) + ), + ) def test_valid_esp32_values(self, core_esp32, value, expected): actual = pins.input_pin(value) @@ -226,18 +244,19 @@ class Test_input_pin: class Test_input_pullup_pin: - @pytest.mark.parametrize("value, expected", ( - ("X0", 16), - )) + @pytest.mark.parametrize("value, expected", (("X0", 16),)) def test_valid_esp8266_values(self, core_esp8266, value, expected): actual = pins.input_pullup_pin(value) assert actual == expected - @pytest.mark.parametrize("value, expected", ( + @pytest.mark.parametrize( + "value, expected", + ( ("Y0", 12), (17, 17), - )) + ), + ) def test_valid_esp32_values(self, core_esp32, value, expected): actual = pins.input_pullup_pin(value) @@ -256,18 +275,19 @@ class Test_input_pullup_pin: class Test_output_pin: - @pytest.mark.parametrize("value, expected", ( - ("X0", 16), - )) + @pytest.mark.parametrize("value, expected", (("X0", 16),)) def test_valid_esp8266_values(self, core_esp8266, value, expected): actual = pins.output_pin(value) assert actual == expected - @pytest.mark.parametrize("value, expected", ( + @pytest.mark.parametrize( + "value, expected", + ( ("Y0", 12), (17, 17), - )) + ), + ) def test_valid_esp32_values(self, core_esp32, value, expected): actual = pins.output_pin(value) @@ -291,18 +311,19 @@ class Test_output_pin: class Test_analog_pin: - @pytest.mark.parametrize("value, expected", ( - (17, 17), - )) + @pytest.mark.parametrize("value, expected", ((17, 17),)) def test_valid_esp8266_values(self, core_esp8266, value, expected): actual = pins.analog_pin(value) assert actual == expected - @pytest.mark.parametrize("value, expected", ( + @pytest.mark.parametrize( + "value, expected", + ( (32, 32), (39, 39), - )) + ), + ) def test_valid_esp32_values(self, core_esp32, value, expected): actual = pins.analog_pin(value) diff --git a/tests/unit_tests/test_wizard.py b/tests/unit_tests/test_wizard.py index 2baff80ed..6c952608d 100644 --- a/tests/unit_tests/test_wizard.py +++ b/tests/unit_tests/test_wizard.py @@ -1,4 +1,4 @@ -""" Tests for the wizard.py file """ +"""Tests for the wizard.py file.""" import esphome.wizard as wz import pytest @@ -14,7 +14,7 @@ def default_config(): "board": "test_board", "ssid": "test_ssid", "psk": "test_psk", - "password": "" + "password": "", } @@ -35,13 +35,13 @@ def test_sanitize_quotes_replaces_with_escaped_char(): The sanitize_quotes function should replace double quotes with their escaped equivalents """ # Given - input_str = "\"key\": \"value\"" + input_str = '"key": "value"' # When output_str = wz.sanitize_double_quotes(input_str) # Then - assert output_str == "\\\"key\\\": \\\"value\\\"" + assert output_str == '\\"key\\": \\"value\\"' def test_config_file_fallback_ap_includes_descriptive_name(default_config): @@ -55,7 +55,7 @@ def test_config_file_fallback_ap_includes_descriptive_name(default_config): config = wz.wizard_file(**default_config) # Then - assert f"ssid: \"Test Node Fallback Hotspot\"" in config + assert 'ssid: "Test Node Fallback Hotspot"' in config def test_config_file_fallback_ap_name_less_than_32_chars(default_config): @@ -70,7 +70,7 @@ def test_config_file_fallback_ap_name_less_than_32_chars(default_config): config = wz.wizard_file(**default_config) # Then - assert f"ssid: \"A Very Long Name For This Node\"" in config + assert 'ssid: "A Very Long Name For This Node"' in config def test_config_file_should_include_ota(default_config): @@ -115,7 +115,9 @@ def test_wizard_write_sets_platform(default_config, tmp_path, monkeypatch): assert f"platform: {default_config['platform']}" in generated_config -def test_wizard_write_defaults_platform_from_board_esp8266(default_config, tmp_path, monkeypatch): +def test_wizard_write_defaults_platform_from_board_esp8266( + default_config, tmp_path, monkeypatch +): """ If the platform is not explicitly set, use "ESP8266" if the board is one of the ESP8266 boards """ @@ -133,7 +135,9 @@ def test_wizard_write_defaults_platform_from_board_esp8266(default_config, tmp_p assert "platform: ESP8266" in generated_config -def test_wizard_write_defaults_platform_from_board_esp32(default_config, tmp_path, monkeypatch): +def test_wizard_write_defaults_platform_from_board_esp32( + default_config, tmp_path, monkeypatch +): """ If the platform is not explicitly set, use "ESP32" if the board is not one of the ESP8266 boards """ @@ -167,7 +171,9 @@ def test_safe_print_step_prints_step_number_and_description(monkeypatch): # Then # Collect arguments to all safe_print() calls (substituting "" for any empty ones) - all_args = [call.args[0] if len(call.args) else "" for call in wz.safe_print.call_args_list] + all_args = [ + call.args[0] if len(call.args) else "" for call in wz.safe_print.call_args_list + ] assert any(step_desc == arg for arg in all_args) assert any(f"STEP {step_num}" in arg for arg in all_args) @@ -212,7 +218,7 @@ def test_strip_accents_removes_diacritics(): """ # Given - input_str = u"Kühne" + input_str = "Kühne" expected_str = "Kuhne" # When @@ -264,7 +270,7 @@ def test_wizard_accepts_default_answers_esp8266(tmpdir, monkeypatch, wizard_answ monkeypatch.setattr("builtins.input", input_mock) monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) - monkeypatch.setattr(wz, "wizard_write", MagicMock()) + monkeypatch.setattr(wz, "wizard_write", MagicMock()) # When retval = wz.wizard(str(config_file)) @@ -286,7 +292,7 @@ def test_wizard_accepts_default_answers_esp32(tmpdir, monkeypatch, wizard_answer monkeypatch.setattr("builtins.input", input_mock) monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) - monkeypatch.setattr(wz, "wizard_write", MagicMock()) + monkeypatch.setattr(wz, "wizard_write", MagicMock()) # When retval = wz.wizard(str(config_file)) @@ -306,14 +312,16 @@ def test_wizard_offers_better_node_name(tmpdir, monkeypatch, wizard_answers): # Given wizard_answers[0] = "Küche #2" expected_name = "kuche_2" - monkeypatch.setattr(wz, "default_input", MagicMock(side_effect=lambda _, default: default)) + monkeypatch.setattr( + wz, "default_input", MagicMock(side_effect=lambda _, default: default) + ) config_file = tmpdir.join("test.yaml") input_mock = MagicMock(side_effect=wizard_answers) monkeypatch.setattr("builtins.input", input_mock) monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) - monkeypatch.setattr(wz, "wizard_write", MagicMock()) + monkeypatch.setattr(wz, "wizard_write", MagicMock()) # When retval = wz.wizard(str(config_file)) @@ -336,7 +344,7 @@ def test_wizard_requires_correct_platform(tmpdir, monkeypatch, wizard_answers): monkeypatch.setattr("builtins.input", input_mock) monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) - monkeypatch.setattr(wz, "wizard_write", MagicMock()) + monkeypatch.setattr(wz, "wizard_write", MagicMock()) # When retval = wz.wizard(str(config_file)) @@ -358,7 +366,7 @@ def test_wizard_requires_correct_board(tmpdir, monkeypatch, wizard_answers): monkeypatch.setattr("builtins.input", input_mock) monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) - monkeypatch.setattr(wz, "wizard_write", MagicMock()) + monkeypatch.setattr(wz, "wizard_write", MagicMock()) # When retval = wz.wizard(str(config_file)) @@ -380,7 +388,7 @@ def test_wizard_requires_valid_ssid(tmpdir, monkeypatch, wizard_answers): monkeypatch.setattr("builtins.input", input_mock) monkeypatch.setattr(wz, "safe_print", lambda t=None: 0) monkeypatch.setattr(wz, "sleep", lambda _: 0) - monkeypatch.setattr(wz, "wizard_write", MagicMock()) + monkeypatch.setattr(wz, "wizard_write", MagicMock()) # When retval = wz.wizard(str(config_file))