diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000..c56ce094a --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,25 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/ambv/black + rev: 20.8b1 + hooks: + - id: black + args: + - --safe + - --quiet + - repo: https://gitlab.com/pycqa/flake8 + rev: 3.8.4 + hooks: + - id: flake8 + additional_dependencies: + - flake8-docstrings==1.5.0 + - pydocstyle==5.1.1 + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.4.0 + hooks: + - id: no-commit-to-branch + args: + - --branch=current + - --branch=next + - --branch=beta diff --git a/Doxygen b/Doxygen index 6834e821f..36c0c07d6 100644 --- a/Doxygen +++ b/Doxygen @@ -38,7 +38,7 @@ PROJECT_NAME = "ESPHome" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.16.2 +PROJECT_NUMBER = 1.17.0b1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/Makefile b/Makefile index 1a15daf6c..e3ce13443 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ ESPHOME_PATH = ../esphome -ESPHOME_REF = v1.16.2 +ESPHOME_REF = v1.17.0b1 .PHONY: html html-strict cleanhtml deploy help webserver Makefile netlify netlify-api api netlify-dependencies svg2png copy-svg2png diff --git a/_static/version b/_static/version index f21c0ae0b..c4c22c58f 100644 --- a/_static/version +++ b/_static/version @@ -1 +1 @@ -1.16.2 \ No newline at end of file +1.17.0b1 \ No newline at end of file diff --git a/changelog/index.rst b/changelog/index.rst index 58680e625..8dd643894 100644 --- a/changelog/index.rst +++ b/changelog/index.rst @@ -2,7 +2,7 @@ Changelog ========= .. redirect:: - :url: /changelog/v1.16.0.html + :url: /changelog/v1.17.0.html .. toctree:: :glob: diff --git a/changelog/v1.14.0.rst b/changelog/v1.14.0.rst index 23d48bb4c..fc5ed3df0 100644 --- a/changelog/v1.14.0.rst +++ b/changelog/v1.14.0.rst @@ -29,7 +29,7 @@ Changelog - Version 1.14.0 - November 1 SGP30, components/sensor/sgp30, sgp30.jpg Tx20, components/sensor/tx20, tx20.jpg - VL53L0x, components/sensor/vl53l0x, vl53l0x.svg + VL53L0x, components/sensor/vl53l0x, vl53l0x.png Xiaomi CGG1, components/sensor/xiaomi_cgg1, xiaomi_cgg1.jpg Xiaomi LYWSD02, components/sensor/xiaomi_lywsd02, xiaomi_lywsd02.jpg ZyAura, components/sensor/zyaura, zgm053.jpg diff --git a/changelog/v1.17.0.rst b/changelog/v1.17.0.rst new file mode 100644 index 000000000..68f009bed --- /dev/null +++ b/changelog/v1.17.0.rst @@ -0,0 +1,176 @@ +Changelog - Version 1.17.0 - TBD 2021 +=============================================== + +.. seo:: + :description: Changelog for ESPHome version 1.17.0. + :image: /_static/changelog-1.17.0.png + :author_twitter: @esphome_ + +.. imgtable:: + :columns: 4 + + Inkbird IBS-TH1 Mini, components/sensor/inkbird_ibsth1_mini, inkbird_isbth1_mini.jpg + MCP4725, components/output/mcp4725, mcp4725.jpg + Xiaomi Miscale, components/sensor/xiaomi_miscale, xiaomi_miscale.jpg + Xiaomi Miscale2, components/sensor/xiaomi_miscale2, xiaomi_miscale2.jpg + Midea Air Conditioner, components/climate/midea_ac, midea.svg + Addressable Light Display, components/display/addressable_light, addressable_light.jpg + Pulse Meter, components/sensor/pulse_meter, pulse.svg + +RELEASE NOTES TO GO HERE + +New Features +------------ + +- esphome: Vl53l0x change address :esphomepr:`1126` by :ghuser:`kkellner` (new-feature) +- esphome: Background calibration & ABC commands for SenseAir S8 :esphomepr:`1623` by :ghuser:`nmaggioni` (new-feature) +- esphome: Add trigger for http actions to receive the status code :esphomepr:`1599` by :ghuser:`jesserockz` (new-feature) + +New Integrations +---------------- + +- esphome: Adding support for the Inkbird IBS-TH1 Mini sensor :esphomepr:`1099` by :ghuser:`fkirill` (new-integration) +- esphome: Add MCP4725 DAC Component :esphomepr:`1418` by :ghuser:`JJK801` (new-integration) +- esphome: Add Xiaomi Miscale v1 and v2 :esphomepr:`1368` by :ghuser:`dckiller51` (new-integration) +- esphome: Add support for the SM300D2 7-in-1 sensor module :esphomepr:`1524` by :ghuser:`moritzgloeckl` (new-integration) +- esphome: Midea climate support :esphomepr:`1328` by :ghuser:`dudanov` (new-integration) +- esphome: Add addressable_light display platform :esphomepr:`1272` by :ghuser:`justfalter` (new-integration) (notable-change) +- esphome: Implement pulse_meter as an improvement on pulse_counter and pulse_width for meters :esphomepr:`1434` by :ghuser:`stevebaxter` (new-integration) + +Breaking Changes +---------------- + +- esphome: MCP23XXX Refactor :esphomepr:`1560` by :ghuser:`jesserockz` (breaking-change) + +Notable Changes +--------------- + +- esphome: Device class attribute for sensor component :esphomepr:`1525` by :ghuser:`marecabo` (notable-change) +- esphome: Add default device classes to sensor components :esphomepr:`1533` by :ghuser:`marecabo` (notable-change) +- esphome: Add addressable_light display platform :esphomepr:`1272` by :ghuser:`justfalter` (new-integration) (notable-change) + +All changes +----------- + +- esphome: Bump voluptuous from 0.12.0 to 0.12.1 :esphomepr:`1411` by :ghuser:`dependabot[bot]` +- esphome: add http request tests :esphomepr:`1448` by :ghuser:`glmnet` +- esphome: codegen: Lambda improvements :esphomepr:`1476` by :ghuser:`balrog-kun` +- docs: Add options to control pulse duration on Climate_IR_LG Component :docspr:`963` by :ghuser:`mhentschke` +- esphome: Add options to control pulse duration on Climate_IR_LG Component :esphomepr:`1470` by :ghuser:`mhentschke` +- esphome: Adding support for the Inkbird IBS-TH1 Mini sensor :esphomepr:`1099` by :ghuser:`fkirill` (new-integration) +- docs: Adding documentation for Inkbird IBS-TH1 Mini sensor :docspr:`657` by :ghuser:`fkirill` +- esphome: Add config validator location :esphomepr:`1490` by :ghuser:`glmnet` +- esphome: Add MCP4725 DAC Component :esphomepr:`1418` by :ghuser:`JJK801` (new-integration) +- docs: Add MCP4725 docs :docspr:`889` by :ghuser:`JJK801` +- docs: Fix format consistency :docspr:`989` by :ghuser:`glmnet` +- esphome: Added codeowners to max7219digit :esphomepr:`1487` by :ghuser:`rspaargaren` +- esphome: Correct Native API Wire Format Documentation :esphomepr:`1528` by :ghuser:`justin-gerhardt` +- esphome: st7735_conf_fixes :esphomepr:`1530` by :ghuser:`SenexCrenshaw` +- docs: ST7735 Changed configuration items to snake_case :docspr:`1000` by :ghuser:`SenexCrenshaw` +- esphome: Device class attribute for sensor component :esphomepr:`1525` by :ghuser:`marecabo` (notable-change) +- docs: Add doc for device_class attribute of sensor :docspr:`996` by :ghuser:`marecabo` +- docs: Add sleep duration to enter deep sleep action :docspr:`995` by :ghuser:`nuttytree` +- esphome: Add duration option to action start deep sleep :esphomepr:`1526` by :ghuser:`nuttytree` +- esphome: fix substitution losing track of document range :esphomepr:`1547` by :ghuser:`glmnet` +- docs: Update esp32_camera.rst :docspr:`1020` by :ghuser:`lukaszrud` +- docs: Fix format next :docspr:`1023` by :ghuser:`glmnet` +- docs: Add another project to diy.rst :docspr:`1019` by :ghuser:`shish` +- docs: Update esphome-configs URL :docspr:`1018` by :ghuser:`shish` +- docs: Icon is ignored by HA when device class is set :docspr:`1011` by :ghuser:`marecabo` +- docs: Update pid.rst :docspr:`1006` by :ghuser:`boradwell` +- docs: Mention that Hyperion.NG works with E1.31 :docspr:`975` by :ghuser:`rradar` +- esphome: Add Xiaomi Miscale v1 and v2 :esphomepr:`1368` by :ghuser:`dckiller51` (new-integration) +- docs: Add docs for Xiaomi Miscale v1 and v2 :docspr:`1021` by :ghuser:`dckiller51` +- docs: Add missing closing parenthesis in example :docspr:`1029` by :ghuser:`lepinkainen` +- docs: Update Inkplate.rst :docspr:`1026` by :ghuser:`jakommo` +- docs: typo in st7735 model number :docspr:`1025` by :ghuser:`wjcarpenter` +- docs: Fix mcp23sXX id config :docspr:`1017` by :ghuser:`jesserockz` +- docs: Update bme680.rst :docspr:`1007` by :ghuser:`wifwucite` +- docs: Sim800l dial :docspr:`1027` by :ghuser:`spilin` +- esphome: Add dial support for sim800l component :esphomepr:`1558` by :ghuser:`spilin` +- esphome: Climate IR LG -keep previous temp and fan if swing :esphomepr:`1556` by :ghuser:`Otamay` +- esphome: Vl53l0x change address :esphomepr:`1126` by :ghuser:`kkellner` (new-feature) +- docs: Update vl53l0x docs :docspr:`679` by :ghuser:`kkellner` +- esphome: tuya: Use queue for sending command messages :esphomepr:`1404` by :ghuser:`stubs12` +- esphome: Replace substitutions in substitutions first :esphomepr:`1567` by :ghuser:`edenhaus` +- esphome: Added heater to climate_ir_lg :esphomepr:`1555` by :ghuser:`Otamay` +- esphome: More yaml validation :esphomepr:`1568` by :ghuser:`glmnet` +- esphome: Add default device classes to sensor components :esphomepr:`1533` by :ghuser:`marecabo` (notable-change) +- docs: Document recurring data in uart switch :docspr:`986` by :ghuser:`gabe565` +- esphome: Add support for recurring data in uart switch :esphomepr:`1514` by :ghuser:`gabe565` +- esphome: Added samsung36 ir protocol :esphomepr:`1438` by :ghuser:`tuxBurner` +- docs: Added remote samsung36 protocol docs :docspr:`904` by :ghuser:`tuxBurner` +- docs: Add IWOOLE Table Lamp cookbook entry :docspr:`947` by :ghuser:`Deinara` +- docs: Update uart.rst example to read all available characters :docspr:`1031` by :ghuser:`RoganDawes` +- esphome: ADC fix: GPIO0 not usable as output if ADC_VCC is used :esphomepr:`1557` by :ghuser:`ferbar` +- esphome: Add constants for device classes of binary_sensor :esphomepr:`1549` by :ghuser:`marecabo` +- esphome: fix path on windows escape :esphomepr:`1573` by :ghuser:`glmnet` +- esphome: Migrate ESPColor to Color :esphomepr:`1551` by :ghuser:`SenexCrenshaw` +- docs: Migrate ESPColor to Color :docspr:`1036` by :ghuser:`SenexCrenshaw` +- esphome: Add support for the SM300D2 7-in-1 sensor module :esphomepr:`1524` by :ghuser:`moritzgloeckl` (new-integration) +- docs: Added documentation for the SM300D2 sensor :docspr:`993` by :ghuser:`moritzgloeckl` +- esphome: changed color temp from float to int :esphomepr:`1522` by :ghuser:`codyjamestechnical` +- esphome: Bump pytest-cov from 2.10.1 to 2.11.1 :esphomepr:`1483` by :ghuser:`dependabot[bot]` +- esphome: Bump colorlog from 4.6.2 to 4.7.2 :esphomepr:`1473` by :ghuser:`dependabot[bot]` +- esphome: pins: Add three new boards :esphomepr:`1576` by :ghuser:`balrog-kun` +- esphome: Bump pytest from 6.2.1 to 6.2.2 :esphomepr:`1574` by :ghuser:`dependabot[bot]` +- esphome: Bump pytz from 2020.5 to 2021.1 :esphomepr:`1575` by :ghuser:`dependabot[bot]` +- esphome: Fix for waveshare 2.13in-ttgo-b73 :esphomepr:`1543` by :ghuser:`nikito7` +- docs: Added new blogpost :docspr:`1038` by :ghuser:`pieterbrink123` +- esphome: Add min/max filters :esphomepr:`1569` by :ghuser:`gabe565` +- docs: Document new min/max filters :docspr:`1032` by :ghuser:`gabe565` +- esphome: Bump pylint from 2.6.0 to 2.7.2 :esphomepr:`1582` by :ghuser:`dependabot[bot]` +- esphome: Extend 'uart:' with 'invert:' for esp32 :esphomepr:`1586` by :ghuser:`needspeed` +- docs: Uart invert option for ESP32 :docspr:`1039` by :ghuser:`Mynasru` +- esphome: Bump platformio from 5.0.4 to 5.1.0 :esphomepr:`1581` by :ghuser:`dependabot[bot]` +- esphome: fix servo warning :esphomepr:`1591` by :ghuser:`glmnet` +- docs: add-black :docspr:`1044` by :ghuser:`glmnet` +- esphome: add-black :esphomepr:`1593` by :ghuser:`glmnet` +- esphome: MCP23XXX Refactor :esphomepr:`1560` by :ghuser:`jesserockz` (breaking-change) +- docs: Update MCP23XXX docs with interrupts and pin schemas :docspr:`1028` by :ghuser:`jesserockz` +- esphome: Improve error checking: too many component id candidates :esphomepr:`1570` by :ghuser:`glmnet` +- esphome: Schema dump :esphomepr:`1564` by :ghuser:`glmnet` +- docs: Dump schema :docspr:`1030` by :ghuser:`glmnet` +- docs: Update i2c.rst :docspr:`1043` by :ghuser:`webeling67` +- docs: Update rf_bridge.rst :docspr:`1042` by :ghuser:`samnewman86` +- esphome: Inkplate 6 Optimizations :esphomepr:`1592` by :ghuser:`Sizurka` +- docs: Fix RF Bridge link to Portisch Repo :docspr:`1045` by :ghuser:`jesserockz` +- docs: pin schema and other fixes :docspr:`1047` by :ghuser:`glmnet` +- esphome: schema-dump-pins :esphomepr:`1596` by :ghuser:`glmnet` +- docs: Adding that mpr121_id is a valid option for binary_sensor :docspr:`966` by :ghuser:`minideezel` +- esphome: change lcd clear() to clear the buffer :esphomepr:`1600` by :ghuser:`ssieb` +- esphome: PN532 - don't read extra page and fix size :esphomepr:`1565` by :ghuser:`ssieb` +- docs: schema-filters :docspr:`1052` by :ghuser:`glmnet` +- esphome: Fix component_tests config :esphomepr:`1608` by :ghuser:`madron` +- esphome: Added receive for Fujitsu ACs :esphomepr:`1577` by :ghuser:`alex-richards` +- esphome: Change COLOR_ON to be 255 values instead of 1 :esphomepr:`1594` by :ghuser:`jesserockz` +- esphome: a4988 wait 1ms when coming out of sleep :esphomepr:`1597` by :ghuser:`WeekendWarrior1` +- docs: Remove cs_pin from rc522 i2c example :docspr:`1059` by :ghuser:`jesserockz` +- esphome: Support fan speed levels :esphomepr:`1541` by :ghuser:`blejdfist` +- docs: Documentation for fan speed levels :docspr:`1056` by :ghuser:`blejdfist` +- docs: Add CLI logs section :docspr:`1060` by :ghuser:`Tmin10` +- esphome: Add option to suffix name with mac address :esphomepr:`1615` by :ghuser:`jesserockz` +- esphome: Midea climate support :esphomepr:`1328` by :ghuser:`dudanov` (new-integration) +- docs: Midea Climate support :docspr:`804` by :ghuser:`dudanov` +- docs: Add docs for `name_add_mac_suffix` config :docspr:`1058` by :ghuser:`jesserockz` +- esphome: SPI transfer fix. Use write when no miso pin is set :esphomepr:`1563` by :ghuser:`SenexCrenshaw` +- esphome: SPI Improvements :esphomepr:`1617` by :ghuser:`SenexCrenshaw` +- esphome: Add addressable_light display platform :esphomepr:`1272` by :ghuser:`justfalter` (new-integration) (notable-change) +- docs: Add docs for addressable_light display :docspr:`755` by :ghuser:`justfalter` +- esphome: Implement pulse_meter as an improvement on pulse_counter and pulse_width for meters :esphomepr:`1434` by :ghuser:`stevebaxter` (new-integration) +- esphome: e131: fix issue 1579: limitation of maximum light count :esphomepr:`1619` by :ghuser:`docteurzoidberg` +- docs: Add documentation for pulse_meter :docspr:`900` by :ghuser:`stevebaxter` +- esphome: Bump platformio from 5.1.0 to 5.1.1 :esphomepr:`1618` by :ghuser:`dependabot[bot]` +- esphome: Fix pulse-meter with device_class and black :esphomepr:`1621` by :ghuser:`jesserockz` +- esphome: Declare Color objects in main.cpp :esphomepr:`1395` by :ghuser:`kbx81` +- esphome: Add 2.13in-ttgo-b1 waveshare epaper module. :esphomepr:`1326` by :ghuser:`matikij` +- docs: Add docs for ttgo-b1 version (next branch) :docspr:`808` by :ghuser:`matikij` +- esphome: Bump flake8 from 3.8.4 to 3.9.0 :esphomepr:`1612` by :ghuser:`dependabot[bot]` +- esphome: Bundle platformio lib_deps in docker images :esphomepr:`1625` +- esphome: Bump protobuf from 3.13.0 to 3.15.6 :esphomepr:`1607` by :ghuser:`dependabot[bot]` +- esphome: Bump pyyaml from 5.3.1 to 5.4.1 :esphomepr:`1482` by :ghuser:`dependabot[bot]` +- esphome: Switch docker images to debian :esphomepr:`1626` +- esphome: Background calibration & ABC commands for SenseAir S8 :esphomepr:`1623` by :ghuser:`nmaggioni` (new-feature) +- docs: SenseAir: background calibration & ABC commands :docspr:`1066` by :ghuser:`nmaggioni` +- esphome: Add trigger for http actions to receive the status code :esphomepr:`1599` by :ghuser:`jesserockz` (new-feature) +- docs: Add docs for http_request on_response trigger :docspr:`1049` by :ghuser:`jesserockz` diff --git a/components/binary_sensor/ble_presence.rst b/components/binary_sensor/ble_presence.rst index 3a0d6d9ce..d19e05b33 100644 --- a/components/binary_sensor/ble_presence.rst +++ b/components/binary_sensor/ble_presence.rst @@ -40,7 +40,7 @@ Configuration variables: - **name** (**Required**, string): The name of the binary sensor. - **mac_address** (*Optional*, MAC Address): The MAC address to track for this binary sensor. Either this or ``service_uuid`` has to be present. -- **service_uuid** (*Optional*, string) 16 bit, 32 bit, or 128 bit BLE Service UUID +- **service_uuid** (*Optional*, string): 16 bit, 32 bit, or 128 bit BLE Service UUID which can be tracked if the device randomizes the MAC address. Either this or ``mac_address`` has to be present. - **id** (*Optional*, :ref:`config-id`): Manually specify diff --git a/components/binary_sensor/index.rst b/components/binary_sensor/index.rst index 4683ad514..f0d99c21c 100644 --- a/components/binary_sensor/index.rst +++ b/components/binary_sensor/index.rst @@ -85,23 +85,40 @@ of these entries matters!) return {}; } -Supported filters: +``invert`` +********** -- **invert**: Simple filter that just inverts every value from the binary sensor. -- **delayed_on**: When a signal ON is received, wait for the specified time period until publishing - an ON state. If an OFF value is received while waiting, the ON action is discarded. Or in other words: - Only send an ON value if the binary sensor has stayed ON for at least the specified time period. - **Useful for debouncing push buttons**. -- **delayed_off**: When a signal OFF is received, wait for the specified time period until publishing - an OFF state. If an ON value is received while waiting, the OFF action is discarded. Or in other words: - Only send an OFF value if the binary sensor has stayed OFF for at least the specified time period. - **Useful for debouncing push buttons**. -- **delayed_on_off**: Only send an ON or OFF value if the binary sensor has stayed in the same state - for at least the specified time period. - **Useful for debouncing binary switches**. -- **lambda**: Specify any :ref:`lambda ` for more complex filters. The input value from - the binary sensor is ``x`` and you can return ``true`` for ON, ``false`` for OFF, and ``{}`` to stop - the filter chain. +Simple filter that just inverts every value from the binary sensor. + +``delayed_on`` +************** + +(**Required**, :ref:`config-time`): When a signal ON is received, wait for the specified time period until publishing +an ON state. If an OFF value is received while waiting, the ON action is discarded. Or in other words: +Only send an ON value if the binary sensor has stayed ON for at least the specified time period. +**Useful for debouncing push buttons**. + +``delayed_off`` +*************** + +(**Required**, :ref:`config-time`): When a signal OFF is received, wait for the specified time period until publishing +an OFF state. If an ON value is received while waiting, the OFF action is discarded. Or in other words: +Only send an OFF value if the binary sensor has stayed OFF for at least the specified time period. +**Useful for debouncing push buttons**. + +``delayed_on_off`` +****************** + +(**Required**, :ref:`config-time`): Only send an ON or OFF value if the binary sensor has stayed in the same state +for at least the specified time period. +**Useful for debouncing binary switches**. + +``lambda`` +********** + +Specify any :ref:`lambda ` for more complex filters. The input value from +the binary sensor is ``x`` and you can return ``true`` for ON, ``false`` for OFF, and ``{}`` to stop +the filter chain. Binary Sensor Automation ------------------------ diff --git a/components/binary_sensor/mpr121.rst b/components/binary_sensor/mpr121.rst index cfc37b839..d815d43ad 100644 --- a/components/binary_sensor/mpr121.rst +++ b/components/binary_sensor/mpr121.rst @@ -6,6 +6,11 @@ MPR121 Capacitive Touch Sensor :image: mpr121.jpg :keywords: MPR121 +.. _mpr121-component: + +Component/Hub +------------- + The ``mpr121`` sensor platform allows you to use your MPR121 (`datasheet `__, `Adafruit`_) Capacitive Touch Sensor with ESPHome. The :ref:`I²C ` is @@ -43,8 +48,6 @@ Configuration variables: The configuration is made up of two parts: The central component, and individual Binary sensors per channel. -Base Configuration: - - **address** (*Optional*, integer): The I²C address of the sensor. Defaults to ``0x5A``. - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor. - **touch_debounce** (*Optional*, integer): The minimum length before a touch is recognized. Range is from 0 to 7. @@ -55,12 +58,21 @@ Base Configuration: and should be between 5 and 30 (lower = more sensitive). Defaults to 12. Typically the touch threshold is a little bigger than the release threshold. - **release_threshold** (*Optional*, integer): The release defines the sensitivity for touch detection and should be between 5 and 30. Defaults to 6. -Binary Sensor Configuration: +Binary Sensor +------------- -- **name** (**Optional**, string): The name for the binary sensor. +The ``mpr121`` binary sensor allows you to use your MPR121 with ESPHome. +First, setup a :ref:`mpr121-component` and then use this binary sensor platform to create individual +binary sensors for each touch sensor. + + +Configuration variables: + + +- **name** (*Optional*, string): The name for the binary sensor. - **mpr121_id** (*Optional*, :ref:`config-id`): The ID of the MPR121 defined above. Useful for multiple MPR121's on the I²C bus - **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation. -- **channel** (*Required*, integer): The channel number at the MPR121 the touchkey is connected to. +- **channel** (**Required**, integer): The channel number at the MPR121 the touchkey is connected to. - **touch_threshold** (*Optional*, integer): A per-channel override of the global touch_threshold value. If not specified, uses the global value. - **release_threshold** (*Optional*, integer): A per-channel override of the global release_threshold value. If not specified, uses the global value. - All other options from :ref:`Binary Sensor `. diff --git a/components/binary_sensor/pn532.rst b/components/binary_sensor/pn532.rst index bab9ca903..ce1d5fad2 100644 --- a/components/binary_sensor/pn532.rst +++ b/components/binary_sensor/pn532.rst @@ -28,14 +28,62 @@ You will need to switch the dip switches located on the module according to the SPI is usually switch 1 OFF and switch 2 ON and I²C is usually switch 1 ON and switch 2 OFF. You will need to have the :ref:`SPI Bus ` or the :ref:`I²C Bus ` configured depending on your choice. +Over SPI +-------- + +The ``pn532_spi`` component allows you to use PN532 NFC/RFID controllers +(`datasheet `__, `Adafruit `__) +with ESPHome. This component is a global hub that establishes the connection to the PN532 via :ref:`SPI ` and +outputs its data. Using the :ref:`PN532 binary sensors ` you can then +create individual binary sensors that track if an NFC/RFID tag is currently detected by the PN532. + .. code-block:: yaml - # Example configuration for SPI (choose which one!) pn532_spi: cs_pin: D3 update_interval: 1s - # Example configuration for I²C (choose which one!) + + binary_sensor: + - platform: pn532 + uid: 74-10-37-94 + name: "PN532 NFC Tag" + +Configuration variables: +************************ + +- **cs_pin** (**Required**, :ref:`Pin Schema `): The pin on the ESP that the chip select line + is connected to. +- **update_interval** (*Optional*, :ref:`config-time`): The duration of each scan on the PN532. This affects the + duration that the individual binary sensors stay active when they're found. + If a device is not found within this time window, it will be marked as not present. Defaults to 1s. +- **on_tag** (*Optional*, :ref:`Automation `): An automation to perform + when a tag is read. See :ref:`pn532-on_tag`. +- **spi_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the :ref:`SPI Component ` if you want + to use multiple SPI buses. +- **id** (*Optional*, :ref:`config-id`): Manually specify the ID for this component. + +.. figure:: images/pn532-spi.jpg + :align: center + :width: 80.0% + + Example for hooking up the PN532 via SPI. Notice the position of the two switches on the right. + +.. _pn532-on_tag: + + +Over I²C +-------- + +The ``pn532`` component allows you to use PN532 NFC/RFID controllers +(`datasheet `__, `Adafruit `__) +with ESPHome. This component is a global hub that establishes the connection to the PN532 via :ref:`I²C ` and +outputs its data. Using the :ref:`PN532 binary sensors ` you can then +create individual binary sensors that track if an NFC/RFID tag is currently detected by the PN532. + + +.. code-block:: yaml + pn532_i2c: update_interval: 1s @@ -47,29 +95,18 @@ You will need to have the :ref:`SPI Bus ` or the :ref:`I²C Bus ` conf Configuration variables: ************************ -- **cs_pin** (**Required for SPI**, :ref:`Pin Schema `): The pin on the ESP that the chip select line - is connected to. - **update_interval** (*Optional*, :ref:`config-time`): The duration of each scan on the PN532. This affects the duration that the individual binary sensors stay active when they're found. If a device is not found within this time window, it will be marked as not present. Defaults to 1s. - **on_tag** (*Optional*, :ref:`Automation `): An automation to perform when a tag is read. See :ref:`pn532-on_tag`. -- **spi_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the :ref:`SPI Component ` if you want - to use multiple SPI buses. - **i2c_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the :ref:`I²C Component ` if you want to use multiple I²C buses. - **id** (*Optional*, :ref:`config-id`): Manually specify the ID for this component. -.. figure:: images/pn532-spi.jpg - :align: center - :width: 80.0% - Example for hooking up the PN532 via SPI. Notice the position of the two switches on the right. - -.. _pn532-on_tag: - -``on_tag`` ----------- +``on_tag`` Action +----------------- This automation will be triggered when the PN532 module responds with a tag. This will only be triggered if the tag is changed or goes away for one cycle of ``update_interval``. @@ -120,8 +157,8 @@ Alternatively you could also send the value directly to Home Assistant via a .. _pn532-tag: -NFC/RFID Tag ------------- +``pn532`` Binary Sensor +----------------------- The ``pn532`` binary sensor platform lets you track if an NFC/RFID tag with a given unique id (``uid``) is currently being detected by the PN532 or not. diff --git a/components/binary_sensor/rc522.rst b/components/binary_sensor/rc522.rst index 4f05192b5..bcf3e9ad4 100644 --- a/components/binary_sensor/rc522.rst +++ b/components/binary_sensor/rc522.rst @@ -8,30 +8,32 @@ RC522 RFID .. _rc522-component: -Component/Hub -------------- - The ``rc522`` component allows you to use RC522 RFID controllers (`datasheet `__, `Ali Express `__) -with ESPHome. This component is a global hub that establishes the connection to the RC522 via either :ref:`SPI ` or -:ref:`I²C ` and outputs its data. Using the :ref:`RC522 binary sensors ` you can then -create individual binary sensors that track if an RFID tag is currently detected by the RC522. - -.. figure:: images/rc522-full.jpg - :align: center - :width: 60.0% - +with ESPHome. ESPHome can read the tag UID from it, every RFID tag comes with a unique +UID value. Each known tag can be associated to a binary sensor, or you can use the tag information directly. See :ref:`rc522-setting_up_tags` for information on how to setup individual binary sensors for this component. - The RC522 supports SPI, I²C and UART communication protocols, ESPHome can use either SPI or I²C. +Component/Hub +------------- + * If you have a module like the image above, it can only be used in SPI mode (`unless hacked `__) and you need to have an :ref:`SPI bus ` in your configuration with both the **miso_pin** and **mosi_pin** set. * If you have a RC522 which communicates via I²C like in the M5 Stack then you need to have an :ref:`I²C ` bus configured. -SPI Option -********** +.. figure:: images/rc522-full.jpg + :align: center + :width: 60.0% + +Over SPI +-------- + +The ``rc522_spi`` component allows you to use RC522 RFID controllers with ESPHome. This component is a global hub that +establishes the connection to the RC522 via :ref:`SPI ` (also avilable over I²C). Using the +:ref:`RC522 binary sensors ` you can then create individual binary sensors that track if +an RFID tag is currently detected by the RC522. .. code-block:: yaml @@ -45,8 +47,29 @@ SPI Option uid: 74-10-37-94 name: "RC522 RFID Tag" -I²C Option -********** +Configuration variables: +************************ + +- **cs_pin** (**Required**, :ref:`Pin Schema `): The pin on the ESP that the chip select line + is connected to. +- **spi_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the :ref:`SPI Component ` if you want + to use multiple SPI buses. +- **on_tag** (*Optional*, :ref:`Automation `): An automation to perform when a tag is read. See + :ref:`rc522-on_tag`. +- **reset_pin** (*Optional*, :ref:`Pin Schema `): The pin connected to the RST line. Some tests + shows the RC522 working okay without this. +- **update_interval** (*Optional*, :ref:`config-time`): The duration of each scan on the RC522. This affects the + duration that the individual binary sensors stay active when they're found. + If a device is not found within this time window, it will be marked as not present. Defaults to ``1s``. +- **id** (*Optional*, :ref:`config-id`): Manually specify the ID for this component. + +Over I²C +-------- + +The ``rc522_i2c`` component allows you to use RC522 RFID controllers with ESPHome. This component is a global hub that +establishes the connection to the RC522 via :ref:`I²C ` (also avilable over SPI). Using the +:ref:`RC522 binary sensors ` you can then create individual binary sensors that track if +an RFID tag is currently detected by the RC522. .. code-block:: yaml @@ -62,36 +85,24 @@ I²C Option Configuration variables: ************************ +- **address** (*Optional*, int): Manually specify the I²C address of the sensor. Defaults to ``0x28``. +- **i2c_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the :ref:`I²C Component ` if you want + to use multiple I²C buses. +- **on_tag** (*Optional*, :ref:`Automation `): An automation to perform when a tag is read. See + :ref:`rc522-on_tag`. - **reset_pin** (*Optional*, :ref:`Pin Schema `): The pin connected to the RST line. Some tests shows the RC522 working okay without this. - **update_interval** (*Optional*, :ref:`config-time`): The duration of each scan on the RC522. This affects the duration that the individual binary sensors stay active when they're found. If a device is not found within this time window, it will be marked as not present. Defaults to ``1s``. -- **on_tag** (*Optional*, :ref:`Automation `): An automation to perform when a tag is read. See - :ref:`rc522-on_tag`. - **id** (*Optional*, :ref:`config-id`): Manually specify the ID for this component. -SPI Only: -^^^^^^^^^ - -- **cs_pin** (**Required**, :ref:`Pin Schema `): The pin on the ESP that the chip select line - is connected to. -- **spi_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the :ref:`SPI Component ` if you want - to use multiple SPI buses. - - -I²C Only: -^^^^^^^^^ - -- **address** (*Optional*, int): Manually specify the I²C address of the sensor. Defaults to ``0x2C``. -- **i2c_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the :ref:`I²C Component ` if you want - to use multiple I²C buses. .. _rc522-on_tag: -``on_tag`` ----------- +``on_tag`` Action +----------------- This automation will be triggered when the RC522 module responds with a tag. Please note that this can be called quite often (with an interval of ``update_interval``) as it's triggered repeatedly @@ -123,8 +134,8 @@ using :ref:`api-homeassistant_tag_scanned_action`. .. _rc522-tag: -RFID Tag --------- +``rc522`` Binary Sensor +----------------------- The ``rc522`` binary sensor platform lets you track if an RFID tag with a given unique id (``uid``) is currently being detected by the RC522 or not. diff --git a/components/binary_sensor/rdm6300.rst b/components/binary_sensor/rdm6300.rst index 2f44bb06d..0026ad3c7 100644 --- a/components/binary_sensor/rdm6300.rst +++ b/components/binary_sensor/rdm6300.rst @@ -83,8 +83,8 @@ using :ref:`api-homeassistant_tag_scanned_action`. .. _rdm6300-tag: -NFC/RFID Tag ------------- +``rdm6300`` Binary Sensor +------------------------- The ``rdm6300`` binary sensor platform lets you track if an NFC/RFID tag with a given unique id (``uid``) is currently being detected by the RDM6300 or not. diff --git a/components/binary_sensor/ttp229.rst b/components/binary_sensor/ttp229.rst index a2f52aa83..4baadf53e 100644 --- a/components/binary_sensor/ttp229.rst +++ b/components/binary_sensor/ttp229.rst @@ -22,8 +22,8 @@ There are two types of this sensor: .. _RobotDyn: https://www.tinytronics.nl/shop/nl/sensoren/touch/robotdyn-touch-module-ttp229-lsf-16-kanaals -``ttp229_lsf`` Type -------------------- +``ttp229_lsf`` Component +------------------------ .. code-block:: yaml @@ -40,19 +40,20 @@ Configuration variables: The configuration is made up of two parts: The central component, and individual Binary sensors per channel. -Base Configuration: - - **id** (*Optional*, :ref:`config-id`): Manually set the ID of this sensor. -Binary Sensor Configuration: +``ttp229_lsf`` Binary Sensor +---------------------------- + +Configuration variables: - **name** (**Required**, string): The name of the binary sensor. - **channel** (**Required**, integer): The channel number at the TTP229 the touchkey is connected to. - **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation. - All other options from :ref:`Binary Sensor `. -``ttp229_bsf`` Type -------------------- +``ttp229_bsf`` Component +------------------------ .. code-block:: yaml @@ -79,7 +80,10 @@ Base Configuration: SCL pin is connected to. - **id** (*Optional*, :ref:`config-id`): Manually set the ID of this component. -Binary Sensor Configuration: +``ttp229_bsf`` Binary Sensor +---------------------------- + +Configuration variables: - **name** (**Required**, string): The name of the binary sensor. - **channel** (**Required**, integer): The channel number at the TTP229 the touchkey is connected to. diff --git a/components/canbus.rst b/components/canbus.rst index 641c63722..86ac347dd 100644 --- a/components/canbus.rst +++ b/components/canbus.rst @@ -56,9 +56,9 @@ Configuration variables: - **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation. - **can_id** (**Required**, integer): default *can id* used for transmitting frames. -- **use_extended_id** (*Optional*, boolean): default *False* identifies the type of *can_id*: +- **use_extended_id** (*Optional*, boolean): default *False* identifies the type of *can_id*: *False*: Standard 11 bits IDs, *True*: Extended 29 bits ID -- **bit_rate** (*Optional*, one of the supported bitrates= defaults to ``125KBPS``. +- **bit_rate** (*Optional*, enum): One of the supported bitrates. Defaults to ``125KBPS``. - 5KBPS - 10KBPS @@ -80,7 +80,7 @@ Configuration variables: Automations: - **on_frame** (*Optional*, :ref:`Automation `): An automation to perform when ability - CAN Frame is received. See below. + CAN Frame is received. See :ref:`canbus-on-frame`. .. _canbus-on-frame: @@ -107,8 +107,8 @@ This automation will be triggered when a can frame is received. A variable ``x` then: light.toggle: light1 -Transmit Frame Action -********************* +``canbus.send`` Action +********************** The can bus can transmit frames by means of the ``canbus.send`` action. There are several forms to use it: @@ -132,23 +132,26 @@ There are several forms to use it: Configuration variables: -- **data** (*Required*, binary data): Data to transmit, up to 8 bytes or +- **data** (**Required**, binary data): Data to transmit, up to 8 bytes or characters are supported by can bus per frame. - **canbus_id** (*Optional*): Optionally set the can bus id to use for transmitting the frame. Not needed if you are using only 1 can bus. - **can_id** (*Optional*, int): Allows to override the can id configured in the can bus device. -- **use_extended_id** (*Optional*, boolean): default *False* identifies the type of *can_id*: +- **use_extended_id** (*Optional*, boolean): default *False* identifies the type of *can_id*: *False*: Standard 11 Bit IDs, *True*: Extended 29Bit ID -MCP2515 -------- +MCP2515 Component +----------------- The MCP2515 is a spi device and therfore you must first add the configuration for the spi bus to your file. You need to have an :ref:`SPI bus ` in your configuration with both the **mosi_pin** and **miso_pin** set. For wireing up the MSP2515 please refer to the section below. +Configuration variables: +************************ + - **cs_pin** (**Required**, :ref:`Pin Schema `): Is used to tell the receiving SPI device when it should listen for data on the SPI bus. Each device has an individual ``CS`` line. Sometimes also called ``SS``. @@ -217,7 +220,7 @@ Standard IDs and Extended IDs can coexist on the same segment. - seconds: /1 then: - canbus.send: - # Extended ID explicit + # Extended ID explicit use_extended_id: True can_id: 0x100 data: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08] @@ -290,11 +293,11 @@ Buttons are connected on the CAN-Node and also the motor is connected via CAN. .. epigraph:: - | **Button 1:** ID 0x50B - 1 byte payload + | **Button 1:** ID 0x50B - 1 byte payload | (0: Button release, 1: Button down, 2: long down, 3: long release, 4 double click) - | **Button 2:** ID 0x50C - 1 byte payload + | **Button 2:** ID 0x50C - 1 byte payload | (0: Button release, 1: Button down, 2: long down, 3: long release, 4 double click) - | **Motor:** ID 0x51A - 1 byte payload + | **Motor:** ID 0x51A - 1 byte payload | (0: off, 1: open, 2: close) .. code-block:: yaml diff --git a/components/climate/bang_bang.rst b/components/climate/bang_bang.rst index 86d1140da..91555e84b 100644 --- a/components/climate/bang_bang.rst +++ b/components/climate/bang_bang.rst @@ -66,8 +66,8 @@ Do note that the actions are only called when the current temperature leaves the idle_action: - switch.turn_off: heater -Configuration variables ------------------------ +Configuration variables: +------------------------ - **sensor** (**Required**, :ref:`config-id`): The sensor that is used to measure the current temperature. - **default_target_temperature_low** (**Required**, float): The default low target temperature for diff --git a/components/climate/ir_climate.rst b/components/climate/ir_climate.rst index a5c7dad61..fe0a8bbfe 100755 --- a/components/climate/ir_climate.rst +++ b/components/climate/ir_climate.rst @@ -15,30 +15,30 @@ as your remote unit would do. There is a growing list of compatible units. If your unit is not listed below you can fill a feature request so it will be added (see FAQ). -+------------------------+---------------------+----------------------+------------------------------------+ -| Name | Platform name | Supports receiver | | -| | | | | -+========================+=====================+======================+====================================+ -| Coolix | ``coolix`` | yes | | -+------------------------+---------------------+----------------------+------------------------------------+ -| Daikin | ``daikin`` | yes | | -+------------------------+---------------------+----------------------+------------------------------------+ -| Fujitsu General | ``fujitsu_general`` | | | -+------------------------+---------------------+----------------------+------------------------------------+ -| Mitsubishi | ``mitsubishi`` | | | -+------------------------+---------------------+----------------------+------------------------------------+ -| TCL112, Fuego | ``tcl112`` | yes | | -+------------------------+---------------------+----------------------+------------------------------------+ -| Toshiba | ``toshiba`` | yes | | -+------------------------+---------------------+----------------------+------------------------------------+ -| Yashima | ``yashima`` | | | -+------------------------+---------------------+----------------------+------------------------------------+ -| Whirlpool | ``whirlpool`` | yes | :ref:`more info` | -+------------------------+---------------------+----------------------+------------------------------------+ -| LG | ``climate_ir_lg`` | yes | | -+------------------------+---------------------+----------------------+------------------------------------+ -| Hitachi | ``hitachi_ac344`` | yes | | -+------------------------+---------------------+----------------------+------------------------------------+ ++---------------------------------------+---------------------+----------------------+ +| Name | Platform name | Supports receiver | +| | | | ++=======================================+=====================+======================+ +| Coolix | ``coolix`` | yes | ++---------------------------------------+---------------------+----------------------+ +| Daikin | ``daikin`` | yes | ++---------------------------------------+---------------------+----------------------+ +| Fujitsu General | ``fujitsu_general`` | | ++---------------------------------------+---------------------+----------------------+ +| Mitsubishi | ``mitsubishi`` | | ++---------------------------------------+---------------------+----------------------+ +| TCL112, Fuego | ``tcl112`` | yes | ++---------------------------------------+---------------------+----------------------+ +| Toshiba | ``toshiba`` | yes | ++---------------------------------------+---------------------+----------------------+ +| Yashima | ``yashima`` | | ++---------------------------------------+---------------------+----------------------+ +| :ref:`Whirlpool`| ``whirlpool`` | yes | ++---------------------------------------+---------------------+----------------------+ +| :ref:`LG` | ``climate_ir_lg`` | yes | ++---------------------------------------+---------------------+----------------------+ +| Hitachi | ``hitachi_ac344`` | yes | ++---------------------------------------+---------------------+----------------------+ This component requires that you have setup a :doc:`/components/remote_transmitter`. @@ -110,19 +110,48 @@ IR receiver. name: "Living Room AC" receiver_id: rcvr -.. _model_whirlpool: +.. _climate_ir_whirlpool: -Whirlpool ---------- +``whirlpool`` Climate +--------------------- Additional configuration is available for this model + +Configuration variables: + - **model** (*Optional*, string): There are two valid models - * ``MODEL_DG11J1_3A``: Temperature range is from 18 to 32 (default) - * ``MODEL_DG11J1_91``: Temperature range is from 16 to 30 + -* ``DG11J1-3A``: Temperature range is from 18 to 32 (default) + -* ``DG11J1-91``: Temperature range is from 16 to 30 +.. _climate_ir_lg: + +``climate_ir_lg`` Climate +------------------------- + +Additional configuration is available for this platform + + +Configuration variables: + +- **header_high** (*Optional*, :ref:`config-time`): time for the high part of the header for the LG protocol. Defaults to ``8000us`` +- **header_low** (*Optional*, :ref:`config-time`): time for the low part of the header for the LG protocol. Defaults to ``4000us`` +- **bit_high** (*Optional*, :ref:`config-time`): time for the high part of any bit in the LG protocol. Defaults to ``600us`` +- **bit_one_low** (*Optional*, :ref:`config-time`): time for the low part of a '1' bit in the LG protocol. Defaults to ``1600us`` +- **bit_zero_low** (*Optional*, :ref:`config-time`): time for the low part of a '0' bit in the LG protocol. Defaults to ``550us`` + +.. code-block:: yaml + + # Example configuration entry + climate: + - platform: climate_ir_lg + name: "AC" + sensor: room_temperature + header_high: 3265us # AC Units from LG in Brazil, for example use these timings + header_low: 9856us + See Also -------- diff --git a/components/climate/midea_ac.rst b/components/climate/midea_ac.rst new file mode 100644 index 000000000..9d45779a7 --- /dev/null +++ b/components/climate/midea_ac.rst @@ -0,0 +1,115 @@ +Midea Air Conditioner +===================== + +.. seo:: + :description: Instructions for setting up a Midea climate device + :image: air-conditioner.png + +The ``midea_ac`` component creates a Midea air conditioner climate device. + +This component requires a auto-loaded ``midea-dongle`` component, that use hardware UART. + +.. note:: + + This protocol also used by some vendors: + + - `Electrolux `_ + - `Qlima `_ + - `Artel `_ + - `Carrier `_ + - `Comfee `_ + - `Inventor `_ + - and maybe others + + Example of hardware implementation is `Midea Open Dongle `_ in free `KiCad `_ format. + +.. code-block:: yaml + + # Example configuration entry + + # Disable logging over UART (required) + logger: + baud_rate: 0 + + # UART settings for Midea dongle (required) + uart: + tx_pin: 1 + rx_pin: 3 + baud_rate: 9600 + + # Optional (if you want modify settings) + midea_dongle: + strength_icon: true + + # Main settings + climate: + - platform: midea_ac + name: "My Midea AC" + visual: + min_temperature: 18 °C + max_temperature: 25 °C + temperature_step: 0.1 °C + beeper: true + swing_horizontal: true + swing_both: true + outdoor_temperature: + name: "Temp" + power_usage: + name: "Power" + humidity_setpoint: + name: "Hum" + +Configuration variables: +------------------------ + +- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation. +- **midea_dongle_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the ``midea_dongle`` if you want to use multiple devices. +- **name** (**Required**, string): The name of the climate device. +- **outdoor_temperature** (*Optional*): The information for the outdoor temperature + sensor. + + - **name** (**Required**, string): The name of the sensor. + - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. + - All other options from :ref:`Sensor `. +- **power_usage** (*Optional*): The information for the current power consumption + sensor. + + - **name** (**Required**, string): The name of the sensor. + - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. + - All other options from :ref:`Sensor `. +- **humidity_setpoint** (*Optional*): The information for the humidity indoor + sensor (experimental). + + - **name** (**Required**, string): The name of the sensor. + - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. + - All other options from :ref:`Sensor `. +- **beeper** (*Optional*, boolean): Beeper feedback on command. Defaults to ``False``. +- **swing_horizontal** (*Optional*, boolean): Enable **swing horizontal** option. Defaults to ``False``. +- **swing_both** (*Optional*, boolean): Enable **swing both** option. Defaults to ``False``. +- All other options from :ref:`Climate `. + +Configuration variables of midea-dongle component: +************************************************** + +- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation. +- **uart_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the :doc:`../uart` if you want + to use multiple UART buses. +- **strength_icon** (*Optional*, boolean): Set if your device have signal strength icon + and you want to use this feature. By default, on connected state, icon show maximum signal quality. Defaults to ``False``. + + +Acknowledgments: +---------------- + +Thanks to the following people for their contributions to reverse engineering the UART protocol and source code in the following repositories: + +* `Mac Zhou `_ +* `NeoAcheron `_ +* `Rene Klootwijk `_ + +See Also +-------- + +- :doc:`/components/climate/index` +- :apiref:`climate/midea_ac.h` +- :ghedit:`Edit` diff --git a/components/climate/pid.rst b/components/climate/pid.rst index 83ce16152..23f57295d 100644 --- a/components/climate/pid.rst +++ b/components/climate/pid.rst @@ -215,8 +215,8 @@ Configuration variables: ``climate.pid.set_control_parameters`` Action --------------------------------------------- -This action sets new values for the control parameters of the PID controller. This can be -used to manually tune the PID controller. Make sure to take update the values you want on +This action sets new values for the control parameters of the PID controller. This can be +used to manually tune the PID controller. Make sure to take update the values you want on the YAML file! They will reset on the next reboot. .. code-block:: yaml @@ -247,14 +247,14 @@ conditions to avoid the control loop to overshoot (or undershoot) a target. on_...: # Basic - - climate.pid.reset_integral_term: pid_climate + - climate.pid.reset_integral_term: pid_climate Configuration variables: - **id** (**Required**, :ref:`config-id`): ID of the PID Climate being reset. -PID Climate Sensor ------------------- +``pid`` Sensor +-------------- Additionally, the PID climate platform provides an optional sensor platform to monitor the calculated PID parameters to help finding good PID values. diff --git a/components/climate/thermostat.rst b/components/climate/thermostat.rst index 47943879e..2d6f52549 100644 --- a/components/climate/thermostat.rst +++ b/components/climate/thermostat.rst @@ -133,8 +133,7 @@ Examples: Got all that? Great. Let's take a closer look at some configuration. -Configuration Variables ------------------------ +Configuration Variables: The thermostat controller uses the sensor to determine whether it should heat or cool. diff --git a/components/climate/tuya.rst b/components/climate/tuya.rst index 169606b9b..d14f906e2 100644 --- a/components/climate/tuya.rst +++ b/components/climate/tuya.rst @@ -48,11 +48,11 @@ Configuration variables: - **switch_datapoint** (**Required**, int): The datapoint id number of the climate switch. - **target_temperature_datapoint** (**Required**, int): The datapoint id number of the target temperature. - **current_temperature_datapoint** (**Required**, int): The datapoint id number of the current temperature. -- **temperature_multiplier** (**Optional**, float): A multiplier to modify the incoming and outgoing temperature values - :ref:`see below `. +- **temperature_multiplier** (*Optional*, float): A multiplier to modify the incoming and outgoing temperature values - :ref:`see below `. If the device has different multipliers for current and target temperatures, **temperature_multiplier** can be replaced with both of: - - **current_temperature_multiplier** (**Optional**, float): A multiplier to modify the current temperature value. - - **target_temperature_multiplier** (**Optional**, float): A multiplier to modify the target temperature value. + - **current_temperature_multiplier** (*Optional*, float): A multiplier to modify the current temperature value. + - **target_temperature_multiplier** (*Optional*, float): A multiplier to modify the target temperature value. - All other options from :ref:`Climate `. .. _temperature-multiplier: diff --git a/components/debug.rst b/components/debug.rst index e6c592006..182326a03 100644 --- a/components/debug.rst +++ b/components/debug.rst @@ -22,7 +22,7 @@ a bunch of useful information like reset reason, free heap size, ESPHome version logger: level: debug -There are no configuration variables for this component. +No configuration variables. See Also -------- diff --git a/components/deep_sleep.rst b/components/deep_sleep.rst index 9b2578681..c056e3b66 100644 --- a/components/deep_sleep.rst +++ b/components/deep_sleep.rst @@ -33,9 +33,8 @@ Configuration variables: - **run_duration** (*Optional*, :ref:`config-time`): The time duration the node should be active, i.e. run code. - **sleep_duration** (*Optional*, :ref:`config-time`): The time duration to stay in deep sleep mode. -- **wakeup_pin** (*Optional*, :ref:`Pin Schema `): - Only on ESP32. A pin to wake up to once in deep sleep mode. Use the inverted property to wake up - to LOW signals. +- **wakeup_pin** (*Optional*, :ref:`Pin Schema `): Only on ESP32. A pin to wake up to once + in deep sleep mode. Use the inverted property to wake up to LOW signals. - **wakeup_pin_mode** (*Optional*): Only on ESP32. Specify how to handle waking up from a ``wakeup_pin`` if the wakeup pin is already in the state with which it would wake up when attempting to enter deep sleep. See :ref:`deep_sleep-esp32_wakeup_pin_mode`. Defaults to ``IGNORE`` @@ -84,6 +83,11 @@ This action makes the given deep sleep component enter deep sleep immediately. on_...: then: - deep_sleep.enter: deep_sleep_1 + sleep_duration: 20min + +Configuration options: + +- **sleep_duration** (*Optional*, :ref:`config-time`): The time duration to stay in deep sleep mode. .. _deep_sleep-prevent_action: @@ -111,7 +115,7 @@ Useful for keeping the ESP active during data transfer or OTA updating (See note it will no longer enter deep sleep mode and you can upload your OTA update. Remember to turn "OTA mode" off again after the OTA update by sending a MQTT message with the payload - ``OFF``. To enter the the deep sleep again after the OTA update send a message on the topic ``livingroom/sleep_mode`` + ``OFF``. To enter the the deep sleep again after the OTA update send a message on the topic ``livingroom/sleep_mode`` with payload ``ON``. Deep sleep will start immediately. Don't forget to delete the payload before the node wakes up again. diff --git a/components/dfplayer.rst b/components/dfplayer.rst index e6afa1687..ed67bbcae 100644 --- a/components/dfplayer.rst +++ b/components/dfplayer.rst @@ -21,10 +21,10 @@ Overview -------- The module can be powered by the 3.3V output of a NodeMCU. For communication you can connect only -the ``tx_pin`` of the ``uart`` bus to the module's ``RX`` but if you need feedback of playback active +the ``tx_pin`` of the ``uart`` bus to the module's ``RX`` but if you need feedback of playback active you will also need to connect the ``rx_pin`` to the module's ``TX``. For best quality audio a powered stereo speaker can be connected to the modules ``DAC_R``, -``DAC_I`` and ``GND``, alternatively the module features a built-in 3W audio amplifier, in that case +``DAC_L`` and ``GND``, alternatively the module features a built-in 3W audio amplifier, in that case the pins ``SPK_1`` and ``SPK_2`` should be connected to one passive speaker and a 5V 1A power supply will be required. @@ -115,8 +115,8 @@ Configuration options: ------------------------------- Plays files inside numbered folders, folders must be numbered from 1 and with leading -zeros. Like `01`, `02`, ... etc. Files inside the folders must be numbered with two -leading zeros, like `001.mp3`, `002.mp3`, ... etc. +zeros. Like ``01``, ``02``, ... etc. Files inside the folders must be numbered with two +leading zeros, like ``001.mp3``, ``002.mp3``, ... etc. Folder numbers can range from 1 to 99 and file name from 1 to 255 or folder number from 1 to 10 and file number from 1 to 1000. @@ -178,7 +178,7 @@ Changes volume. Configuration options: - **volume** (**Required**, int, :ref:`templatable `): The volume value. - Valid values goes from 0 to 30. + Valid values goes from ``0`` to ``30``. ``dfplayer.set_eq`` Action -------------------------- diff --git a/components/display/addressable_light.rst b/components/display/addressable_light.rst new file mode 100644 index 000000000..3bf6bba7f --- /dev/null +++ b/components/display/addressable_light.rst @@ -0,0 +1,146 @@ +Addressable Light +================= + +.. seo:: + :description: Instructions for setting up displays using addressable lights and LED matrix + :image: addressable_light.jpg + +The ``addressable_light`` display platform allows to display text and graphics on an addressable +light that has been arranged in a display matrix. + +The display requires that an :apiclass:`AddressableLight ` component, such as +:doc:`/components/light/fastled` or :doc:`/components/light/neopixelbus`, be defined. + +.. figure:: images/addressable_light.jpg + :align: center + :width: 75.0% + + WS2812B Addressable Light Display + +.. code-block:: yaml + + light: + - platform: fastled_clockless + chipset: WS2812B + pin: GPIO4 + num_leds: 64 + rgb_order: GRB + name: "led_matrix" + id: led_matrix_light + default_transition_length: 0s + color_correct: [50%, 50%, 50%] + restore_mode: ALWAYS_ON + + display: + - platform: addressable_light + id: led_matrix_display + addressable_light_id: led_matrix_light + width: 8 + height: 8 + rotation: 180° + update_interval: 16ms + lambda: |- + // Draw a bulls-eye pattern + Color red = Color(0xFF0000); + Color green = Color(0x00FF00); + Color blue = Color(0x0000FF); + it.rectangle(0, 0, 8, 8, red); + it.rectangle(1, 1, 6, 6, green); + it.rectangle(2, 2, 4, 4, blue); + it.rectangle(3, 3, 2, 2, red); + +Configuration variables: +------------------------ + +- **addressable_light_id** (**Required**, :ref:`config-id`): The id of the addressable light component to use + as a display. +- **width** (**Required**, int): The width of the LED matrix in pixels. +- **height** (**Required**, int): The height of the LED matrix in pixels. +- **rotation** (*Optional*): Set the rotation of the display. Everything you draw in ``lambda:`` will be rotated + by this option. One of ``0°`` (default), ``90°``, ``180°``, ``270°``. +- **update_interval** (*Optional*, :ref:`config-time`): The interval to call the lambda to update the display. + Defaults to ``16ms``. +- **pixel_mapper** (*Optional*, :ref:`lambda `): A lambda that returns the integer address of the LED + given the supplied the ``x`` and ``y`` pixel coordinate. By default, a left-to-right direct pixel mapper is used. +- **lambda** (*Optional*, :ref:`lambda `): The lambda to use for rendering the content on the display. + ``it`` will be an instance of :apiclass:`DisplayBuffer `. + See :ref:`display-engine` for more information. +- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation. + + +.. note:: + + When enabled (the default, but also via ``it.set_enabled(true)``), any effect currently running on the + addressable light will be disabled. When disabled (``it.set_enabled(false)``), the last configured effect will + be restored. + + While the display is enabled, it is still possible to control the parent addressable light component in some + limited capacity. Changing the brightness will still work, but changing the color will have no affect. It is not + adivsable to enable any effects (ex: rainbow, color wipe, etc) while the display is enabled, as this will cause a + great deal of flickering while the effect competes with the display for rendering. + + +pixel_mapper +------------ + +An addressable LED matrix is just an addressable LED strip laid out in a matrix -- the path often snaking +down-up-down, left-right-left, or whichever way the manufacturer has chosen. Like an addressable LED strip, +each pixel on a matrix is addressed as an offset from the first pixel (0). The job of the pixel mapper is +to translate a logical x-y pixel coordinate to the address of the expected physical LED. + +Determining the correct algorithm for the pixel mapper for your matrix will hopefully only require some graph paper and a little bit of math. + + +Default +******* + +The default pixel mapper assumes that the led matrix is addressed starting with the top left LED, moving to the right, and +then starting with the left-most row of the next row. + +.. figure:: images/addressable_light_pixel_map_default.png + :align: center + :width: 75.0% + + Default pixel_mapper as used with a 4x4 led matrix + + +BTF-Lighting 8x32 WS2812B Flexible LED Matrix +********************************************* + +The following image illustrates the path the addressable strip takes through the common the BTF-Lighting 8x32 matrix. + +.. figure:: images/addressable_light_pixel_map_8x32.png + :align: center + :width: 75.0% + + LED layout for BTF-Lighting 8x32 WS2812B Flexible LED Matrix + + +Below is a definition that includes a pixel_mapper suitable for these 8x32 matrices. + +.. code-block:: yaml + + display: + - platform: addressable_light + id: led_matrix_32x8_display + addressable_light_id: led_matrix_32x8 + width: 32 + height: 8 + pixel_mapper: |- + if (x % 2 == 0) { + return (x * 8) + y; + } + return (x * 8) + (7 - y); + rotation: 0° + update_interval: 16ms + + +See Also +-------- + +- :apiref:`addressable_light/addressable_light_display.h` +- :doc:`/components/light/index` +- :doc:`/components/light/fastled` +- :doc:`/components/light/neopixelbus` +- :doc:`/components/light/partition` +- :ghedit:`Edit` diff --git a/components/display/ili9341.rst b/components/display/ili9341.rst index 536d6c96f..612a89b91 100644 --- a/components/display/ili9341.rst +++ b/components/display/ili9341.rst @@ -33,13 +33,13 @@ beyond the typical SPI connections, it is better suited for use with the ESP32. dc_pin: 27 led_pin: 32 ### see note below ### reset_pin: 33 - + lambda: |- it.fill(COLOR_BLACK); it.print(0, 0, id(my_font), id(my_red), TextAlign::TOP_LEFT, "Hello World!"); - -Configuration variables -*********************** + +Configuration variables: +************************ - **model** (**Required**): The model of the display. Options are: diff --git a/components/display/images/addressable_light.jpg b/components/display/images/addressable_light.jpg new file mode 100644 index 000000000..bb0de7cd6 Binary files /dev/null and b/components/display/images/addressable_light.jpg differ diff --git a/components/display/images/addressable_light_pixel_map_8x32.png b/components/display/images/addressable_light_pixel_map_8x32.png new file mode 100644 index 000000000..d5886c3d8 Binary files /dev/null and b/components/display/images/addressable_light_pixel_map_8x32.png differ diff --git a/components/display/images/addressable_light_pixel_map_default.png b/components/display/images/addressable_light_pixel_map_default.png new file mode 100644 index 000000000..f39ab8893 Binary files /dev/null and b/components/display/images/addressable_light_pixel_map_default.png differ diff --git a/components/display/images/inkplate.jpg b/components/display/images/inkplate.jpg new file mode 100644 index 000000000..a373c8082 Binary files /dev/null and b/components/display/images/inkplate.jpg differ diff --git a/components/display/index.rst b/components/display/index.rst index b6c650e57..782de3f4e 100644 --- a/components/display/index.rst +++ b/components/display/index.rst @@ -321,11 +321,41 @@ use any string you pass it, like ``"ON"`` or ``"OFF"``. Displaying Time *************** -With ESPHome you can also display the current time using the NTP protocol. Please see the example :ref:`here `. +You can display current time using a time component. Please see the example :ref:`here `. + + +.. _config-color: + +Color +***** + +When using RGB-capable displays in ESPHome you may wish to use custom colors. +A ``color`` component exists for just this purpose: + +.. code-block:: yaml + + color: + - id: my_light_red + red: 100% + green: 20% + blue: 25% + white: 0% + + +Configuration variables: + +- **red** (*Optional*, percentage): The percentage of the red component. Defaults to ``100%``. +- **green** (*Optional*, percentage): The percentage of the green component. Defaults to ``100%``. +- **blue** (*Optional*, percentage): The percentage of the blue component. Defaults to ``100%``. +- **white** (*Optional*, percentage): The percentage of the white component. Defaults to ``100%``. + +RGB displays use red, green, and blue, while grayscale displays may use white. Images ****** +Use this component to store graphical images on the device, you can then draw the images on compatible displays. + .. code-block:: yaml image: @@ -338,7 +368,7 @@ Configuration variables: - **file** (**Required**, string): The path (relative to where the .yaml file is) of the image file. - **id** (**Required**, :ref:`config-id`): The ID with which you will be able to reference the image later in your display code. -- **resize** (*Optional*, int): If set, this will resize the image to fit inside the given dimensions ``WIDTHxHEIGHT`` +- **resize** (*Optional*, string): If set, this will resize the image to fit inside the given dimensions ``WIDTHxHEIGHT`` and preserve the aspect ratio. - **type** (*Optional*): Specifies how to encode image internally. Defaults to ``BINARY``. @@ -388,8 +418,8 @@ as the additional parameters. Animation ********* -Animation inherits all options from the image component. -It adds an additional method to change the shown picture of a gif. +Allows to use animated images on displays. Animation inherits all options from the image component. +It adds an additional lambda method: ``next_frame()`` to change the shown picture of a gif. .. code-block:: yaml @@ -426,6 +456,30 @@ This can be combined with all Lambdas: lambda: |- id(my_animation).next_frame(); + +Configuration variables: +^^^^^^^^^^^^^^^^^^^^^^^^ + +- **file** (**Required**, string): The path (relative to where the .yaml file is) of the gif file. +- **id** (**Required**, :ref:`config-id`): The ID with which you will be able to reference the animation later + in your display code. +- **resize** (*Optional*, string): If set, this will resize all the frames to fit inside the given dimensions ``WIDTHxHEIGHT`` + and preserve the aspect ratio. +- **type** (*Optional*): Specifies how to encode each frame internally. Defaults to ``BINARY``. + + - ``BINARY``: Two colors, suitable for 1 color displays or 2 color image in color displays. Uses 1 bit + per pixel, 8 pixels per byte. + - ``GREYSCALE``: Full scale grey. Uses 8 bits per pixel, 1 pixel per byte. + - ``RGB24``: Full RGB color stored. Uses 3 bytes per pixel. + +- **dither** (*Optional*): Specifies which dither method used to process each frame, only used in GREYSCALE and BINARY type image. + Defaults to ``NONE``. You can read more about it `here `__ + and `here `__. + + - ``NONE``: Every pixel convert to its nearest color. + - ``FLOYDSTEINBERG``: Uses Floyd-Steinberg dither to approximate the original image luminosity levels. + + .. _display-pages: Display Pages @@ -495,6 +549,7 @@ You can then switch between these with three different actions: - display.page.show_next: my_display - component.update: my_display + See Also -------- diff --git a/components/display/inkplate6.rst b/components/display/inkplate6.rst new file mode 100644 index 000000000..9c5f167c7 --- /dev/null +++ b/components/display/inkplate6.rst @@ -0,0 +1,277 @@ +Inkplate 6 +========== + +.. seo:: + :description: Instructions for setting up Inkplate E-Paper displays in ESPHome. + :image: inkplate.jpg + +All-in-one e-paper display ``Inkplate 6`` +Inkplate 6 is a powerful, Wi-Fi enabled ESP32 based six-inch e-paper display – recycled from a Kindle e-reader. Its main feature is simplicity. +Learn more at `Inkplate's website `__ + +.. figure:: images/inkplate.jpg + :align: center + :width: 75.0% + + Inkplate 6 + + +.. code-block:: yaml + + # Example minimal configuration entry + + mcp23017: + - id: mcp23017_hub + address: 0x20 + + display: + - platform: inkplate6 + id: inkplate_display + greyscale: false + partial_updating: false + update_interval: 60s + + ckv_pin: 32 + sph_pin: 33 + gmod_pin: + mcp23017: mcp23017_hub + number: 1 + gpio0_enable_pin: + mcp23017: mcp23017_hub + number: 8 + oe_pin: + mcp23017: mcp23017_hub + number: 0 + spv_pin: + mcp23017: mcp23017_hub + number: 2 + powerup_pin: + mcp23017: mcp23017_hub + number: 4 + wakeup_pin: + mcp23017: mcp23017_hub + number: 3 + vcom_pin: + mcp23017: mcp23017_hub + number: 5 + +.. warning:: + + When using the Inkplate epaper module, the GPIO pin numbers above *cannot be changed* as they are + hardwired within the module/PCB. + +.. warning:: + + Inkplate module cannot perform partial update if 3 bit mode is on. + It just ignores the function call in that case. + + +Configuration variables: +************************ + +- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation. +- **greyscale** (*Optional*, boolean): Makes the screen display 3 bit colors. Defaults to ``False`` +- **partial_updating** (*Optional*, boolean): Makes the screen update partially, which is faster, but leaves burnin. Defaults to ``False`` +- **full_update_every** (*Optional*, int): When partial updating is enabled, forces a full screen update after chosen number of updates. Defaults to ``10`` +- **lambda** (*Optional*, :ref:`lambda `): The lambda to use for rendering the content on the display. + See :ref:`display-engine` for more information. +- **update_interval** (*Optional*, :ref:`config-time`): The interval to re-draw the screen. Defaults to ``5s``. +- **pages** (*Optional*, list): Show pages instead of a single lambda. See :ref:`display-pages`. + +- **ckv_pin** (**Required**, :ref:`config-pin`): The CKV pin for the Inkplate display. +- **gmod_pin** (**Required**, :ref:`config-pin`): The GMOD pin for the Inkplate display. +- **gpio0_enable_pin** (**Required**, :ref:`config-pin`): The GPIO0 Enable pin for the Inkplate display. +- **oe_pin** (**Required**, :ref:`config-pin`): The OE pin for the Inkplate display. +- **powerup_pin** (**Required**, :ref:`config-pin`): The Powerup pin for the Inkplate display. +- **sph_pin** (**Required**, :ref:`config-pin`): The SPH pin for the Inkplate display. +- **spv_pin** (**Required**, :ref:`config-pin`): The SPV pin for the Inkplate display. +- **vcom_pin** (**Required**, :ref:`config-pin`): The VCOM pin for the Inkplate display. +- **cl_pin** (*Optional*, :ref:`config-pin`): The CL pin for the Inkplate display. + Defaults to GPIO0. +- **le_pin** (*Optional*, :ref:`config-pin`): The LE pin for the Inkplate display. + Defaults to GPIO2. + +- **display_data_0_pin** (*Optional*, :ref:`config-pin`): The Data 0 pin for the Inkplate display. + Defaults to GPIO4. +- **display_data_1_pin** (*Optional*, :ref:`config-pin`): The Data 1 pin for the Inkplate display. + Defaults to GPIO5. +- **display_data_2_pin** (*Optional*, :ref:`config-pin`): The Data 2 pin for the Inkplate display. + Defaults to GPIO18. +- **display_data_3_pin** (*Optional*, :ref:`config-pin`): The Data 3 pin for the Inkplate display. + Defaults to GPIO19. +- **display_data_4_pin** (*Optional*, :ref:`config-pin`): The Data 4 pin for the Inkplate display. + Defaults to GPIO23. +- **display_data_5_pin** (*Optional*, :ref:`config-pin`): The Data 5 pin for the Inkplate display. + Defaults to GPIO25. +- **display_data_6_pin** (*Optional*, :ref:`config-pin`): The Data 6 pin for the Inkplate display. + Defaults to GPIO26. +- **display_data_7_pin** (*Optional*, :ref:`config-pin`): The Data 7 pin for the Inkplate display. + Defaults to GPIO27. + + +Complete example +**************** + +The following is a complete example YAML configuration that does a few things beyond the usual +Wi-Fi, API, and OTA configuration. + +.. code-block:: yaml + + # Example configuration entry + esphome: + name: inkplate + platform: ESP32 + board: esp-wrover-kit + + logger: + + wifi: + ssid: + password: + ap: + ssid: Inkplate-AP + password: '12345678' + + captive_portal: + + ota: + + api: + + switch: + - platform: restart + name: "Inkplate Reboot" + id: reboot + + - platform: gpio + id: battery_read_mosfet + pin: + mcp23017: mcp23017_hub + number: 9 + inverted: true + + - platform: template + name: "Inkplate Greyscale mode" + lambda: return id(inkplate_display).get_greyscale(); + turn_on_action: + - lambda: id(inkplate_display).set_greyscale(true); + turn_off_action: + - lambda: id(inkplate_display).set_greyscale(false); + + - platform: template + name: "Inkplate Partial Updating" + lambda: return id(inkplate_display).get_partial_updating(); + turn_on_action: + - lambda: id(inkplate_display).set_partial_updating(true); + turn_off_action: + - lambda: id(inkplate_display).set_partial_updating(false); + + sensor: + - platform: adc + id: battery_voltage + update_interval: never + attenuation: 11db + pin: 35 + - platform: template + name: "Inkplate Battery Voltage" + lambda: |- + id(battery_read_mosfet).turn_on(); + delay(1); + float adc = id(battery_voltage).sample(); + id(battery_read_mosfet).turn_off(); + return adc; + filters: + - multiply: 2 + + i2c: + + mcp23017: + - id: mcp23017_hub + address: 0x20 + + binary_sensor: + - platform: status + name: "Inkplate Status" + id: system_status + + - platform: gpio + name: "Inkplate Touch Pad 1" + pin: + mcp23017: mcp23017_hub + number: 10 + - platform: gpio + name: "Inkplate Touch Pad 2" + pin: + mcp23017: mcp23017_hub + number: 11 + - platform: gpio + name: "Inkplate Touch Pad 3" + pin: + mcp23017: mcp23017_hub + number: 12 + + time: + - platform: sntp + id: esptime + + font: + - file: "Helvetica.ttf" + id: helvetica_96 + size: 96 + - file: "Helvetica.ttf" + id: helvetica_48 + size: 48 + + + display: + - platform: inkplate6 + id: inkplate_display + greyscale: false + partial_updating: false + update_interval: 60s + + ckv_pin: 32 + sph_pin: 33 + gmod_pin: + mcp23017: mcp23017_hub + number: 1 + gpio0_enable_pin: + mcp23017: mcp23017_hub + number: 8 + oe_pin: + mcp23017: mcp23017_hub + number: 0 + spv_pin: + mcp23017: mcp23017_hub + number: 2 + powerup_pin: + mcp23017: mcp23017_hub + number: 4 + wakeup_pin: + mcp23017: mcp23017_hub + number: 3 + vcom_pin: + mcp23017: mcp23017_hub + number: 5 + + lambda: |- + it.fill(COLOR_ON); + + it.print(100, 100, id(helvetica_48), COLOR_OFF, TextAlign::TOP_LEFT, "ESPHome"); + + it.strftime(400, 300, id(helvetica_48), COLOR_OFF, TextAlign::CENTER, "%Y-%m-%d", id(esptime).now()); + it.strftime(400, 400, id(helvetica_96), COLOR_OFF, TextAlign::CENTER, "%H:%M", id(esptime).now()); + + if (id(system_status).state) { + it.print(700, 100, id(helvetica_48), COLOR_OFF, TextAlign::TOP_RIGHT, "Online"); + } else { + it.print(700, 100, id(helvetica_48), COLOR_OFF, TextAlign::TOP_RIGHT, "Offline"); + } + + +See Also +-------- + +- :doc:`index` +- `Arduino Inkplate 6 library `__ by `E-radionica.com `__ +- :ghedit:`Edit` diff --git a/components/display/lcd_display.rst b/components/display/lcd_display.rst index 40fc478e3..ad54d07d4 100644 --- a/components/display/lcd_display.rst +++ b/components/display/lcd_display.rst @@ -7,8 +7,8 @@ Character-Based LCD Display .. _lcd-pcf8574: -PCF8574 -------- +lcd_pcf8574 Component +--------------------- The ``lcd_pcf8574`` display platform allows you to use standard character-based LCD displays like `this one `__ @@ -56,8 +56,8 @@ Configuration variables: .. _lcd-gpio: -GPIO ----- +lcd_gpio Component +------------------ The ``lcd_gpio`` display platform allows you to use standard character-based LCD displays like `this one `__ with ESPHome. This integration is only for LCD displays that display individual characters on a screen (usually 16-20 columns diff --git a/components/display/nextion.rst b/components/display/nextion.rst index 60903e5c3..e37e00f26 100644 --- a/components/display/nextion.rst +++ b/components/display/nextion.rst @@ -39,8 +39,7 @@ Configuration variables: - **uart_id** (*Optional*, :ref:`config-id`): The ID of the :ref:`UART bus ` you wish to use for this display. Use this if you want to use multiple UART buses at once. -- **brightness** (*Optional*, percentage): Set the screen brightness. Must be in range - ``0%`` to ``100%`` or ``0.0`` to ``1.0``. Defaults to ``100%``. +- **brightness** (*Optional*, percentage): Set display brightness in %. Defaults to ``100%`` - **lambda** (*Optional*, :ref:`lambda `): The lambda to use for rendering the content on the nextion display. See :ref:`display-nextion_lambda` for more information. - **update_interval** (*Optional*, :ref:`config-time`): The interval to call the lambda to update the display. diff --git a/components/display/pcd8544.rst b/components/display/pcd8544.rst index a8fda0a19..21812e19e 100644 --- a/components/display/pcd8544.rst +++ b/components/display/pcd8544.rst @@ -53,9 +53,9 @@ To use a backlight LIGHT pin needs to be connected to ground. If connected to GP Configuration variables: ************************ -- **reset_pin** (**Required**)(:ref:`Pin Schema `): The RESET pin. -- **cs_pin** (**Required**)(:ref:`Pin Schema `): The CS pin. -- **dc_pin** (**Required**)(:ref:`Pin Schema `): The DC pin. +- **reset_pin** (**Required**, :ref:`Pin Schema `): The RESET pin. +- **cs_pin** (**Required**, :ref:`Pin Schema `): The CS pin. +- **dc_pin** (**Required**, :ref:`Pin Schema `): The DC pin. - **lambda** (*Optional*, :ref:`lambda `): The lambda to use for rendering the content on the display. See :ref:`display-engine` for more information. - **update_interval** (*Optional*, :ref:`config-time`): The interval to re-draw the screen. Defaults to ``5s``. diff --git a/components/display/ssd1306.rst b/components/display/ssd1306.rst index dee36f434..a60b0f170 100644 --- a/components/display/ssd1306.rst +++ b/components/display/ssd1306.rst @@ -61,7 +61,7 @@ Configuration variables: - **address** (*Optional*, int): Manually specify the :ref:`I²C ` address of the display. Defaults to 0x3C. - **rotation** (*Optional*): Set the rotation of the display. Everything you draw in ``lambda:`` will be rotated by this option. One of ``0°`` (default), ``90°``, ``180°``, ``270°``. -- **brightness** (*Optional*): Set the screen brightness in percents 0.0-1.0. Defaults to `1.0` that corresponds to 100%. +- **brightness** (*Optional*, percentage): Set display brightness in %. Defaults to ``100%`` - **external_vcc** (*Optional*, boolean): Set this to true if you have the VCC pin connected to an external power supply. Defaults to ``false``. - **lambda** (*Optional*, :ref:`lambda `): The lambda to use for rendering the content on the display. @@ -69,7 +69,6 @@ Configuration variables: - **update_interval** (*Optional*, :ref:`config-time`): The interval to re-draw the screen. Defaults to ``5s``. - **pages** (*Optional*, list): Show pages instead of a single lambda. See :ref:`display-pages`. - **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation. -- **brightness** (*Optional*, float): Manually override display brightness in %. Defaults to ``100%`` .. note:: @@ -133,6 +132,7 @@ Configuration variables: - **reset_pin** (*Optional*, :ref:`Pin Schema `): The RESET pin. Defaults to not connected. - **rotation** (*Optional*): Set the rotation of the display. Everything you draw in ``lambda:`` will be rotated by this option. One of ``0°`` (default), ``90°``, ``180°``, ``270°``. +- **brightness** (*Optional*, percentage): Set display brightness in %. Defaults to ``100%`` - **external_vcc** (*Optional*, boolean): Set this to true if you have the VCC pin connected to an external power supply. Defaults to ``false``. - **lambda** (*Optional*, :ref:`lambda `): The lambda to use for rendering the content on the display. @@ -142,7 +142,6 @@ Configuration variables: - **spi_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the :ref:`SPI Component ` if you want to use multiple SPI buses. - **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation. -- **brightness** (*Optional*, float): Manually override display brightness in %. Defaults to ``100%`` See Also -------- diff --git a/components/display/ssd1322.rst b/components/display/ssd1322.rst index d2a0dd249..35fcc545e 100644 --- a/components/display/ssd1322.rst +++ b/components/display/ssd1322.rst @@ -7,8 +7,8 @@ SSD1322 OLED Display .. _ssd1322-spi: -Usage ------ +``ssd1322_spi`` Component +------------------------- The ``ssd1322_spi`` display platform allows you to use SSD1322 (`datasheet `__, @@ -47,9 +47,9 @@ Configuration variables: - ``SSD1322 256x64`` -- **reset_pin** (:ref:`Pin Schema `): The RESET pin. -- **cs_pin** (:ref:`Pin Schema `): The CS pin. -- **dc_pin** (:ref:`Pin Schema `): The DC pin. +- **dc_pin** (**Required**, :ref:`Pin Schema `): The DC pin. +- **reset_pin** (*Optional*, :ref:`Pin Schema `): The RESET pin. +- **cs_pin** (*Optional*, :ref:`Pin Schema `): The CS pin. - **lambda** (*Optional*, :ref:`lambda `): The lambda to use for rendering the content on the display. See :ref:`display-engine` for more information. - **update_interval** (*Optional*, :ref:`config-time`): The interval to re-draw the screen. Defaults to ``5s``. diff --git a/components/display/ssd1325.rst b/components/display/ssd1325.rst index 778b7093a..45740b025 100644 --- a/components/display/ssd1325.rst +++ b/components/display/ssd1325.rst @@ -7,8 +7,8 @@ SSD1325/7 OLED Display .. _ssd1325-spi: -Usage ------ +``ssd1325_spi`` Component +------------------------- The ``ssd1325_spi`` display platform allows you to use SSD1325 (`datasheet `__, @@ -44,8 +44,8 @@ that explains how to do this, if necessary. lambda: |- it.print(0, 0, id(font), "Hello World!"); -Configuration Variables -*********************** +Configuration variables: +************************ - **model** (**Required**): The model of the display. Options are: @@ -54,10 +54,10 @@ Configuration Variables - ``SSD1325 96x16`` - ``SSD1325 64x48`` -- **reset_pin** (:ref:`Pin Schema `): The RESET pin. -- **cs_pin** (:ref:`Pin Schema `): The pin on the ESP that that the CS line is connected to. +- **dc_pin** (**Required**, :ref:`Pin Schema `): The DC pin. +- **reset_pin** (*Optional*, :ref:`Pin Schema `): The RESET pin. +- **cs_pin** (*Optional*, :ref:`Pin Schema `): The pin on the ESP that that the CS line is connected to. The CS line can be connected to GND if this is the only device on the SPI bus. -- **dc_pin** (:ref:`Pin Schema `): The DC pin. - **lambda** (*Optional*, :ref:`lambda `): The lambda to use for rendering the content on the display. See :ref:`display-engine` for more information. - **update_interval** (*Optional*, :ref:`config-time`): The interval to re-draw the screen. Defaults to ``5s``. diff --git a/components/display/ssd1327.rst b/components/display/ssd1327.rst index a958e15dc..3ba15b3f8 100644 --- a/components/display/ssd1327.rst +++ b/components/display/ssd1327.rst @@ -41,8 +41,8 @@ ESP; this is recommended as it improves reliability. lambda: |- it.print(0, 0, id(font), "Hello World!"); -Configuration variables -*********************** +Configuration variables: +************************ - **model** (**Required**): The model of the display. At present, only one option is available: @@ -52,13 +52,12 @@ Configuration variables - **address** (*Optional*, int): Manually specify the :ref:`I²C ` address of the display. Defaults to 0x3D. - **rotation** (*Optional*): Set the rotation of the display. Everything you draw in ``lambda:`` will be rotated by this option. One of ``0°`` (default), ``90°``, ``180°``, ``270°``. -- **brightness** (*Optional*): Set the screen brightness in percents 0.0-1.0. Defaults to `1.0` that corresponds to 100%. +- **brightness** (*Optional*, percentage): Set display brightness in %. Defaults to ``100%`` - **lambda** (*Optional*, :ref:`lambda `): The lambda to use for rendering the content on the display. See :ref:`display-engine` for more information. - **update_interval** (*Optional*, :ref:`config-time`): The interval to re-draw the screen. Defaults to ``5s``. - **pages** (*Optional*, list): Show pages instead of a single lambda. See :ref:`display-pages`. - **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation. -- **brightness** (*Optional*, float): Manually override display brightness in %. Defaults to ``100%`` .. note:: @@ -101,8 +100,8 @@ available pin on the ESP; this is recommended as it improves reliability. lambda: |- it.print(0, 0, id(font), "Hello World!"); -Configuration variables -*********************** +Configuration variables: +************************ - **model** (**Required**): The model of the display. At present, only one option is available: @@ -113,6 +112,7 @@ Configuration variables - **reset_pin** (*Optional*, :ref:`Pin Schema `): The RESET pin. Defaults to not connected. - **rotation** (*Optional*): Set the rotation of the display. Everything you draw in ``lambda:`` will be rotated by this option. One of ``0°`` (default), ``90°``, ``180°``, ``270°``. +- **brightness** (*Optional*, percentage): Set display brightness in %. Defaults to ``100%`` - **lambda** (*Optional*, :ref:`lambda `): The lambda to use for rendering the content on the display. See :ref:`display-engine` for more information. - **update_interval** (*Optional*, :ref:`config-time`): The interval to re-draw the screen. Defaults to ``5s``. @@ -120,7 +120,6 @@ Configuration variables - **spi_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the :ref:`SPI Component ` if you want to use multiple SPI buses. - **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation. -- **brightness** (*Optional*, float): Manually override display brightness in %. Defaults to ``100%`` Configuration examples ********************** diff --git a/components/display/ssd1331.rst b/components/display/ssd1331.rst index effe29fb2..525571b04 100644 --- a/components/display/ssd1331.rst +++ b/components/display/ssd1331.rst @@ -39,13 +39,13 @@ require 5 volts connected to their ``+`` pin. Connect the GND or G pin to ground lambda: |- it.print(0, 0, id(font), "Hello World!"); -Configuration variables -*********************** +Configuration variables: +************************ -- **reset_pin** (:ref:`Pin Schema `): The RESET pin. +- **dc_pin** (**Required**, :ref:`Pin Schema `): The DC pin. +- **reset_pin** (*Optional*, :ref:`Pin Schema `): The RESET pin. - **cs_pin** (*Optional*, :ref:`Pin Schema `): The pin on the ESP that that the CS line is connected to. The CS line can be connected to GND if this is the only device on the SPI bus. -- **dc_pin** (:ref:`Pin Schema `): The DC pin. - **lambda** (*Optional*, :ref:`lambda `): The lambda to use for rendering the content on the display. See :ref:`display-engine` for more information. - **update_interval** (*Optional*, :ref:`config-time`): The interval to re-draw the screen. Defaults to ``5s``. diff --git a/components/display/ssd1351.rst b/components/display/ssd1351.rst index 728275a31..64d46c112 100644 --- a/components/display/ssd1351.rst +++ b/components/display/ssd1351.rst @@ -7,8 +7,8 @@ SSD1351 OLED Display .. _ssd1351-spi: -Usage ------ +``ssd1351_spi`` Component +------------------------- The ``ssd1351_spi`` display platform allows you to use SSD1351 (`datasheet `__, @@ -43,18 +43,17 @@ which should be connected to 3.3 volts only. Connect the GND or G pin to GND. lambda: |- it.print(0, 0, id(font), "Hello World!"); -Configuration variables -*********************** +Configuration variables: +************************ - **model** (**Required**): The model of the display. Options are: - ``SSD1351 128x128`` (SSD1351 with 128 columns and 128 rows) - ``SSD1351 128x96`` (SSD1351 with 128 columns and 96 rows) -- **reset_pin** (:ref:`Pin Schema `): The RESET pin. -- **cs_pin** (*Optional*, :ref:`Pin Schema `): The pin on the ESP that that the CS line is connected to. - The CS line can be connected to GND if this is the only device on the SPI bus. -- **dc_pin** (:ref:`Pin Schema `): The DC pin. +- **dc_pin** (**Required**, :ref:`Pin Schema `): The DC pin. +- **cs_pin** (**Required**, :ref:`Pin Schema `): The pin on the ESP that that the CS line is connected to. +- **reset_pin** (*Optional*, :ref:`Pin Schema `): The RESET pin. - **lambda** (*Optional*, :ref:`lambda `): The lambda to use for rendering the content on the display. See :ref:`display-engine` for more information. - **update_interval** (*Optional*, :ref:`config-time`): The interval to re-draw the screen. Defaults to ``5s``. diff --git a/components/display/st7735.rst b/components/display/st7735.rst index 7590e3017..2c5554ad5 100644 --- a/components/display/st7735.rst +++ b/components/display/st7735.rst @@ -6,7 +6,7 @@ ST7735 Display :keywords: ST7735 :image: ST7735.png -ST7735 Display Driver. +ST7735 Display Driver. Usage ----- @@ -32,7 +32,7 @@ There are numerous board types out there. Some initialize differently as well. T model: "INITR_18BLACKTAB" reset_pin: D4 cs_pin: D1 - dc_pin: D2 + dc_pin: D2 rotation: 0 devicewidth: 128 deviceheight: 160 @@ -42,28 +42,28 @@ There are numerous board types out there. Some initialize differently as well. T update_interval: 5s Configuration variables: -~~~~~~~~~~~~~~~~~~~~~~~~ +************************ - **model** (**Required**, "See Models Below"): This the model to use. INITR_BLACKTAB is the default -- **reset_pin** (:ref:`Pin Schema `): The RESET pin. -- **cs_pin** (:ref:`Pin Schema `): The CS pin. -- **dc_pin** (:ref:`Pin Schema `): The DC pin. -- **devicewidth** (**Required**, int): The device width. 128 is default -- **deviceheight** (**Required**, int): The device height. 160 is default -- **colstart** (**Required**, int): The device height. 160 is default -- **rowstart** (**Required**, int): The device height. 160 is default -- **eightbitcolor** (*Optional*, "True/False" ): 8bit mode. Default is False. This saves 50% of the buffer required for the display. +- **cs_pin** (**Required**, :ref:`Pin Schema `): The CS pin. +- **dc_pin** (**Required**, :ref:`Pin Schema `): The DC pin. +- **device_width** (**Required**, int): The device width. 128 is default +- **device_height** (**Required**, int): The device height. 160 is default +- **col_start** (**Required**, int): The device height. 160 is default +- **row_start** (**Required**, int): The device height. 160 is default +- **eight_bit_color** (*Optional*, "True/False" ): 8bit mode. Default is False. This saves 50% of the buffer required for the display. +- **reset_pin** (*Optional*, :ref:`Pin Schema `): The RESET pin. Memory notes: -~~~~~~~~~~~~~ +************* - 8Bit color saves 50% of the buffer required. - eightbitcolor: True 160x128 = 20480 *Important for memory constrained devices* -- eightbitcolor: False 160x128x2 = 40960 +- eightbitcolor: False 160x128x2 = 40960 Models: -~~~~~~~ +******* - INITR_GREENTAB - INITR_REDTAB diff --git a/components/display/st7789v.rst b/components/display/st7789v.rst index 224376e95..f6352148f 100644 --- a/components/display/st7789v.rst +++ b/components/display/st7789v.rst @@ -50,13 +50,13 @@ hardwired programming. (OTA updates are of course possible after ESPHome is init When using the TTGO T-Display module, the GPIO pin numbers above *cannot be changed* as they are hardwired within the module/PCB. -Configuration variables -*********************** +Configuration variables: +************************ -- **backlight_pin** (:ref:`Pin Schema `): The display's backlight pin. -- **cs_pin** (:ref:`Pin Schema `): The CS pin. -- **dc_pin** (:ref:`Pin Schema `): The DC pin. -- **reset_pin** (:ref:`Pin Schema `): The RESET pin. +- **backlight_pin** (**Required**, :ref:`Pin Schema `): The display's backlight pin. +- **cs_pin** (**Required**, :ref:`Pin Schema `): The CS pin. +- **dc_pin** (**Required**, :ref:`Pin Schema `): The DC pin. +- **reset_pin** (**Required**, :ref:`Pin Schema `): The RESET pin. - **lambda** (*Optional*, :ref:`lambda `): The lambda to use for rendering the content on the display. See :ref:`display-engine` for more information. - **update_interval** (*Optional*, :ref:`config-time`): The interval to re-draw the screen. Defaults to ``5s``. diff --git a/components/display/waveshare_epaper.rst b/components/display/waveshare_epaper.rst index d67e12821..bc5f632b3 100644 --- a/components/display/waveshare_epaper.rst +++ b/components/display/waveshare_epaper.rst @@ -8,7 +8,7 @@ Waveshare E-Paper Display The ``waveshare_epaper`` display platform allows you to use some E-Paper displays sold by `Waveshare `__ with ESPHome. The 2.13" `TTGO module `__ with an ESP32 on the board is supported as well. -Depending on your specific revision of the board you might need to try out the `-b73` version (see below). +Depending on your specific revision of the board you might need to try out the `-b73` or `-b1` version (see below). Similar modules sold by other vendors might also work but not have been tested yet. Currently only single-color E-Ink displays are implemented and of those only a few modules. @@ -75,6 +75,7 @@ Configuration variables: - ``2.13in`` (not tested) - ``2.13in-ttgo`` (T5_V2.3 tested) - ``2.13in-ttgo-b73`` (T5_V2.3 with B73 display tested) + - ``2.13in-ttgo-b1`` (T5_V2.3 with B1 display tested) - ``2.70in`` (currently not working with the HAT Rev 2.1 version) - ``2.90in`` - ``2.90inv2`` diff --git a/components/esp32_ble_tracker.rst b/components/esp32_ble_tracker.rst index 710bc43c6..c238c552b 100644 --- a/components/esp32_ble_tracker.rst +++ b/components/esp32_ble_tracker.rst @@ -154,7 +154,7 @@ variable ``x`` of type ``std::vector`` is passed to the automation for Configuration variables: - **mac_address** (*Optional*, MAC Address): The MAC address to filter for this automation. -- **manufacturer_id** (**Required**, string) 16 bit, 32 bit, or 128 bit BLE Manufacturer ID. +- **manufacturer_id** (**Required**, string): 16 bit, 32 bit, or 128 bit BLE Manufacturer ID. - See :ref:`Automation `. .. _esp32_ble_tracker-on_ble_service_data_advertise: @@ -182,7 +182,7 @@ variable ``x`` of type ``std::vector`` is passed to the automation for Configuration variables: - **mac_address** (*Optional*, MAC Address): The MAC address to filter for this automation. -- **service_uuid** (**Required**, string) 16 bit, 32 bit, or 128 bit BLE Service UUID. +- **service_uuid** (**Required**, string): 16 bit, 32 bit, or 128 bit BLE Service UUID. - See :ref:`Automation `. See Also diff --git a/components/esphome.rst b/components/esphome.rst index ca9f465c8..0247c7e3f 100644 --- a/components/esphome.rst +++ b/components/esphome.rst @@ -49,6 +49,9 @@ Advanced options: - **libraries** (*Optional*, list of libraries): A list of `platformio libraries `__ to include in the project. See `platformio lib install `__. - **comment** (*Optional*, string): Additional text information about this node. Only for display in UI. +- **name_add_mac_suffix** (*Optional*, boolean): Appends the last 6 bytes of the mac address of the device to + the name in the form `_aabbcc`. Defaults to ``False``. + See :ref:`esphome-mac_suffix`. ESP8266 Options: @@ -297,6 +300,17 @@ Now upload the updated config to the device. As a second step, you now need to r The same procedure can be done for changing the static IP of a device. + +.. _esphome-mac_suffix: + +Adding the MAC address as a suffix to the device name +----------------------------------------------------- + +Using ``name_add_mac_suffix`` allows the user to compile a single binary file to flash +many of the same device and they will all have unique names/hostnames. +Note that you will still need to create an individual YAML config file if you want to +OTA update the devices in the future. + See Also -------- diff --git a/components/ethernet.rst b/components/ethernet.rst index 4ba201415..0d6b68bdf 100644 --- a/components/ethernet.rst +++ b/components/ethernet.rst @@ -48,9 +48,9 @@ Configuration variables: - **manual_ip** (*Optional*): Manually configure the static IP of the node. - - **static_ip** (*Required*, IPv4 address): The static IP of your node. - - **gateway** (*Required*, IPv4 address): The gateway of the local network. - - **subnet** (*Required*, IPv4 address): The subnet of the local network. + - **static_ip** (**Required**, IPv4 address): The static IP of your node. + - **gateway** (**Required**, IPv4 address): The gateway of the local network. + - **subnet** (**Required**, IPv4 address): The subnet of the local network. - **dns1** (*Optional*, IPv4 address): The main DNS server to use. - **dns2** (*Optional*, IPv4 address): The backup DNS server to use. @@ -63,10 +63,10 @@ Configuration variables: .. note:: If your ethernet board is not designed with an ESP32 built in, chances are that you are going - to use flying leads, dupont wires, etc. to connect the ethernet to the ESP32. This is - probably to fail as the ethernet interface uses a high frequency clock signal. For more + to use flying leads, dupont wires, etc. to connect the ethernet to the ESP32. This is + probably to fail as the ethernet interface uses a high frequency clock signal. For more information and wiring details refer to the the link in the *See also* section. - + Configuration for wESP32 board ------------------------------ @@ -114,7 +114,7 @@ Configuration for OpenHacks LAN8720 mdc_pin: GPIO23 mdio_pin: GPIO18 phy_addr: 1 - + Note: This board has an issue that might cause the ESP32 to boot in program mode. When testing, make sure you are monitoring the serial output and reboot the device several times to see if it boots into the program properly. diff --git a/components/fan/images/fan-ui.png b/components/fan/images/fan-ui.png index 01621d4d2..b25feffd8 100644 Binary files a/components/fan/images/fan-ui.png and b/components/fan/images/fan-ui.png differ diff --git a/components/fan/index.rst b/components/fan/index.rst index 42435ea03..478e9d616 100644 --- a/components/fan/index.rst +++ b/components/fan/index.rst @@ -7,14 +7,13 @@ Fan Component With the ``fan`` domain you can create components that appear as fans in the Home Assistant frontend. A fan can be switched ON or OFF, optionally -has a speed setting (``LOW``, ``MEDIUM``, ``HIGH``) and can have an -oscillate output. +has a speed level between 1 and the maximum supported speed level of the fan, and can have an +oscillate and direction output. This component restores its state on reboot/reset. .. figure:: images/fan-ui.png :align: center - :width: 70.0% .. _config-fan: @@ -93,9 +92,8 @@ Configuration options: - **id** (**Required**, :ref:`config-id`): The ID of the fan. - **oscillating** (*Optional*, boolean, :ref:`templatable `): Set the oscillation state of the fan. Defaults to not affecting oscillation. -- **speed** (*Optional*, string, :ref:`templatable `): - Set the speed setting of the fan. One of ``OFF``, ``LOW``, ``MEDIUM``, ``HIGH``. - If you template this value, return ``FAN_SPEED_...``, for example ``FAN_SPEED_HIGH``. +- **speed** (*Optional*, int, :ref:`templatable `): + Set the speed level of the fan. Can be a number between 1 and the maximum speed level of the fan. Full Fan Index -------------- diff --git a/components/fan/speed.rst b/components/fan/speed.rst index 03c4c790c..b9080022d 100644 --- a/components/fan/speed.rst +++ b/components/fan/speed.rst @@ -30,15 +30,9 @@ Configuration variables: :ref:`output ` to use for the oscillation state of this fan. Default is empty. - **direction_output** (*Optional*, :ref:`config-id`): The id of the :ref:`output ` to use for the direction state of the fan. Default is empty. -- **speed** (*Optional*): Set the float values for each speed setting: - - - **low** (*Required*, float): Set the value for the low speed - setting. Must be in range 0 to 1. Defaults to 0.33. - - **medium** (*Required*, float): Set the value for the medium speed - setting. Must be in range 0 to 1. Defaults to 0.66. - - **high** (*Required*, float): Set the value for the high speed - setting. Must be in range 0 to 1. Defaults to 1. - +- **speed_count** (*Optional*, int): Set the number of supported discrete speed levels. The value is used + to calculate the percentages for each speed. E.g. ``2`` means that you have 50% and 100% while ``100`` + will allow 1% increments in the output. Defaults to ``100``. - **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation. - All other options from :ref:`Fan Component `. diff --git a/components/fan/tuya.rst b/components/fan/tuya.rst index 65bb611ae..8fb4e8299 100644 --- a/components/fan/tuya.rst +++ b/components/fan/tuya.rst @@ -53,7 +53,7 @@ Configuration variables: - **name** (**Required**, string): The name of the fan. - **speed_datapoint** (**Required**, int): The datapoint id number of the fan speed. - **switch_datapoint** (**Required**, int): The datapoint id number of the fan switch. -- **oscillation_datapoint** (**Optional**, int): The datapoint id number of the oscillation +- **oscillation_datapoint** (*Optional*, int): The datapoint id number of the oscillation switch. Probably not supported on any Tuya controllers currently, but it's there if need be. - All other options from :ref:`Fan `. diff --git a/components/gps.rst b/components/gps.rst index 4aeda2ee4..6207e3ac5 100644 --- a/components/gps.rst +++ b/components/gps.rst @@ -33,10 +33,7 @@ in your configuration - only the RX pin should be necessary. time: - platform: gps -Configuration variables: ------------------------- - -The component is split up in platforms. +The component is split up in platforms. No configuration variables. First you need to define a global GPS module hub (as seen above). diff --git a/components/http_request.rst b/components/http_request.rst index a11d384d8..b9da808c1 100644 --- a/components/http_request.rst +++ b/components/http_request.rst @@ -49,6 +49,12 @@ This :ref:`action ` sends a GET request. headers: Content-Type: application/json verify_ssl: false + on_response: + then: + - logger.log: + format: 'Response status: %d' + args: + - status_code # Short form - http_request.get: https://esphome.io @@ -57,6 +63,7 @@ Configuration variables: - **url** (**Required**, string, :ref:`templatable `): URL to send request. - **headers** (*Optional*, mapping): Map of HTTP headers. Values are :ref:`templatable `. - **verify_ssl** (*Optional*, boolean): Verify the SSL certificate of the endpoint. Defaults to ``true``. +- **on_response** (*Optional*, :ref:`Automation `): An automation to perform when the request is finished. .. note:: @@ -112,6 +119,29 @@ Configuration variables: - **method** (**Required**, string): HTTP method to use (``GET``, ``POST``, ``PUT``, ``DELETE``, ``PATCH``). - All other options from :ref:`http_request-post_action`. +.. _http_request-on_response: + +``on_response`` Trigger +----------------------- + +This automation will be triggered when the HTTP request is finished and will supply the +http response code in parameter ``status_code`` as an ``int``. + +.. code-block:: yaml + + on_... + then: + - http_request.get: + url: https://esphome.io + verify_ssl: false + on_response: + then: + - logger.log: + format: "Response status: %d" + args: + - status_code + + .. _http_request-examples: Examples diff --git a/components/i2c.rst b/components/i2c.rst index f5e3181e6..3fa859ad5 100644 --- a/components/i2c.rst +++ b/components/i2c.rst @@ -11,9 +11,9 @@ I²C Bus This component sets up the I²C bus for your ESP32 or ESP8266. In order for these components to work correctly, you need to define the I²C bus in your configuration. Please note the ESP will enable its internal 10kΩ pullup resistors for these pins, so you usually don't need to -put on external ones. You can use multiple devices on one I²C bus as each device is given a -unique address for communicating between between it and the ESP. You can do this by hopping -wires from the two lines (SDA and SCL) from each device board to the next device board or by +put on external ones. You can use multiple devices on one I²C bus as each device is given a +unique address for communicating between between it and the ESP. You can do this by hopping +wires from the two lines (SDA and SCL) from each device board to the next device board or by connecting the wires from each device back to the two I²C pins on the ESP. .. code-block:: yaml @@ -37,7 +37,7 @@ Configuration variables: Defaults to ``True``. - **frequency** (*Optional*, float): Set the frequency the I²C bus should operate on. Defaults to ``50kHz``. Values are ``50kHz``, ``100kHz``, ``200kHz``, ... ``800kHz`` -- **id** (*Optional*, :ref:`config-id`) Manually specify the ID for this I²C bus if you need multiple I²C buses. +- **id** (*Optional*, :ref:`config-id`): Manually specify the ID for this I²C bus if you need multiple I²C buses. .. note:: diff --git a/components/light/index.rst b/components/light/index.rst index fdc98cda4..5f0eadd68 100644 --- a/components/light/index.rst +++ b/components/light/index.rst @@ -77,7 +77,7 @@ This action toggles a light with the given ID when executed. # Shorthand: - light.toggle: light_1 -Configuration options: +Configuration variables: - **id** (**Required**, :ref:`config-id`): The ID of the light. - **transition_length** (*Optional*, :ref:`config-time`, :ref:`templatable `): The length of the transition @@ -121,7 +121,7 @@ This action turns a light with the given ID on when executed. # Shorthand - light.turn_on: light_1 -Configuration options: +Configuration variables: - **id** (**Required**, :ref:`config-id`): The ID of the light. - **transition_length** (*Optional*, :ref:`config-time`, :ref:`templatable `): The length of the transition @@ -180,7 +180,7 @@ This action turns a light with the given ID off when executed. # Shorthand - light.turn_off: light_1 -Configuration options: +Configuration variables: - **id** (**Required**, :ref:`config-id`): The ID of the light. - **transition_length** (*Optional*, :ref:`config-time`, :ref:`templatable `): The length of the transition @@ -214,7 +214,7 @@ is essentially just a combination of the turn_on and turn_off calls. id: light_1 state: on -Configuration options: +Configuration variables: - **id** (**Required**, :ref:`config-id`): The ID of the light. - **state** (*Optional*, :ref:`templatable `, boolean): Change the ON/OFF @@ -238,10 +238,10 @@ by a relative amount. id: light_1 relative_brightness: 5% -Configuration options: +Configuration variables: - **id** (**Required**, :ref:`config-id`): The ID of the light. -- **relative_brightness** (**Required***, :ref:`templatable `, percentage): +- **relative_brightness** (**Required**, :ref:`templatable `, percentage): The relative brightness to dim the light by. - **transition_length** (*Optional*, :ref:`config-time`, :ref:`templatable `): The length of the transition. @@ -718,8 +718,12 @@ This effect allows you to access each LED individually in a custom light effect. Available variables in the lambda: - **it** - :apiclass:`AddressableLight ` instance (see API reference for more info). -- **current_color** - :apistruct:`ESPColor ` instance (see API reference for more info). -- **initial_run** - A bool which is true on the first execution of the lambda. Useful to reset static variables when restarting an effect. +- **current_color** - :apistruct:`Color ` instance (see API reference for more info). +- **initial_run** - A bool which is true on the first execution of the lambda. Useful to reset static variables when restarting a effect. + + .. note:: + + ESPColor has been migrated to Color. See :apistruct:`Color ` for more information. .. code-block:: yaml @@ -733,18 +737,18 @@ Available variables in the lambda: // it.size() - Number of LEDs // it[num] - Access the LED at index num. // Set the LED at num to the given r, g, b values - // it[num] = ESPColor(r, g, b); - // Get the color at index num (ESPColor instance) + // it[num] = Color(r, g, b); + // Get the color at index num (Color instance) // it[num].get(); // Example: Simple color wipe for (int i = it.size() - 1; i > 0; i--) { it[i] = it[i - 1].get(); } - it[0] = ESPColor::random_color(); + it[0] = Color::random_color(); // Bonus: use .range() and .all() to set many LEDs without having to write a loop. - it.range(0, 50) = ESPColor::BLACK; + it.range(0, 50) = Color::BLACK; it.all().fade_to_black(10); .. code-block:: yaml @@ -768,7 +772,7 @@ Available variables in the lambda: // again you can use the initial_run variables if (initial_run) { progress = 0; - it.all() = ESPColor::BLACK; + it.all() = Color::BLACK; // optionally do a return so nothing happens until the next update_interval return; } @@ -817,8 +821,10 @@ Configuration variables: - **sequence** (*Optional*, :ref:`Action `): The actions to perform in sequence until the effect is stopped. -E1.31 -***** +.. _e131-light-effect: + +E1.31 Effect +************ This effect enables controlling addressable lights using UDP-based E1.31_ protocol. @@ -840,16 +846,15 @@ For Example JINX_ or Hyperion.NG_ could be used to control E1.31_ enabled ESPHom Configuration variables: -- **method** (*Optional*): Listening method, one of ``multicast`` or ``unicast``. Defaults to ``multicast``. -- **universe** (*Required*, integer): The value of universe, between 1 to 512. +- **universe** (**Required**, integer): The value of universe, between 1 to 512. - **channels** (*Optional*): The type of data. This is used to specify if it is a ``MONO``, ``RGB`` or ``RGBW`` light and in which order the colors are. Defaults to ``RGB``. There are three modes of operation: -- `MONO`: this supports 1 channel per LED (luminance), up-to 512 LEDs per universe -- `RGB`: this supports 3 channels per LED (RGB), up-to 170 LEDs (3*170 = 510 bytes) per universe -- `RGBW`: this supports 4 channels per LED (RGBW), up-to 128 LEDs (4*128 = 512 bytes) per universe +- ``MONO``: this supports 1 channel per LED (luminance), up-to 512 LEDs per universe +- ``RGB``: this supports 3 channels per LED (RGB), up-to 170 LEDs (3*170 = 510 bytes) per universe +- ``RGBW``: this supports 4 channels per LED (RGBW), up-to 128 LEDs (4*128 = 512 bytes) per universe If there's more LEDs than allowed per-universe, additional universe will be used. In the above example of 189 LEDs, first 170 LEDs will be assigned to 1 universe, @@ -858,14 +863,22 @@ the rest of 19 LEDs will be automatically assigned to 2 universe. It is possible to enable multiple light platforms to listen to the same universe concurrently, allowing to replicate the behaviour on multiple strips. -The udp port esphome is listenig on is 5568. +E1.31 Component +^^^^^^^^^^^^^^^ + +The :ref:`e131-light-effect` requires a component hub for the ``e131`` light effect. + +Configuration variables: + +- **method** (*Optional*): Listening method, one of ``multicast`` or ``unicast``. Defaults to ``multicast``. + .. _E1.31: https://www.doityourselfchristmas.com/wiki/index.php?title=E1.31_(Streaming-ACN)_Protocol .. _JINX: http://www.live-leds.de/jinx-v1-3-with-resizable-mainwindow-real-dmx-and-sacne1-31/ .. _Hyperion.NG: https://github.com/hyperion-project/hyperion.ng -Adalight -******** +Adalight Effect +*************** This effect enables controlling addressable lights using UART-based Adalight_ protocol, allowing to create realtime ambient lighting effects. @@ -902,8 +915,8 @@ Configuration variables: .. _Adalight: https://learn.adafruit.com/adalight-diy-ambient-tv-lighting .. _Prismatik: https://github.com/psieg/Lightpack -WLED -**** +WLED Effect +*********** This effect enables controlling addressable lights using UDP-based `UDP Realtime Control`_ protocol used by WLED_, allowing to create realtime ambient diff --git a/components/logger.rst b/components/logger.rst index e559c9c82..565f55d6a 100644 --- a/components/logger.rst +++ b/components/logger.rst @@ -37,6 +37,9 @@ Advanced settings: Defaults to ``UART0``. - **esp8266_store_log_strings_in_flash** (*Optional*, boolean): If set to false, disables storing log strings in the flash section of the device (uses more memory). Defaults to true. +- **on_message** (*Optional*, :ref:`Automation `): An action to be + performed when a message is to be looged. The vairables ``int level``, ``const char* tag`` and + ``const char* message`` are available for lambda processing. .. _logger-hardware_uarts: diff --git a/components/mcp230xx.rst b/components/mcp230xx.rst index 07a34c44e..6bff7d85c 100644 --- a/components/mcp230xx.rst +++ b/components/mcp230xx.rst @@ -15,8 +15,8 @@ The Microchip MCP230xx series of general purpose, parallel I/O expansion for I² .. _mcp23008-label: -MCP23008 --------- +MCP23008 Component +------------------ The MCP23008 component (`datasheet `__, `Adafruit `__) has 8 GPIOs that can be configured independently. @@ -33,7 +33,7 @@ The MCP23008 component (`datasheet `__) has 16 GPIOs and can be configured the same way than the other variants. @@ -104,16 +114,23 @@ has 16 GPIOs and can be configured the same way than the other variants. Configuration variables: -~~~~~~~~~~~~~~~~~~~~~~~~ +************************ - **id** (**Required**, :ref:`config-id`): The id to use for this MCP23016 component. - **address** (*Optional*, int): The I²C address of the driver. Defaults to ``0x20``. +Pin configuration variables: +**************************** + +- **mcp23xxx** (**Required**, :ref:`config-id`): The id of the MCP23016 component. +- All other options from :ref:`Pin Schema ` + + .. _mcp23017-label: -MCP23017 --------- +MCP23017 Component +------------------ The MCP23017 component allows you to use MCP23017 I/O expanders (`datasheet `__, @@ -137,7 +154,7 @@ binary sensor or GPIO switch. - platform: gpio name: "MCP23017 Pin #0" pin: - mcp23017: mcp23017_hub + mcp23xxx: mcp23017_hub # Use pin number 0 number: 0 mode: OUTPUT @@ -148,7 +165,7 @@ binary sensor or GPIO switch. - platform: gpio name: "MCP23017 Pin #1" pin: - mcp23017: mcp23017_hub + mcp23xxx: mcp23017_hub # Use pin number 1 number: 1 # One of INPUT or INPUT_PULLUP @@ -156,7 +173,7 @@ binary sensor or GPIO switch. inverted: False Configuration variables: -~~~~~~~~~~~~~~~~~~~~~~~~ +************************ - **id** (**Required**, :ref:`config-id`): The id to use for this MCP23017 component. - **address** (*Optional*, int): The I²C address of the driver. @@ -165,6 +182,13 @@ Configuration variables: Useful when the MCP23017's power supply is greater than 3.3 volts. Note that these pins will require pull-up resistors (to 3.3 volts) when this mode is enabled. +Pin configuration variables: +**************************** + +- **mcp23xxx** (**Required**, :ref:`config-id`): The id of the MCP23017 component. +- **interrupt** (*Optional*): Set this pin to trigger the port INT pin on the component. Can be one of ``CHANGE``, ``RISING``, ``FALLING``. +- All other options from :ref:`Pin Schema ` + See Also -------- diff --git a/components/mcp23Sxx.rst b/components/mcp23Sxx.rst index 39d6a146e..2b6f26a92 100644 --- a/components/mcp23Sxx.rst +++ b/components/mcp23Sxx.rst @@ -15,8 +15,8 @@ This is exactly the same API as the MCP23SXX I/O Expander except talks on the SP .. _mcp23S08-label: -MCP23S08 --------- +MCP23S08 Component +------------------ The MCP23S08 component (`datasheet `__, `Digi-Key `__) has 8 GPIOs that can be configured independently. @@ -34,7 +34,7 @@ The MCP23S08 component (`datasheet ` .. _mcp23S17-label: -MCP23S17 --------- +MCP23S17 Component +------------------ The MCP23S17 component allows you to use MCP23S17 I/O expanders (`datasheet `__, @@ -90,7 +100,7 @@ binary sensor or GPIO switch. - platform: gpio name: "MCP23S17 Pin #0" pin: - mcp23s17: mcp23s17_hub + mcp23xxx: mcp23s17_hub # Use pin number 0 number: 0 mode: OUTPUT @@ -101,7 +111,7 @@ binary sensor or GPIO switch. - platform: gpio name: "MCP23S17 Pin #1" pin: - mcp23s17: mcp23s17_hub + mcp23xxx: mcp23s17_hub # Use pin number 1 number: 1 # One of INPUT or INPUT_PULLUP @@ -109,12 +119,22 @@ binary sensor or GPIO switch. inverted: False Configuration variables: -~~~~~~~~~~~~~~~~~~~~~~~~ +************************ - **id** (**Required**, :ref:`config-id`): The id to use for this MCP23S17 component. -- **cs_pin** (*Required*, int): The SPI chip select pin to use. +- **cs_pin** (**Required**, int): The SPI chip select pin to use. - **deviceaddress** (*Optional*, int): The address of the chip. Defaults to ``0``. +- **open_drain_interrupt** (*Optional*, bool): Configure interrupt pins to open-drain mode. + Useful when the MCP23S17's power supply is greater than 3.3 volts. Note that these pins + will require pull-up resistors (to 3.3 volts) when this mode is enabled. + +Pin Configuration Variables: +**************************** + +- **mcp23xxx** (**Required**, :ref:`config-id`): The id of the MCP23S17 component. +- **interrupt** (*Optional*): Set this pin to trigger the port INT pin on the component. Can be one of ``CHANGE``, ``RISING``, ``FALLING``. +- All other options from :ref:`Pin Schema ` See Also diff --git a/components/mqtt.rst b/components/mqtt.rst index 75d229a06..3f00b66e4 100644 --- a/components/mqtt.rst +++ b/components/mqtt.rst @@ -48,7 +48,7 @@ Configuration variables: - **topic_prefix** (*Optional*, string): The prefix used for all MQTT messages. Should not contain trailing slash. Defaults to ````. -- **log_topic** (*Optional*, :ref:`mqtt-message`) The topic to send MQTT log +- **log_topic** (*Optional*, :ref:`mqtt-message`): The topic to send MQTT log messages to. - **birth_message** (*Optional*, :ref:`mqtt-message`): The message to send when a connection to the broker is established. See :ref:`mqtt-last_will_birth` for more information. @@ -440,9 +440,9 @@ Publish an MQTT message on a topic using this action in automations. Configuration options: -- **topic** (*Required*, string, :ref:`templatable `): +- **topic** (**Required**, string, :ref:`templatable `): The MQTT topic to publish the message. -- **payload** (*Required*, string, :ref:`templatable `): The message content. +- **payload** (**Required**, string, :ref:`templatable `): The message content. - **qos** (*Optional*, int, :ref:`templatable `): The `Quality of Service `__ level of the topic. Defaults to 0. @@ -491,9 +491,9 @@ as seen below. Configuration options: -- **topic** (*Required*, string, :ref:`templatable `): +- **topic** (**Required**, string, :ref:`templatable `): The MQTT topic to publish the message. -- **payload** (*Required*, :ref:`lambda `): The message content. +- **payload** (**Required**, :ref:`lambda `): The message content. - **qos** (*Optional*, int): The `Quality of Service `__ level of the topic. Defaults to 0. diff --git a/components/output/index.rst b/components/output/index.rst index 60c05b8db..5eb6e272a 100644 --- a/components/output/index.rst +++ b/components/output/index.rst @@ -39,12 +39,13 @@ Configuration variables: automatically be switched on too. - **inverted** (*Optional*, boolean): If the output should be treated as inverted. Defaults to ``False``. -- **min_power** (*Optional*, float): Only for float outputs. Sets the - minimum output value of this output platform. - Must be in range from 0 to max_power. Defaults to 0. -- **max_power** (*Optional*, float): Only for float outputs. Sets the - maximum output value of this output platform. - Must be in range from min_power to 1. Defaults to 1. + +Float outputs only: + +- **min_power** (*Optional*, float): Sets the minimum output value of this output platform. + Must be in range from 0 to max_power. Defaults to ``0``. +- **max_power** (*Optional*, float): Sets the maximum output value of this output platform. + Must be in range from min_power to 1. Defaults to ``1``. .. _output-turn_on_action: diff --git a/components/output/mcp4725.rst b/components/output/mcp4725.rst new file mode 100644 index 000000000..ea4ff9d48 --- /dev/null +++ b/components/output/mcp4725.rst @@ -0,0 +1,57 @@ +MCP4725 Output +============== + +.. seo:: + :description: Instructions for setting up MCP4725 outputs on the ESP. + :image: mcp4725.png + +The MCP4725 output component allows to use `12bit external DAC +`__ +in order to have analog output(s) on any board by using I2C. Devices default address is ``0x60`` +and configurable alternative is ``0x61``. + +.. code-block:: yaml + + # Example configuration entry + + # Set a global i2c connection + i2c: + sda: 21 + scl: 22 + scan: True + + # Set the output with default (address: 0x60 / global i2c) + output: + - platform: mcp4725 + id: dac_output + + on_...: + then: + - output.set_level: + id: dac_output + level: 100% + + +Configuration variables: +------------------------ + +- **id** (**Required**, :ref:`config-id`): The id to use for this output component. +- **address** (*Optional*, int): Manually specify the I2C address of + the DAC. Defaults to ``0x60``. +- All other options from :ref:`Output `. + +Usage with voltages higher than 3.3v +------------------------------------ + +In order to drive analog modules with voltages higher than 3.3v, use a `TTL bi-directionnal level +converter `__ + +Be careful about what converter you use, some of of them have channels labeled with `RX` and `TX`, +in this case only `TX` channels are bi-directional (so you must use 2 `TX` channels for I2C to work). + +See Also +-------- + +- :doc:`/components/output/esp32_dac` +- :doc:`/components/output/esp8266_pwm` +- :ghedit:`Edit` diff --git a/components/output/my9231.rst b/components/output/my9231.rst index e15b1b91e..568d572e4 100644 --- a/components/output/my9231.rst +++ b/components/output/my9231.rst @@ -8,8 +8,8 @@ MY9231/MY9291 LED driver .. _my9231-component: -Component ---------- +Component/Hub +------------- The MY9231/MY9291 component represents a MY9231/MY9291 LED diver chain (`MY9231 description `__, @@ -57,6 +57,40 @@ Configuration variables: this ``my9231`` component. Use this if you have multiple MY9231/MY9291 chains connected at the same time. + +.. _my9231-output: + +Output +------ + +The MY931/MY9291 output component exposes a MY931/MY9291 channel of a global +:ref:`my9231-component` as a float output. + +.. code-block:: yaml + + # Example configuration entry + my9231: + - data_pin: GPIO12 + clock_pin: GPIO14 + + # Individual outputs + output: + - platform: my9231 + id: 'my9231_output1' + channel: 0 + +Configuration variables: +************************ + +- **id** (**Required**, :ref:`config-id`): The id to use for this output component. +- **channel** (**Required**, int): Chose the channel of the MY9231/MY9291 chain of + this output component. Channel 0 is the most close channel. +- **my9231_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the + :ref:`my9231-component`. + Use this if you have multiple MY9231/MY9291 chains you want to use at the same time. +- All other options from :ref:`Output `. + + Sonoff B1 configuration example ------------------------------- @@ -172,38 +206,6 @@ And here is a complete configuration for the AiThinker AiLight: white: output_cold_white -.. _my9231-output: - -Driver Output -------------- - -The MY931/MY9291 output component exposes a MY931/MY9291 channel of a global -:ref:`my9231-component` as a float output. - -.. code-block:: yaml - - # Example configuration entry - my9231: - - data_pin: GPIO12 - clock_pin: GPIO14 - - # Individual outputs - output: - - platform: my9231 - id: 'my9231_output1' - channel: 0 - -Configuration variables: -************************ - -- **id** (**Required**, :ref:`config-id`): The id to use for this output component. -- **channel** (**Required**, int): Chose the channel of the MY9231/MY9291 chain of - this output component. Channel 0 is the most close channel. -- **my9231_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the - :ref:`my9231-component`. - Use this if you have multiple MY9231/MY9291 chains you want to use at the same time. -- All other options from :ref:`Output `. - See Also -------- diff --git a/components/output/sm16716.rst b/components/output/sm16716.rst index 4b2a2df22..88b2d22ff 100644 --- a/components/output/sm16716.rst +++ b/components/output/sm16716.rst @@ -8,8 +8,8 @@ SM16716 LED driver .. _sm16716-component: -Component ---------- +Component/Hub +------------- The SM16716 component represents a SM16716 LED diver chain (`SM16716 description `__, @@ -61,8 +61,8 @@ Configuration variables: .. _sm16716-output: -Driver Output -------------- +Output +------ The SM16716 output component exposes a SM16716 channel of a global :ref:`sm16716-component` as a float output. diff --git a/components/output/template.rst b/components/output/template.rst index d2905087b..5edda1d9c 100644 --- a/components/output/template.rst +++ b/components/output/template.rst @@ -38,8 +38,8 @@ Configuration variables: - **id** (**Required**, :ref:`config-id`): The id to use for this output component. - **type** (**Required**, string): The type of output. One of ``binary`` and ``float``. -- **on_write_action** (*Required*, :ref:`Action `): The action that should - be performed when the state of the output is updated. +- **write_action** (**Required**, :ref:`Automation `): An automation to perform + when the state of the output is updated. - All other options from :ref:`Output `. See :apiclass:`output::BinaryOutput` and :apiclass:`output::FloatOutput`. @@ -51,13 +51,13 @@ See :apiclass:`output::BinaryOutput` and :apiclass:`output::FloatOutput`. .. _output-template-on_write_action: -``output.template.on_write`` Action ------------------------------------ +``write_action`` Trigger +------------------------ -When the state for this output is updated, the on_write action is executed. +When the state for this output is updated, the ``write_action`` is triggered. It is possible to access the state value inside Lambdas: -.. code-block:: yaml +.. code-block:: yaml - platform: template id: my_output diff --git a/components/pcf8574.rst b/components/pcf8574.rst index 199455c22..f4a94b42b 100644 --- a/components/pcf8574.rst +++ b/components/pcf8574.rst @@ -47,13 +47,24 @@ not work. inverted: False Configuration variables: -~~~~~~~~~~~~~~~~~~~~~~~~ +************************ - **id** (**Required**, :ref:`config-id`): The id to use for this PCF8574 component. - **address** (*Optional*, int): The I²C address of the driver. Defaults to ``0x21``. - **pcf8575** (*Optional*, boolean): Whether this is a 16-pin PCF8575. Defaults to ``False``. + +Pin configuration variables: +**************************** + +- **pcf8574** (**Required**, :ref:`config-id`): The id of the PCF8574 component of the pin. +- **number** (**Required**, integer): The pin number. +- **inverted** (*Optional*, boolean): If all read and written values + should be treated as inverted. Defaults to ``False``. +- **mode** (*Optional*, string): A pin mode to set for the pin at. One of ``INPUT`` or ``OUTPUT``. + + See Also -------- diff --git a/components/remote_receiver.rst b/components/remote_receiver.rst index 639f943eb..b075a37a7 100644 --- a/components/remote_receiver.rst +++ b/components/remote_receiver.rst @@ -36,6 +36,7 @@ Configuration variables: - **pioneer**: Decode and dump Pioneer infrared codes. - **jvc**: Decode and dump JVC infrared codes. - **samsung**: Decode and dump Samsung infrared codes. + - **samsung36**: Decode and dump Samsung36 infrared codes. - **sony**: Decode and dump Sony infrared codes. - **rc_switch**: Decode and dump RCSwitch RF codes. - **rc5**: Decode and dump RC5 IR codes. @@ -80,6 +81,9 @@ Automations: - **on_samsung** (*Optional*, :ref:`Automation `): An automation to perform when a Samsung remote code has been decoded. A variable ``x`` of type :apiclass:`remote_base::SamsungData` is passed to the automation for use in lambdas. +- **on_samsung36** (*Optional*, :ref:`Automation `): An automation to perform when a + Samsung36 remote code has been decoded. A variable ``x`` of type :apiclass:`remote_base::Samsung36Data` + is passed to the automation for use in lambdas. - **on_panasonic** (*Optional*, :ref:`Automation `): An automation to perform when a Panasonic remote code has been decoded. A variable ``x`` of type :apiclass:`remote_base::PanasonicData` is passed to the automation for use in lambdas. @@ -153,6 +157,11 @@ Remote code selection (exactly one of these has to be included): - **data** (**Required**, int): The data to trigger on, see dumper output for more info. +- **samsung36**: Trigger on a decoded Samsung36 remote code with the given data. + + - **address** (**Required**, int): The address to trigger on, see dumper output for more info. + - **command** (**Required**, int): The command. + - **panasonic**: Trigger on a decoded Panasonic remote code with the given data. - **address** (**Required**, int): The address to trigger on, see dumper output for more info. @@ -211,10 +220,10 @@ Remote code selection (exactly one of these has to be included): remote_transmitter: pin: 5 carrier_duty_percent: 100% - + .. note:: - To caputure the codes more effectively with directly connected receiver like tsop38238 you can try to use `INPUT_PULLUP`: + To caputure the codes more effectively with directly connected receiver like tsop38238 you can try to use ``INPUT_PULLUP``: .. code-block:: yaml diff --git a/components/remote_transmitter.rst b/components/remote_transmitter.rst index a2334fcb9..73d18d840 100644 --- a/components/remote_transmitter.rst +++ b/components/remote_transmitter.rst @@ -78,6 +78,9 @@ Configuration variables: If you're looking for the same functionality as is default in the ``rpi_rf`` integration in Home Assistant, you'll want to set the **times** to 10 and the **wait_time** to 0s. +If you're looking for the same functionality as is default in the ``rpi_rf`` integration in +Home Assistant, you'll want to set the **times** to 10 and the **wait_time** to 0s. + .. _remote_transmitter-transmit_raw: ``remote_transmitter.transmit_raw`` Action @@ -209,6 +212,24 @@ Configuration variables: - **data** (**Required**, int): The data to send, see dumper output for more details. - All other options from :ref:`remote_transmitter-transmit_action`. +``remote_transmitter.transmit_samsung36`` Action +************************************************ + +This :ref:`action ` sends a Samsung36 infrared remote code to a remote transmitter. + +.. code-block:: yaml + + on_...: + - remote_transmitter.transmit_samsung36: + address: 0x0400 + command: 0x000E00FF + +Configuration variables: + +- **address** (**Required**, int): The address to send, see dumper output for more details. +- **command** (**Required**, int): The Samsung36 command to send, see dumper output for more details. +- All other options from :ref:`remote_transmitter-transmit_action`. + ``remote_transmitter.transmit_panasonic`` Action ************************************************ @@ -244,7 +265,7 @@ This :ref:`action ` sends a Pioneer infrared remote code to a rem Configuration variables: - **rc_code_1** (**Required**, int): The remote control code to send, see dumper output for more details. -- **rc_code_2** (**Optional**, int): The secondary remote control code to send; some codes are sent in +- **rc_code_2** (*Optional*, int): The secondary remote control code to send; some codes are sent in two parts. - Note that ``repeat`` is still optional, however **Pioneer devices may require that a given code is received multiple times before they will act on it.** Add this if your device does not respond to diff --git a/components/sensor/apds9960.rst b/components/sensor/apds9960.rst index dd0885858..0a2004a2a 100644 --- a/components/sensor/apds9960.rst +++ b/components/sensor/apds9960.rst @@ -5,6 +5,12 @@ APDS9960 Sensor :description: Instructions for setting up APDS9960 sensors. :image: apds9960.jpg + +.. _apds9960-component: + +Component/Hub +------------- + The ``apds9960`` sensor platform allows you to use your APDS9960 RGB and gesture sensors (`datasheet `__, `SparkFun`_) with ESPHome. @@ -49,7 +55,13 @@ Base Configuration: - **update_interval** (*Optional*, :ref:`config-time`): The interval to check the sensor. Defaults to ``60s``. -Sensor Configuration: +Sensor +------ + +The ``apds9960`` sensor allows you to use your :doc:`apds9960` to perform different +measurements. + +Configuration variables: - **name** (**Required**, string): The name for the sensor. - **type** (**Required**, string): The type of sensor measurement. One of @@ -63,7 +75,13 @@ Sensor Configuration: - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. - All other options from :ref:`Sensor `. -Binary Sensor Configuration: +Binary Sensor +------------- + +The ``apds9960`` binary sensor allows you to use your :doc:`apds9960` to perform different +measurements. + +Configuration variables: - **name** (**Required**, string): The name for the binary sensor. - **direction** (**Required**, string): The direction to measure. One of: diff --git a/components/sensor/as3935.rst b/components/sensor/as3935.rst index 7d7224a1c..0c1a7fc87 100644 --- a/components/sensor/as3935.rst +++ b/components/sensor/as3935.rst @@ -6,7 +6,7 @@ AMS AS3935 Franklin Lightning Sensor :image: images/as3935.jpg :keywords: as3935 -The ``as3935`` sensor platform allows you to use your AS3935 sensor +The **AS3935** sensor platform allows you to use your AS3935 sensor (`AliExpress`_, `AMS_AS3935`_) in order to get notified when a thunderstorm is getting close. @@ -14,6 +14,9 @@ The AS3935 can detect the presence of lightning activity and provide an estimati on the distance to the head of the storm. The chip issues a notification through an interrupt pin. +Component/Hub +------------- + The AS3935 can be configured to use either the SPI **or** I²C protocol for data communication. First choose which communication method you want to use for the sensor, set the SI pin for the appropriate level and set up the ESPhome integration for the chosen communication method. @@ -46,17 +49,20 @@ A1 I²C address selection MSB .. _AliExpress: https://de.aliexpress.com/af/as3935.html?SearchText=as3935 .. _AMS_AS3935: https://ams.com/as3935 +Over SPI +-------- + +The ``as3935_spi`` sensor platform allows you to use your AS3935 sensor +(`AliExpress`_, `AMS_AS3935`_) in order to get notified when a thunderstorm is getting close. + + .. code-block:: yaml # Example configuration for SPI (decide for one!) as3935_spi: cs_pin: GPIO12 irq_pin: GPIO13 - # Example configuration for I²C (decide for one!) - as3935_i2c: - irq_pin: GPIO12 - - # Example configuration for creating sensors + # Example lightning and energy sensor sensor: - platform: as3935 lightning_energy: @@ -68,9 +74,10 @@ A1 I²C address selection MSB name: "Storm Alert" -Configuration variables (shared): ---------------------------------- +Configuration variables: +************************ +- **cs_pin** (**Required**, :ref:`Pin Schema `): The chip select pin. - **irq_pin** (**Required**, :ref:`config-pin`): The IRQ pin, which indicates if a lightning strike has been detected. - **indoor** (*Optional*, boolean): Indicates if the sensor is used indoor. Defaults to ``true``. - **noise_level** (*Optional*, integer): Noise floor level is compared to known reference voltage. @@ -90,34 +97,16 @@ Configuration variables (shared): - **capacitance** (*Optional*, integer): This setting will add capacitance to the series RLC antenna on the product to help tune its resonance. The datasheet specifies being within 3.5 percent of 500kHz to get optimal lightning detection and distance sensing. It's possible to add up to 120pF in steps of 8pF to the antenna. Defaults to ``0``. - - **watchdog_threshold** (*Optional*, integer): Determines the threshold for events that trigger the IRQ pin. Defaults to ``2``. -Sensor entries: -- **lightning_energy** (*Optional*): Lightning energy value. According to the datasheet this is only a pure value that doesn't have any physical meaning. +Over I²C +-------- - - **name** (**Required**, string): The name for the lightning energy sensor. - - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. - - All other options from :ref:`Sensor `. -- **distance** (*Optional*): Distance in km to the front of the storm and not the distance to a lightning strike. +The ``as3935_i2c`` sensor platform allows you to use your AS3935 sensor +(`AliExpress`_, `AMS_AS3935`_) in order to get notified when a thunderstorm is getting close. - - **name** (**Required**, string): The name for the distance sensor. - - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. - - All other options from :ref:`Sensor `. -- **binary sensor** (*Optional*): Binary sensor that indicates if a lightning strike was detected. - - - **name** (**Required**, string): The name of the binary sensor. - - **id** (*Optional*, - :ref:`config-id`): Manually specify - the ID used for code generation. - - All other options from :ref:`Binary Sensor `. - -Configuration variables (I²C): -------------------------------- - -Use this if you want to use your AS3935 in I²C mode. .. code-block:: yaml @@ -135,33 +124,67 @@ Use this if you want to use your AS3935 in I²C mode. - platform: as3935 name: "Storm Alert" +Configuration variables: +************************ + + - **address** (*Optional*, int): Manually specify the I²C address of the sensor. Defaults to ``0x03`` (``A0` and ``A1`` pins pulled low). Another address can be ``0x02``. +- **irq_pin** (**Required**, :ref:`config-pin`): The IRQ pin, which indicates if a lightning strike has been detected. +- **indoor** (*Optional*, boolean): Indicates if the sensor is used indoor. Defaults to ``true``. +- **noise_level** (*Optional*, integer): Noise floor level is compared to known reference voltage. + If this level is exceeded the chip will issue an interrupt to the IRQ pin, broadcasting that it can not + operate properly due to noise (INT_NH). Defaults to ``2``. +- **spike_rejection** (*Optional*, integer): Helps to differentiate between real events and actual lightning. + Increasing this value increases robustness at the cost of sensitivity to distant events. Defaults to ``2``. +- **lightning_threshold** (*Optional*, integer): The number of lightnings that must appear in a 15-minute time + window before a lightning storm is detected. + 15 minutes is the window of time before the number of detected lightning events is reset. + The number of lightning strikes can be set to 1,5,9, or 16. Defaults to ``1``. +- **mask_disturber** (*Optional*, boolean): This setting will return whether or not disturbers trigger + the IRQ Pin. Defaults to ``false``. +- **div_ratio** (*Optional*, integer): The antenna is designed to resonate at 500kHz and so can be tuned + with the following setting. The accuracy of the antenna must be within 3.5 percent of that value for + proper signal validation and distance estimation. Defaults to ``0``. +- **capacitance** (*Optional*, integer): This setting will add capacitance to the series RLC antenna on the product + to help tune its resonance. The datasheet specifies being within 3.5 percent of 500kHz to get optimal lightning + detection and distance sensing. It's possible to add up to 120pF in steps of 8pF to the antenna. Defaults to ``0``. +- **watchdog_threshold** (*Optional*, integer): Determines the threshold for events that trigger the IRQ pin. + Defaults to ``2``. -Configuration variables (SPI): ------------------------------- -Use this if you want to use your AS3935 in SPI mode. +Sensor +------ -.. code-block:: yaml +A sensor platform to read lightning data - # Example configuration for SPI (decide for one!) - as3935_spi: - cs_pin: GPIO12 - irq_pin: GPIO13 - # Example lightning and energy sensor - sensor: - - platform: as3935 - lightning_energy: - name: "Lightning Energy" - distance: - name: "Distance Storm" - binary_sensor: - - platform: as3935 - name: "Storm Alert" +Configuration variables: + +- **lightning_energy** (*Optional*): Lightning energy value. According to the datasheet this is only a pure value that doesn't have any physical meaning. + + - **name** (**Required**, string): The name for the lightning energy sensor. + - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. + - All other options from :ref:`Sensor `. + +- **distance** (*Optional*): Distance in km to the front of the storm and not the distance to a lightning strike. + + - **name** (**Required**, string): The name for the distance sensor. + - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. + - All other options from :ref:`Sensor `. + + +Binary Sensor +------------- + +Binary sensor that indicates if a lightning strike was detected. + +Configuration variables: + +- **name** (**Required**, string): The name of the binary sensor. +- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation. +- All other options from :ref:`Binary Sensor `. -- **cs_pin** (*Required*, :ref:`Pin Schema `): The chip select pin. See Also -------- diff --git a/components/sensor/custom.rst b/components/sensor/custom.rst index ca48b73a5..a0fdc92f4 100644 --- a/components/sensor/custom.rst +++ b/components/sensor/custom.rst @@ -76,7 +76,7 @@ Let's now also take a closer look at this line, which you might not be too used .. code-block:: cpp - class MyCustomSensor : public Component, public Sensor { + class MyCustomSensor : public Component, public Sensor { What this line is essentially saying is that we're defining our own class that's called ``MyCustomSensor`` which is also a subclass of :apiclass:`Component` and :apiclass:`Sensor `. @@ -137,7 +137,7 @@ One last thing. Some sensors, such as the BMP180 were are going to explain later .. code-block:: cpp float get_setup_priority() const override { return esphome::setup_priority::HARDWARE; } - + Where HARDWARE can be any of: .. code-block:: cpp @@ -161,7 +161,7 @@ Where HARDWARE can be any of: extern const float AFTER_CONNECTION; /// For components that should be initialized at the very end of the setup process. extern const float LATE; - + Now don't let the wording confuse you. The ``get_setup_priority()`` method is an override. Instead of fetching the setup priority setup for us, it instead fetches the setup priority for esphome, while being defined by us. The BMP180 would for instance need to be setup with a priority of IO or lower. A serial streaming (TCP) server would require a working WIFI setup and therefore get AFTER_WIFI. This finalizes our example as: @@ -172,9 +172,9 @@ This finalizes our example as: public: // constructor MyCustomSensor() : PollingComponent(15000) {} - + float get_setup_priority() const override { return esphome::setup_priority::XXXX; } - + void setup() override { // This will be called by App.setup() } @@ -182,7 +182,7 @@ This finalizes our example as: // This will be called every "update_interval" milliseconds. } }; - + Step 2: Registering the custom sensor ------------------------------------- @@ -403,6 +403,7 @@ Note that the number of arguments you put in the curly braces *must* match the n ``sensors:`` block - *and* they must be in the same order. Configuration variables: +************************ - **lambda** (**Required**, :ref:`lambda `): The lambda to run for instantiating the sensor(s). diff --git a/components/sensor/dallas.rst b/components/sensor/dallas.rst index b3225bb3c..312948201 100644 --- a/components/sensor/dallas.rst +++ b/components/sensor/dallas.rst @@ -45,8 +45,8 @@ Configuration variables: .. _dallas-sensor: -Sensors -------- +Sensor +------ The ``dallas`` sensor allows you to use DS18B20 and similar sensors. First, you need to define a :ref:`dallas sensor component `. diff --git a/components/sensor/images/inkbird_isbth1_mini-full.jpg b/components/sensor/images/inkbird_isbth1_mini-full.jpg new file mode 100644 index 000000000..e34559a40 Binary files /dev/null and b/components/sensor/images/inkbird_isbth1_mini-full.jpg differ diff --git a/components/sensor/images/inkbird_isbth1_mini-ui.png b/components/sensor/images/inkbird_isbth1_mini-ui.png new file mode 100644 index 000000000..e12eb9496 Binary files /dev/null and b/components/sensor/images/inkbird_isbth1_mini-ui.png differ diff --git a/components/sensor/images/inkbird_isbth1_mini.png b/components/sensor/images/inkbird_isbth1_mini.png new file mode 100644 index 000000000..1e21a6f63 Binary files /dev/null and b/components/sensor/images/inkbird_isbth1_mini.png differ diff --git a/components/sensor/images/sm300d2-full.jpg b/components/sensor/images/sm300d2-full.jpg new file mode 100644 index 000000000..47e1714ca Binary files /dev/null and b/components/sensor/images/sm300d2-full.jpg differ diff --git a/components/sensor/images/sm300d2-pins.jpg b/components/sensor/images/sm300d2-pins.jpg new file mode 100644 index 000000000..d0bfa9361 Binary files /dev/null and b/components/sensor/images/sm300d2-pins.jpg differ diff --git a/components/sensor/images/sm300d2-ui.png b/components/sensor/images/sm300d2-ui.png new file mode 100644 index 000000000..3cc52024f Binary files /dev/null and b/components/sensor/images/sm300d2-ui.png differ diff --git a/components/sensor/images/vl53l0x.png b/components/sensor/images/vl53l0x.png new file mode 100644 index 000000000..41dde9a26 Binary files /dev/null and b/components/sensor/images/vl53l0x.png differ diff --git a/components/sensor/images/xiaomi_miscale.jpg b/components/sensor/images/xiaomi_miscale.jpg new file mode 100644 index 000000000..1173ff0ea Binary files /dev/null and b/components/sensor/images/xiaomi_miscale.jpg differ diff --git a/components/sensor/images/xiaomi_miscale2.jpg b/components/sensor/images/xiaomi_miscale2.jpg new file mode 100644 index 000000000..81f767bbe Binary files /dev/null and b/components/sensor/images/xiaomi_miscale2.jpg differ diff --git a/components/sensor/index.rst b/components/sensor/index.rst index 13fd48881..ac52c8f45 100644 --- a/components/sensor/index.rst +++ b/components/sensor/index.rst @@ -27,6 +27,7 @@ override them if you want to. # Optional variables: unit_of_measurement: "°C" icon: "mdi:water-percent" + device_class: "temperature" accuracy_decimals: 1 expire_after: 30s filters: @@ -40,7 +41,11 @@ Configuration variables: - **unit_of_measurement** (*Optional*, string): Manually set the unit of measurement the sensor should advertise its values with. This does not actually do any maths (conversion between units). -- **icon** (*Optional*, icon): Manually set the icon to use for the sensor in the frontend. +- **device_class** (*Optional*, string): The device class for the + sensor. See https://www.home-assistant.io/integrations/sensor/#device-class + for a list of available options. Set to ``""`` to remove the default device class of a sensor. +- **icon** (*Optional*, icon): Manually set the icon to use for the sensor in the frontend. The icon set here + is ignored by Home Assistant, if a device class is already set. - **accuracy_decimals** (*Optional*, int): Manually set the accuracy of decimals to use when reporting values. - **filters** (*Optional*): Specify filters to use for some basic transforming of values. See :ref:`Sensor Filters ` for more information. @@ -127,8 +132,10 @@ for platforms with multiple sensors) - delta: 5.0 - lambda: return x * (9.0/5.0) + 32.0; -``offset`` / ``multiply`` -************************* +``offset`` +********** + +Adds a constant value to each sensor value. .. code-block:: yaml @@ -139,8 +146,10 @@ for platforms with multiple sensors) - offset: 2.0 - multiply: 1.2 -Offset adds a constant value to each sensor value. Multiply multiplies each value -by a constant value. +``multiply`` +************ + +Multiplies each value by a constant value. .. _sensor-filter-calibrate_linear: @@ -200,7 +209,7 @@ degree with a least squares solver. ``filter_out`` ************** -Filter out specific values to be displayed. For example to filter out the value ``85.0`` +(**Required**, number): Filter out specific values to be displayed. For example to filter out the value ``85.0`` .. code-block:: yaml @@ -213,8 +222,9 @@ Filter out specific values to be displayed. For example to filter out the value ``median`` ********** -Calculate moving median over the data. This can be used to filter outliers from the received -sensor data. A large window size will make the filter slow to react to input changes. +A `simple moving median `__ +over the last few values. This can be used to filter outliers from the received sensor data. A large +window size will make the filter slow to react to input changes. .. code-block:: yaml @@ -227,28 +237,78 @@ sensor data. A large window size will make the filter slow to react to input cha send_every: 4 send_first_at: 3 -- **median**: A `simple moving median - `__ - over the last few values. +Configuration variables: - - **window_size**: The number of values over which to calculate the median - when pushing out a value. This number should - be odd if you want an actual received value pushed out. - Defaults to ``5``. - - **send_every**: How often a sensor value should be pushed out. For - example, in above configuration the median is calculated after every 4th - received sensor value, over the last 7 received values. - Defaults to ``5``. - - **send_first_at**: By default, the very first raw value on boot is immediately - published. With this parameter you can specify when the very first value is to be sent. - Must be smaller than or equal to ``send_every`` - Defaults to ``1``. +- **window_size** (*Optional*, integer): The number of values over which to calculate the median + when pushing out a value. This number should + be odd if you want an actual received value pushed out. + Defaults to ``5``. +- **send_every** (*Optional*, integer): How often a sensor value should be pushed out. For + example, in above configuration the median is calculated after every 4th + received sensor value, over the last 7 received values. + Defaults to ``5``. +- **send_first_at** (*Optional*, integer): By default, the very first raw value on boot is immediately + published. With this parameter you can specify when the very first value is to be sent. + Must be smaller than or equal to ``send_every`` + Defaults to ``1``. -``sliding_window_moving_average`` / ``exponential_moving_average`` -****************************************************************** +``min`` +******* -Two simple moving averages over the data. These can be used to have a short update interval -on the sensor but only push out an average on a specific interval (thus increasing resolution). +A moving minimum over the last few values. A large window size will make the filter slow to +react to input changes. + +.. code-block:: yaml + + # Example configuration entry + - platform: wifi_signal + # ... + filters: + - min: + window_size: 7 + send_every: 4 + send_first_at: 3 + +Configuration variables: + +- **window_size** (*Optional*, integer): The number of values over which to calculate the min/max when pushing out a + value. Defaults to ``5``. +- **send_every** (*Optional*, integer): How often a sensor value should be pushed out. For + example, in above configuration the min is calculated after every 4th + received sensor value, over the last 7 received values. + Defaults to ``5``. +- **send_first_at** (*Optional*, integer): By default, the very first raw value on boot is immediately + published. With this parameter you can specify when the very first value is to be sent. + Must be smaller than or equal to ``send_every`` + Defaults to ``1``. + +``max`` +******* + +A moving maximum over the last few values. A large window size will make the filter slow to +react to input changes. + +Configuration variables: + +- **window_size** (*Optional*, integer): The number of values over which to calculate the min/max + when pushing out a value. + Defaults to ``5``. +- **send_every** (*Optional*, integer): How often a sensor value should be pushed out. For + example, in above configuration the min is calculated after every 4th + received sensor value, over the last 7 received values. + Defaults to ``5``. +- **send_first_at** (*Optional*, integer): By default, the very first raw value on boot is immediately + published. With this parameter you can specify when the very first value is to be sent. + Must be smaller than or equal to ``send_every`` + Defaults to ``1``. + + +``sliding_window_moving_average`` +********************************* + +A `simple moving average `__ +over the last few values. It can be used to have a short update interval on the sensor but only push +out an average on a specific interval (thus increasing resolution). .. code-block:: yaml @@ -260,28 +320,36 @@ on the sensor but only push out an average on a specific interval (thus increasi window_size: 15 send_every: 15 -- **sliding_window_moving_average**: A `simple moving - average `__ - over the last few values. +Configuration variables: - - **window_size**: The number of values over which to perform an - average when pushing out a value. - - **send_every**: How often a sensor value should be pushed out. For - example, in above configuration the weighted average is only - pushed out on every 15th received sensor value. - - **send_first_at**: By default, the very first raw value on boot is immediately - published. With this parameter you can specify when the very first value is to be sent. - Defaults to ``1``. +- **window_size** (*Optional*, integer): The number of values over which to perform an + average when pushing out a value. +- **send_every** (*Optional*, integer): How often a sensor value should be pushed out. For + example, in above configuration the weighted average is only + pushed out on every 15th received sensor value. +- **send_first_at** (*Optional*, integer): By default, the very first raw value on boot is immediately + published. With this parameter you can specify when the very first value is to be sent. + Defaults to ``1``. -- **exponential_moving_average**: A simple `exponential moving - average `__ - over the last few values. +``exponential_moving_average`` +****************************** - - **alpha**: The forget factor/alpha value of the filter. - - **send_every**: How often a sensor value should be pushed out. +A simple `exponential moving average +`__ over the last few +values. It can be used to have a short update interval on the sensor but only push +out an average on a specific interval (thus increasing resolution). -``throttle`` / ``heartbeat`` / ``debounce`` / ``delta`` -******************************************************* +Configuration variables: + +- **alpha** (*Optional*, float): The forget factor/alpha value of the filter. Defaults to ``0.1``. +- **send_every** (*Optional*, integer): How often a sensor value should be pushed out. Defaults to ``15``. + +``throttle`` +************ + +Throttle the incoming values. When this filter gets an incoming value, +it checks if the last incoming value is at least ``specified time period`` old. +If it is not older than the configured value, the value is not passed forward. .. code-block:: yaml @@ -293,28 +361,38 @@ on the sensor but only push out an average on a specific interval (thus increasi - delta: 5.0 - lambda: return x * (9.0/5.0) + 32.0; -- **throttle**: Throttle the incoming values. When this filter gets an incoming value, - it checks if the last incoming value is at least ``specified time period`` old. - If it is not older than the configured value, the value is not passed forward. -- **heartbeat**: Send the last value that this sensor in the specified time interval. - So a value of ``10s`` will cause the filter to output values every 10s regardless - of the input values. - -- **debounce**: Only send values if the last incoming value is at least ``specified time period`` - old. For example if two values come in at almost the same time, this filter will only output - the last value and only after the specified time period has passed without any new incoming - values. - -- **delta**: This filter stores the last value passed through this filter and only - passes incoming values through if the absolute difference is greater than the configured - value. For example if a value of 1.0 first comes in, it's passed on. If the delta filter - is configured with a value of 5, it will now not pass on an incoming value of 2.0, only values - that are at least 6.0 big or -4.0. - -``or`` Filter +``heartbeat`` ************* +Send the last value that this sensor in the specified time interval. +So a value of ``10s`` will cause the filter to output values every 10s regardless +of the input values. + +``debounce`` +************ + +Only send values if the last incoming value is at least ``specified time period`` +old. For example if two values come in at almost the same time, this filter will only output +the last value and only after the specified time period has passed without any new incoming +values. + +``delta`` +********* + +This filter stores the last value passed through this filter and only +passes incoming values through if the absolute difference is greater than the configured +value. For example if a value of 1.0 first comes in, it's passed on. If the delta filter +is configured with a value of 5, it will now not pass on an incoming value of 2.0, only values +that are at least 6.0 big or -4.0. + +``or`` +****** + +Pass forward a value with the first child filter that returns. Above example +will only pass forward values that are *either* at least 1s old or are if the absolute +difference is at least 5.0. + .. code-block:: yaml # Example filters: @@ -323,22 +401,18 @@ on the sensor but only push out an average on a specific interval (thus increasi - throttle: 1s - delta: 5.0 -- **or**: Pass forward a value with the first child filter that returns. Above example - will only pass forward values that are *either* at least 1s old or are if the absolute - difference is at least 5.0. +``lambda`` +********** -``lambda`` Filter -***************** +Perform a simple mathematical operation over the sensor values. The input value is ``x`` and +the result of the lambda is used as the output (use ``return``). .. code-block:: yaml filters: - lambda: return x * (9.0/5.0) + 32.0; -**lambda**: Perform a simple mathematical operation over the sensor -values. The input value is ``x`` and the result of the lambda is used -as the output (use ``return``). Make sure to add ``.0`` to all values in the lambda, otherwise divisions of integers will result in integers (not floating point values). diff --git a/components/sensor/inkbird_ibsth1_mini.rst b/components/sensor/inkbird_ibsth1_mini.rst new file mode 100644 index 000000000..03cc6bfb2 --- /dev/null +++ b/components/sensor/inkbird_ibsth1_mini.rst @@ -0,0 +1,103 @@ +Inkbird IBS-TH1 Mini BLE Sensor +=============================== + +.. seo:: + :description: Instructions for setting up Inkbird IBS-TH1 Mini Bluetooth-based temperature and humidity sensors in ESPHome. + :image: inkbird_isbth1_mini.jpg + :keywords: Inkbird, BLE, Bluetooth, IBS-TH1 + +The ``inkbird_ibsth1_mini`` sensor platform lets you track the output of Inkbird IBS-TH1 Mini Bluetooth +Low Energy devices using the :doc:`/components/esp32_ble_tracker`. This component will track the +temperature, humidity and the battery level of the IBS-TH1 Mini device every time the +sensor sends out a BLE broadcast. Note that contrary to other implementations, ESPHome can track as +many IBS-TH1 Mini devices at once as you want. + +.. figure:: images/inkbird_isbth1_mini-full.jpg + :align: center + :width: 80.0% + + Inkbird IBS-TH1 Mini Temperature and Humidity Sensor over BLE. + +.. figure:: images/inkbird_isbth1_mini-ui.png + :align: center + :width: 80.0% + +.. code-block:: yaml + + # Example configuration entry + esp32_ble_tracker: + + sensor: + - platform: inkbird_ibsth1_mini + mac_address: 38:81:D7:0A:9C:11 + temperature: + name: "Inkbird IBS-TH1 Mini Temperature" + humidity: + name: "Inkbird IBS-TH1 Mini Humidity" + battery_level: + name: "Inkbird IBS-TH1 Mini Battery Level" + +Configuration variables: +------------------------ + +- **mac_address** (**Required**, MAC Address): The MAC address of the Inkbird IBS-TH1 Mini device. +- **temperature** (*Optional*): The information for the temperature sensor. + + - **name** (**Required**, string): The name for the temperature sensor. + - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. + - All other options from :ref:`Sensor `. + +- **humidity** (*Optional*): The information for the humidity sensor + + - **name** (**Required**, string): The name for the humidity sensor. + - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. + - All other options from :ref:`Sensor `. + +- **battery_level** (*Optional*): The information for the battery level sensor + + - **name** (**Required**, string): The name for the battery level sensor. + - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. + - All other options from :ref:`Sensor `. + + +Setting Up Devices +------------------ + +To set up Inkbird IBS-TH1 Mini devices you first need to find their MAC Address so that ESPHome can +identify them. So first, create a simple configuration without any ``inkbird_ibsth1_mini`` entries +like so: + +.. code-block:: yaml + + esp32_ble_tracker: + +After uploading the ESP32 will immediately try to scan for BLE devices such as the Inkbird IBS-TH1 Mini. +When it detects these sensors, it will automatically parse the BLE message print a +message like this one: + +.. code:: + + [13:36:43][D][esp32_ble_tracker:544]: Found device 38:81:D7:0A:9C:11 RSSI=-53 + [13:36:43][D][esp32_ble_tracker:565]: Address Type: PUBLIC + [13:36:43][D][esp32_ble_tracker:567]: Name: 'sps' + +Note that it can sometimes take some time for the first BLE broadcast to be received. Please note that address type +should say 'PUBLIC' and the device name should be 'sps', this is how you find the Inkbird IBS-TH1 Mini among all the +other devices. + +Then just copy the address (``38:81:D7:0A:9C:11``) into a new ``sensor.inkbird_ibsth1_mini`` platform +entry like in the configuration example at the top. + +.. note:: + + The ESPHome Inkbird IBS-TH1 Mini integration listens passively to packets the device sends by itself. + ESPHome therefore has no impact on the battery life of the device. + +See Also +-------- + +- :doc:`/components/esp32_ble_tracker` +- :doc:`/components/sensor/index` +- :apiref:`inkbird_ibsth1_mini/inkbird_ibsth1_mini.h` +- `OpenMQTTGateway `__ by `@1technophile `__ +- :ghedit:`Edit` diff --git a/components/sensor/mcp3008.rst b/components/sensor/mcp3008.rst index 173f878e6..fe14d9bcf 100644 --- a/components/sensor/mcp3008.rst +++ b/components/sensor/mcp3008.rst @@ -8,15 +8,17 @@ MCP3008 I/O Expander The Microchip Technology Inc. MCP3008 devices are successive approximation 10-bit Analogto-Digital (A/D) converters with on-board sample and -hold circuitry. +hold circuitry. .. figure:: images/mcp3008.jpg :align: center :width: 50.0% -MCP3008 -------- +.. _mcp3008-component: + +Component/Hub +------------- The MCP3008 component allows you to use MCP3008 8-Channel 10-Bit A/D Converter (`datasheet `__, @@ -65,14 +67,19 @@ If you want just the scaled value you can use the read_data function name: Freezer Temperature Configuration variables: -~~~~~~~~~~~~~~~~~~~~~~~~ -MCP3008 Component -***************** - **id** (**Required**, :ref:`config-id`): The id to use for this MCP3008 component. - **cs_pin** (**Required**, int): The SPI cable select pin to use -MCP3008 Sensor Component -************************ + +Sensor +------ + +The ``mcp3008`` sensor allows you to use your MCP3008 10-Bit A/D Converter sensors with ESPHome. +First, setup a :ref:`MCP3008 Hub ` for your MCP3008 sensor and then use this +sensor platform to create individual sensors that will report the voltage to Home Assistant. + +Configuration variables: + - **id** (**Required**, :ref:`config-id`): The id of the parent MCP3008 component. - **number** (**Required**, int): The pin number of the MCP3008 - **reference_voltage** (*Optional*, float): The reference voltage. Defaults to ``3.3V``. diff --git a/components/sensor/mcp9808.rst b/components/sensor/mcp9808.rst index d04ee776c..6bd23f940 100644 --- a/components/sensor/mcp9808.rst +++ b/components/sensor/mcp9808.rst @@ -32,15 +32,11 @@ required to be set up in your configuration for this sensor to work. Configuration variables: ------------------------ -- **temperature** (**Required**): The information for the temperature sensor. - - - **name** (**Required**, string): The name for the temperature sensor. - - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. - - All other options from :ref:`Sensor `. - +- **name** (**Required**, string): The name for the temperature sensor. +- **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. - **address** (*Optional*, int): Manually specify the I²C address of the sensor. Defaults to ``0x18``. - **update_interval** (*Optional*, :ref:`config-time`): The interval to check the sensor. Defaults to ``60s``. - +- All other options from :ref:`Sensor `. See Also -------- diff --git a/components/sensor/pulse_meter.rst b/components/sensor/pulse_meter.rst new file mode 100644 index 000000000..6de3c4df4 --- /dev/null +++ b/components/sensor/pulse_meter.rst @@ -0,0 +1,82 @@ +Pulse Meter Sensor +================== + +.. seo:: + :description: Instructions for setting up pulse meter sensors. + :image: pulse.png + +The pulse meter sensor allows you to count the number and frequency of pulses on any pin. It is intended to be a drop-in replacement +for :doc:`integration sensor `, but offering better resolution. +It measures the time between rising edges on a pin, for each pulse it outputs the frequency in pulses/min. + +.. code-block:: yaml + + # Example configuration entry + sensor: + - platform: pulse_meter + pin: 12 + name: "Pulse Meter" + +Configuration variables: +------------------------ + +- **pin** (**Required**, :ref:`config-pin`): The pin to count pulses on. +- **name** (**Required**, string): The name of the sensor. + +- **internal_filter** (*Optional*, :ref:`config-time`): If a pulse shorter than this + time is detected, it’s discarded and no pulse is counted. Defaults to ``13us``. For S0 pulse meters that are used to meter power consumption 50-100 ms is a reasonable value. + +- **timeout** (*Optional*, :ref:`config-time`): If we don't see a pulse for this length of time, we assume 0 pulses/sec. Defaults to ``5 min``. +- **total** (*Optional*, :ref:`Sensor `): An additional sensor that outputs the total number of pulses counted. +- All other options from :ref:`Sensor `. + +Converting units +---------------- + +The sensor defaults to units of “pulses/min”. You can change this by using :ref:`sensor-filters`. +For example, if you’re using the pulse meter with a photodiode to +count the light pulses on a power meter that outputs 1000 pulses per kWh, +you can use the following to output instantaneous usage in kW: + +.. code-block:: yaml + + # Example configuration entry + sensor: + - platform: pulse_meter + pin: 12 + unit_of_measurement: 'kW' + name: 'Electricity Usage' + filters: + - multiply: 0.06 + +Counting total pulses +--------------------- + +When the total sensor is configured, pulse_meter also reports the total +number of pulses measured. When used on a power meter, this can be used to +measure the total consumed energy in kWh. + +.. code-block:: yaml + + # Example configuration entry + sensor: + - platform: pulse_meter + pin: 12 + unit_of_measurement: 'kW' + name: 'Electricity Usage' + filters: + - multiply: 0.06 + total: + name: "Electricity Total" + unit_of_measurement: "kWh" + accuracy_decimals: 0 + filters: + - multiply: 0.001 + +See Also +-------- + +- :ref:`sensor-filters` +- :doc:`/components/sensor/pulse_counter` +- :apiref:`pulse_meter/pulse_meter_sensor.h` +- :ghedit:`Edit` diff --git a/components/sensor/ruuvitag.rst b/components/sensor/ruuvitag.rst index 792d38f61..9b98a9462 100644 --- a/components/sensor/ruuvitag.rst +++ b/components/sensor/ruuvitag.rst @@ -129,7 +129,7 @@ Configuration variables: - All other options from :ref:`Sensor `. - Only available if RAWv2 protocol is used. -- **movement_count** (*Optional*): The information for the movement count +- **movement_counter** (*Optional*): The information for the movement count sensor - **name** (**Required**, string): The name for the movement count sensor. diff --git a/components/sensor/senseair.rst b/components/sensor/senseair.rst index a173b6c1c..67db919bb 100644 --- a/components/sensor/senseair.rst +++ b/components/sensor/senseair.rst @@ -64,6 +64,77 @@ Configuration variables: ``G+`` should be connected to power supply (supported voltage is 4.5 V to 5.25 V), ``G0`` to ``GND`` pin +.. _senseair-background_calibration_action: + +``senseair.background_calibration`` Action +------------------------------------------ + +This :ref:`action ` initiates a background calibration on the sensor with the given ID: the current +CO2 level will be used as a reference for the 400ppm threshold. Ensure that the sensor is in a stable environment with +fresh ambient air, preferably near a window that has already been opened for a sufficient time. + +.. code-block:: yaml + + on_...: + then: + - senseair.background_calibration: my_senseair_id + +.. _senseair-background_calibration_result_action: + +``senseair.background_calibration_result`` Action +------------------------------------------------- + +This :ref:`action ` requests the result of the background calibration procedure from the sensor +with the given ID. The value will be printed in ESPHome logs. + +Wait at least one sensor lamp cycle after having triggered the background calibration before requesting its result. + +.. code-block:: yaml + + on_...: + then: + - senseair.background_calibration_result: my_senseair_id + +.. _senseair-abc_get_period_action: + +``senseair.abc_get_period`` Action +---------------------------------- + +This :ref:`action ` requests the currently configured ABC interval from the sensor with the given ID. +The value will be printed in ESPHome logs. + +.. code-block:: yaml + + on_...: + then: + - senseair.abc_get_period: my_senseair_id + +.. _senseair-abc_enable_action: + +``senseair.abc_enable`` Action +------------------------------ + +This :ref:`action ` enables Automatic Baseline Calibration on the sensor with the given ID. +ABC will be activated with the default interval of 180 hours. + +.. code-block:: yaml + + on_...: + then: + - senseair.abc_enable: my_senseair_id + +.. _senseair-abc_disable_action: + +``senseair.abc_disable`` Action +------------------------------- + +This :ref:`action ` disables Automatic Baseline Calibration on the sensor with the given ID. + +.. code-block:: yaml + + on_...: + then: + - senseair.abc_disable: my_senseair_id See Also -------- diff --git a/components/sensor/sm300d2.rst b/components/sensor/sm300d2.rst new file mode 100644 index 000000000..286dd9953 --- /dev/null +++ b/components/sensor/sm300d2.rst @@ -0,0 +1,123 @@ +SM300D2 7-in-1 Air Quality Sensor +================================= + +.. seo:: + :description: Instructions for setting up SM300D2 sensor to work with ESPHome + :image: sm300d2-full.jpg + :keywords: sm300d2 + +The ``sm300d2`` sensor platform allows you to use the SM300D2 7-in-1 Air Quality Sensor with ESPHome. + +.. figure:: images/sm300d2-full.jpg + :align: center + :width: 50.0% + + SM300D2 7-in-1 Air Quality Sensor. + +.. figure:: images/sm300d2-ui.png + :align: center + :width: 50.0% + + +The SM300D2 sensor supports connections via UART or RS485. This platform only supports UART-connections. +Make sure you have a :ref:`UART bus ` in your configuration with the ``rx_pin`` connected to the +TX pin of the sensor. The sensor does not support receiving data, so the ``tx_pin`` does not need to be +connected. The sensor expects the baud rate to be set at 9600. + +.. code-block:: yaml + + # Example configuration entry + uart: + rx_pin: D0 + tx_pin: D1 + baud_rate: 9600 + + sensor: + - platform: sm300d2 + co2: + name: "SM300D2 CO2 Value" + formaldehyde: + name: "SM300D2 Formaldehyde Value" + tvoc: + name: "SM300D2 TVOC Value" + pm_2_5: + name: "SM300D2 PM2.5 Value" + pm_10_0: + name: "SM300D2 PM10 Value" + temperature: + name: "SM300D2 Temperature Value" + humidity: + name: "SM300D2 Humidity Value" + update_interval: 60s + +Configuration variables: +------------------------ + + +- **co2** (**Required**): The CO₂ data from the sensor in parts per million (ppm). + + - **name** (**Required**, string): The name of the CO₂ sensor. + - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. + - All other options from :ref:`Sensor `. + +- **formaldehyde** (**Required**): The formaldehyde data of the sensor in micrograms per cubic meter air (µg/m³). + + - **name** (**Required**, string): The name of the formaldehyde sensor. + - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. + - All other options from :ref:`Sensor `. + +- **tvoc** (**Required**): The total volatile organic compounds (TVOC) data of the sensor in micrograms per cubic meter air (µg/m³). + + - **name** (**Required**, string): The name of the TVOC sensor. + - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. + - All other options from :ref:`Sensor `. + +- **pm_2_5** (**Required**): The PM2.5 data of the sensor in micrograms per cubic meter air (µg/m³). + + - **name** (**Required**, string): The name of the PM2.5 sensor. + - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. + - All other options from :ref:`Sensor `. + +- **pm_10_0** (**Required**): The PM10 data of the sensor in micrograms per cubic meter air (µg/m³). + + - **name** (**Required**, string): The name of the PM10 sensor. + - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. + - All other options from :ref:`Sensor `. + +- **temperature** (**Required**): The temperature data of the sensor in degrees celsius (°C). + + - **name** (**Required**, string): The name of the temperature sensor. + - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. + - All other options from :ref:`Sensor `. + +- **humidity** (**Required**): The humidity data of the sensor in percent relative humidity (%). + + - **name** (**Required**, string): The name of the humidity sensor. + - **id** (*Optional*, :ref:`config-id`): Set the ID of this sensor for use in lambdas. + - All other options from :ref:`Sensor `. + +- **update_interval** (*Optional*, :ref:`config-time`): The interval to check the + sensor. Defaults to ``60s``. + +- **uart_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the :ref:`UART Component ` if you want + to use multiple UART buses. + +- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for actions. + +.. figure:: images/sm300d2-pins.jpg + :align: center + :width: 80.0% + + Pins on the SM300D2. UART RX is not in use. + +.. note:: + + ``5V`` should be connected to power supply (supported voltage is 4.8 V to 5.2 V), ``GD`` to ``GND`` pin + + +See Also +-------- + +- :ref:`sensor-filters` +- :apiref:`sm300d2/sm300d2.h` +- :ghedit:`Edit` diff --git a/components/sensor/tmp117.rst b/components/sensor/tmp117.rst index 685626309..749df70a4 100644 --- a/components/sensor/tmp117.rst +++ b/components/sensor/tmp117.rst @@ -34,8 +34,8 @@ If accuracy is a must, see section 8.2.2.2 of the `datasheet `__, -`ST `__) with ESPHome +`ST `__) with ESPHome to measure distances. The sensor works optically by emitting short infrared pulses and measuring the time it takes the light to be reflected back @@ -17,8 +17,21 @@ on several conditions like surface reflectance, field of view, temperature etc. you can expect surfaces up to 60cm to work, after that you need to make sure the surface is reflecting well enough (see also section 5 of datasheet). -The :ref:`I²C Bus ` is -required to be set up in your configuration for this sensor to work. +.. figure:: images/vl53l0x.png + :align: center + :width: 100.0% + +The :ref:`I²C Bus ` is required to be set up in your configuration for this sensor to work. + +- ``VCC`` connects to 3V3 (``3V3`` will output 3.3V), or directly connect ``VCC`` to 3.3V +- ``GND`` connects to ground +- ``SCL`` connects I2C SCL (clock) +- ``SDA`` connects I2C SDA (data) +- ``GPIO1`` is not used by ESPHome +- ``XSHUT`` connects to free GPIO pin. Enable/disable device. This is optional if there is only one + VL53L0X sensor on the I²C bus and the default ``0x29`` address is used. Otherwise this is required. + + .. figure:: images/vl53l0x-full.jpg :align: center @@ -32,7 +45,7 @@ required to be set up in your configuration for this sensor to work. .. code-block:: yaml - # Example configuration entry + # Simple configuration entry example sensor: - platform: vl53l0x name: "VL53L0x Distance" @@ -50,11 +63,44 @@ Configuration variables: (mega counts per second). This is the minimum signal amplitude detected by the sensor necessary for it to report a valid reading. Setting a lower value may increase the range of the sensor but also increases the chance of getting inaccurate readings. Defaults to ``0.25``. -- All other options from :ref:`Sensor `. - **long_range** (*Optional*, bool): Set the sensor in long range mode. The signal_rate_limit is overruled - to ``0.1``. Defaults to false. -- **address** (*Optional*, int): Manually specify the I²C address of the sensor. Defaults to ``0x29``. + to ``0.1``. Defaults to ``false``. +- **address** (*Optional*, int): Manually specify the i2c address of the sensor. Defaults to ``0x29``. + If an address other the ``0x29`` is specified, the sensor will be dynamically re-addressed at startup. + A dynamic re-address of sensor requires the ``enable_pin`` configuration variable to be assigned. + If more then one VL53L0X sensor is used on the same i2c bus, a unique address must be specified per sensor. +- **enable_pin** (*Optional*, :ref:`Pin Schema `): The pin connected to XSHUT + on vl53l0x to enable/disable sensor. **Required** if not using address ``0x29`` which is the cause if you + have multiple VL53L0X on the same i2c bus. In this case you have to assign a different pin to each VL53L0X. +- **timeout** (*Optional*, :ref:`config-time`): Sensor setup timeout. Default to ``10ms``. - **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation. +- All other options from :ref:`Sensor `. + + +.. code-block:: yaml + + # Muliple VL53L0X sensors on same i2c bus + # Example configuration entry + sensor: + - platform: vl53l0x + name: "distance1" + id: distance1 + address: 0x41 + enable_pin: GPIO16 + timeout: 200us + update_interval: 500ms + unit_of_measurement: "m" + + - platform: vl53l0x + name: "distance2" + id: distance2 + address: 0x42 + enable_pin: GPIO17 + timeout: 200us + update_interval: 500ms + unit_of_measurement: "m" + + See Also -------- diff --git a/components/sensor/xiaomi_miscale.rst b/components/sensor/xiaomi_miscale.rst new file mode 100644 index 000000000..a4f7087db --- /dev/null +++ b/components/sensor/xiaomi_miscale.rst @@ -0,0 +1,100 @@ +Xiaomi Miscale Sensors +======================== + +.. seo:: + :description: Instructions for setting up Xiaomi Miscale bluetooth-based sensors in ESPHome. + :image: xiaomi_miscale.jpg + :keywords: Xiaomi, BLE, Bluetooth, XMTZC01HM, XMTZC04HM + +The ``xiaomi_miscale`` sensor platform lets you track the output of Xiaomi Bluetooth Low Energy devices using the :doc:`/components/esp32_ble_tracker`. This component will track, for example, the weight of the device every time the sensor sends out a BLE broadcast. Contrary to other implementations, ``xiaomi_miscale`` listens passively to advertisement packets and does not pair with the device. Hence ESPHome has no impact on battery life. + +To get the body scores using your weight, height, age and gender see the custom_components ``__ + +Supported Devices +----------------- + +XMTZC01HM, XMTZC04HM +******************** + +Miscale measures weight. + +.. figure:: images/xiaomi_miscale.jpg + :align: center + :width: 60.0% + +Configuration example: + +.. code-block:: yaml + + sensor: + - platform: xiaomi_miscale + mac_address: 'C8:47:8C:9F:7B:0A' + weight: + name: "Xiaomi Mi Scale Weight" + +Configuration example with multiple users : + +You have to replace the numbers in the lambdas to determine your weight which is between X weight and X weight. + +.. code-block:: yaml + + sensor: + - platform: xiaomi_miscale + mac_address: 'C8:47:8C:9F:7B:0A' + weight: + name: "Xiaomi Mi Scale Weight" + id: weight_miscale + on_value: + then: + - lambda: |- + if (id(weight_miscale).state >= 69 && id(weight_miscale).state <= 74.49) { + return id(weight_user1).publish_state(x);} + else if (id(weight_miscale).state >= 74.50 && id(weight_miscale).state <= 83) { + return id(weight_user2).publish_state(x);} + else if (id(weight_miscale).state >= 46 && id(weight_miscale).state <= 65) { + return id(weight_user3).publish_state(x);} + else if (id(weight_miscale).state >= 28 && id(weight_miscale).state <= 45) { + return id(weight_user4).publish_state(x);} + else if (id(weight_miscale).state >= 5 && id(weight_miscale).state <= 20) { + return id(weight_user5).publish_state(x);} + + - platform: template + name: Weight Aurélien + id: weight_user1 + unit_of_measurement: 'kg' + icon: mdi:weight-kilogram + accuracy_decimals: 2 + - platform: template + name: Weight Siham + id: weight_user2 + unit_of_measurement: 'kg' + icon: mdi:weight-kilogram + accuracy_decimals: 2 + - platform: template + name: Weight Théo + id: weight_user3 + unit_of_measurement: 'kg' + icon: mdi:weight-kilogram + accuracy_decimals: 2 + - platform: template + name: Weight Sacha + id: weight_user4 + unit_of_measurement: 'kg' + icon: mdi:weight-kilogram + accuracy_decimals: 2 + - platform: template + name: Weight Noham + id: weight_user5 + unit_of_measurement: 'kg' + icon: mdi:weight-kilogram + accuracy_decimals: 2 + + +See Also +-------- + +- :doc:`/components/esp32_ble_tracker` +- :doc:`/components/sensor/index` +- bodymiscale score integration for Home Assistant (bodymiscale custom component) ``__ + +- :ghedit:`Edit` diff --git a/components/sensor/xiaomi_miscale2.rst b/components/sensor/xiaomi_miscale2.rst new file mode 100644 index 000000000..ad1f40c1b --- /dev/null +++ b/components/sensor/xiaomi_miscale2.rst @@ -0,0 +1,149 @@ +Xiaomi Miscale2 Sensors +======================== + +.. seo:: + :description: Instructions for setting up Xiaomi Miscale2 bluetooth-based sensors in ESPHome. + :image: xiaomi_miscale2.jpg + :keywords: Xiaomi, BLE, Bluetooth, XMTZC02HM, XMTZC05HM + +The ``xiaomi_miscale2`` sensor platform lets you track the output of Xiaomi Bluetooth Low Energy devices using the :doc:`/components/esp32_ble_tracker`. This component will track, for example, the weight and the impedance of the device every time the sensor sends out a BLE broadcast. Contrary to other implementations, ``xiaomi_miscale2`` listens passively to advertisement packets and does not pair with the device. Hence ESPHome has no impact on battery life. + +To get the body scores using your weight, height, age and gender see the custom_components ``__ + +Supported Devices +----------------- + +XMTZC02HM, XMTZC05HM +******************** + +Miscale2 measures weight and impedance. + +.. figure:: images/xiaomi_miscale2.jpg + :align: center + :width: 60.0% + +Configuration example: + +.. code-block:: yaml + + sensor: + - platform: xiaomi_miscale2 + mac_address: '5C:CA:D3:70:D4:A2' + weight: + name: "Xiaomi Mi Scale Weight" + impedance: + name: "Xiaomi Mi Scale Impedance" + +Configuration example with multiple users : + +You have to replace the numbers in the lambdas to determine your weight which is between X weight and X weight. + +.. code-block:: yaml + + sensor: + - platform: xiaomi_miscale2 + mac_address: '5C:CA:D3:70:D4:A2' + weight: + name: "Xiaomi Mi Scale Weight" + id: weight_miscale + on_value: + then: + - lambda: |- + if (id(weight_miscale).state >= 69 && id(weight_miscale).state <= 74.49) { + return id(weight_user1).publish_state(x);} + else if (id(weight_miscale).state >= 74.50 && id(weight_miscale).state <= 83) { + return id(weight_user2).publish_state(x);} + else if (id(weight_miscale).state >= 46 && id(weight_miscale).state <= 65) { + return id(weight_user3).publish_state(x);} + else if (id(weight_miscale).state >= 28 && id(weight_miscale).state <= 45) { + return id(weight_user4).publish_state(x);} + else if (id(weight_miscale).state >= 5 && id(weight_miscale).state <= 20) { + return id(weight_user5).publish_state(x);} + + impedance: + name: "Xiaomi Mi Scale Impedance" + id: impedance_xiaomi + on_value: + then: + - lambda: |- + if (id(weight_miscale).state >= 69 && id(weight_miscale).state <= 74.49) { + return id(impedance_user1).publish_state(x);} + else if (id(weight_miscale).state >= 74.50 && id(weight_miscale).state <= 83) { + return id(impedance_user2).publish_state(x);} + else if (id(weight_miscale).state >= 46 && id(weight_miscale).state <= 65) { + return id(impedance_user3).publish_state(x);} + else if (id(weight_miscale).state >= 28 && id(weight_miscale).state <= 45) { + return id(impedance_user4).publish_state(x);} + else if (id(weight_miscale).state >= 5 && id(weight_miscale).state <= 20) { + return id(impedance_user5).publish_state(x);} + + - platform: template + name: Weight Aurélien + id: weight_user1 + unit_of_measurement: 'kg' + icon: mdi:weight-kilogram + accuracy_decimals: 2 + - platform: template + name: Impedance Aurélien + id: impedance_user1 + unit_of_measurement: 'ohm' + icon: mdi:omega + accuracy_decimals: 0 + - platform: template + name: Weight Siham + id: weight_user2 + unit_of_measurement: 'kg' + icon: mdi:weight-kilogram + accuracy_decimals: 2 + - platform: template + name: Impedance Siham + id: impedance_user2 + unit_of_measurement: 'ohm' + icon: mdi:omega + accuracy_decimals: 0 + - platform: template + name: Weight Théo + id: weight_user3 + unit_of_measurement: 'kg' + icon: mdi:weight-kilogram + accuracy_decimals: 2 + - platform: template + name: Impedance Théo + id: impedance_user3 + unit_of_measurement: 'ohm' + icon: mdi:omega + accuracy_decimals: 0 + - platform: template + name: Weight Sacha + id: weight_user4 + unit_of_measurement: 'kg' + icon: mdi:weight-kilogram + accuracy_decimals: 2 + - platform: template + name: Impedance Sacha + id: impedance_user4 + unit_of_measurement: 'ohm' + icon: mdi:omega + accuracy_decimals: 0 + - platform: template + name: Weight Noham + id: weight_user5 + unit_of_measurement: 'kg' + icon: mdi:weight-kilogram + accuracy_decimals: 2 + - platform: template + name: Impedance Noham + id: impedance_user5 + unit_of_measurement: 'ohm' + icon: mdi:omega + accuracy_decimals: 0 + + +See Also +-------- + +- :doc:`/components/esp32_ble_tracker` +- :doc:`/components/sensor/index` +- bodymiscale score integration for Home Assistant (bodymiscale custom component) ``__ + +- :ghedit:`Edit` diff --git a/components/sim800l.rst b/components/sim800l.rst index ed208dab0..d1ce18afb 100644 --- a/components/sim800l.rst +++ b/components/sim800l.rst @@ -2,11 +2,11 @@ Sim800L Component ================= .. seo:: - :description: Instructions for setting up the SIM800L GSM module to send and receive SMS in ESPHome. + :description: Instructions for setting up the SIM800L GSM module to dial, send and receive SMS in ESPHome. :image: sim800l.jpg :keywords: SMS SIM800L GSM -The ``SIM800L`` Component provides the ability to send and receive SMS text messages. The device must be +The ``SIM800L`` Component provides the ability to dial, send and receive SMS text messages. The device must be connected via a :doc:`UART bus ` supporting both receiving and transmitting line. The UART bus must be configured at the same speed of the module which is by default 9600bps. The required connection wires are ``+VCC``, ``GND``, ``RX`` and ``TX``. @@ -92,11 +92,24 @@ Send a SMS message to a phone recipient using this action in automations. message: !lambda |- return id(reed_switch).state ? "Door is now OPEN" : "Hey door just CLOSED"; + +.. _sim800l-dial_action: + +``sim800l.dial`` Action +--------------------------- + +Dial to a phone recipient using this action in automations. + +.. code-block:: yaml + + on_...: + then: + - sim800l.dial: + recipient: '+15551234567' + Configuration options: -- **recipient** (***Required**, string, :ref:`templatable `): The message recipient. - number. -- **message** (**Required**, string, :ref:`templatable `): The message content. +- **recipient** (***Required**, string, :ref:`templatable `): The number to dial. - **id** (*Optional*, :ref:`config-id`): Manually specify the ID of the SIM800L if you have multiple components. .. note:: @@ -105,14 +118,14 @@ Configuration options: .. code-block:: cpp - id(sim800l1).send_sms("+15551234567", "The message content"); + id(sim800l1).dial("+15551234567"); Getting started with Home Assistant ----------------------------------- The following code will get you up and running with a configuration updating received messages -on Home Assistant and will also setup a service so you can send messages with your SIM800L. +on Home Assistant and will also setup a service so you can send messages and dial with your SIM800L. .. code-block:: yaml @@ -126,6 +139,12 @@ on Home Assistant and will also setup a service so you can send messages with yo - sim800l.send_sms: recipient: !lambda 'return recipient;' message: !lambda 'return message;' + - service: dial + variables: + recipient: string + then: + - sim800l.dial: + recipient: !lambda 'return recipient;' text_sensor: - platform: template @@ -159,6 +178,9 @@ To trigger the automation from Home Assistant you can invoke the service with th data: recipient: "+15551234567" message: "Hello World!" + - service: esphome.livingroom_dial + data: + recipient: "+15551234567" Relay management commands received from an authorized sender: diff --git a/components/sn74hc595.rst b/components/sn74hc595.rst index 0bae6b13c..21ce5b213 100644 --- a/components/sn74hc595.rst +++ b/components/sn74hc595.rst @@ -43,7 +43,7 @@ Use of the OE pin is optional. If used, the pin should be pulled up externally. inverted: False Configuration variables: -~~~~~~~~~~~~~~~~~~~~~~~~ +************************ - **id** (**Required**, :ref:`config-id`): The id to use for this SN74HC595 component. - **data_pin** (**Required**, :ref:`Pin Schema `): Pin connected to SN74HC595 SER input. @@ -52,11 +52,21 @@ Configuration variables: - **oe_pin** (*Optional*, :ref:`Pin Schema `): Pin connected to SN74HC595 OE pin - **sr_count** (*Optional*, int): Number of daisy-chained shift registers, up-to 4. Defaults to ``1``. + +Pin configuration variables: +**************************** + +- **sn74hc595** (**Required**, :ref:`config-id`): The id of the SN74HC595 component of the pin. +- **number** (**Required**, integer): The pin number. +- **inverted** (*Optional*, boolean): If all written values should be treated as inverted. + Defaults to ``False``. + + See Also -------- - :doc:`switch/gpio` - :doc:`binary_sensor/gpio` -- `Serial to Parallel Shifting-Out with a 74HC595 ` +- `Serial to Parallel Shifting-Out with a 74HC595 `__ - :apiref:`sn74hc595/sn74hc595.h` - :ghedit:`Edit` diff --git a/components/stepper/index.rst b/components/stepper/index.rst index 3ce05815a..54b27dc4d 100644 --- a/components/stepper/index.rst +++ b/components/stepper/index.rst @@ -16,8 +16,27 @@ and ULN2003 (`datasheet `__) are This component will not show up in the Home Assistant front-end automatically because Home Assistant doesn't have support for steppers. Please see :ref:`stepper-ha-config`. -A4988 Configuration -------------------- +.. _base_stepper_config: + +Base Stepper Configuration +-------------------------- + +All stepper configuration schemas inherit these options. + +Configuration variables: + +- **max_speed** (**Required**, float): The maximum speed in ``steps/s`` (steps per seconds) to drive the + stepper at. Note most steppers can't step properly with speeds higher than 250 steps/s. +- **acceleration** (*Optional*, float): The acceleration in ``steps/s^2`` (steps per seconds squared) + to use when starting to move. The default is ``inf`` which means infinite acceleration, so the + stepper will try to drive with the full speed immediately. This value is helpful if that first motion of + the motor is too jerky for what it's moving. If you make this a small number, it will take the motor a + moment to get up to speed. +- **deceleration** (*Optional*, float): The same as ``acceleration``, but for when the motor is decelerating + shortly before reaching the set position. Defaults to ``inf`` (immediate deceleration). + +A4988 Component +--------------- Put this code into the configuration file on ESPhome for this device. @@ -43,16 +62,11 @@ Configuration variables: stepper driver. - **dir_pin** (**Required**, :ref:`Pin Schema `): The ``DIRECTION`` pin of the A4988 stepper driver. -- **max_speed** (**Required**, float): The maximum speed in ``steps/s`` (steps per seconds) to drive the - stepper at. Note most steppers can't step properly with speeds higher than 250 steps/s. - **sleep_pin** (*Optional*, :ref:`Pin Schema `): Optionally also use the ``SLEEP`` pin of the A4988 stepper driver. If specified, the driver will be put into sleep mode as soon as the stepper reaches the target steps. -- **acceleration** (*Optional*, float): The acceleration in ``steps/s^2`` (steps per seconds squared) - to use when starting to move. The default is ``inf`` which means infinite acceleration, so the - stepper will try to drive with the full speed immediately. -- **deceleration** (*Optional*, float): The same as ``acceleration``, but for when the motor is decelerating - shortly before reaching the set position. Defaults to ``inf`` (immediate deceleration). + +- All other from :ref:`base_stepper_config`. .. note:: @@ -67,8 +81,8 @@ Configuration variables: number: D1 inverted: True -ULN2003 Configuration ---------------------- +ULN2003 Component +----------------- Put this code into the configuration file on ESPHome for this device. @@ -92,8 +106,10 @@ Put this code into the configuration file on ESPHome for this device. Configuration variables: - **id** (**Required**, :ref:`config-id`): Specify the ID of the stepper so that you can control it. -- **pin_a**, **pin_b**, **pin_c**, **pin_d** (**Required**, :ref:`Pin Schema `): - The four pins of the stepper control board. +- **pin_a** (**Required**, :ref:`Pin Schema `): The pin **a** of the stepper control board. +- **pin_b** (**Required**, :ref:`Pin Schema `): The pin **b** of the stepper control board. +- **pin_c** (**Required**, :ref:`Pin Schema `): The pin **c** of the stepper control board. +- **pin_d** (**Required**, :ref:`Pin Schema `): The pin **d** of the stepper control board. - **sleep_when_done** (*Optional*, boolean): Whether to turn off all coils when the stepper has reached the target position - **step_mode** (*Optional*, string): The step mode to operate the motor with. One of: @@ -102,15 +118,7 @@ Configuration variables: - ``HALF_STEP`` - ``WAVE_DRIVE`` -- **max_speed** (**Required**, float): The maximum speed in ``steps/s`` (steps per seconds) to drive the - stepper at. Note most steppers can't step properly with speeds higher than 250 steps/s. -- **acceleration** (*Optional*, float): The acceleration in ``steps/s^2`` (steps per seconds squared) - to use when starting to move. The default is ``inf`` which means infinite acceleration, so the - stepper will try to drive with the full speed immediately. This value is helpful if that first motion of - the motor is too jerky for what it's moving. If you make this a small number, it will take the motor a - moment to get up to speed. -- **deceleration** (*Optional*, float): The same as ``acceleration``, but for when the motor is decelerating - shortly before reaching the set position. Defaults to ``inf`` (immediate deceleration). +- All other from :ref:`base_stepper_config`. .. _stepper-set_target_action: @@ -141,7 +149,7 @@ position (in steps). The stepper will always run towards the target position and Configuration options: - **id** (**Required**, :ref:`config-id`): The ID of the stepper. -- **target** (*Optional*, int, :ref:`templatable `): The target position in steps. +- **target** (**Required**, int, :ref:`templatable `): The target position in steps. .. warning:: @@ -195,10 +203,10 @@ the target again. return -1000; } -Configuration options: +Configuration variables: - **id** (**Required**, :ref:`config-id`): The ID of the stepper. -- **target** (*Optional*, int, :ref:`templatable `): The target position in steps. +- **position** (**Required**, int, :ref:`templatable `): The position to report in steps. .. _stepper-set_speed_action: @@ -225,11 +233,11 @@ Configuration variables: Home Assistant Configuration ---------------------------- -This component will not show up in the Home Assistant front-end (Overview) automatically because +This component will not show up in the Home Assistant front-end (Overview) automatically because Home Assistant does not support steppers natively. You can add the stepper component code below to your Home Assistant configuration (``configuration.yaml``) to -be able to control the stepper from the front-end. +be able to control the stepper from the front-end. .. code-block:: yaml @@ -242,7 +250,7 @@ be able to control the stepper from the front-end. max: 1000 step: 1 mode: slider - + # Do something when the slider changes automation: - alias: Write Stepper Value to ESP @@ -255,18 +263,18 @@ be able to control the stepper from the front-end. data_template: target: '{{ trigger.to_state.state | int }}' -In the above code, "stepper_control" is the ID of a numeric input field. It must be unique and it is -used in the automation section as a reference name. The display name for this field is in -stepper_control's ``name`` key. +In the above code, "stepper_control" is the ID of a numeric input field. It must be unique and it is +used in the automation section as a reference name. The display name for this field is in +stepper_control's ``name`` key. -If you want your user interface to give you more control over your stepper controller, such as +If you want your user interface to give you more control over your stepper controller, such as setting the acceleration, deceleration, etc, then you can add more input fields after ``stepper_control`` but before ``automation``. They can be a simple number-entry field (mode: box) or a slider like this. Each of these extra input fields needs an associated input parameter defined on the ESPHome device's API service. The automation section tells Home Assistant what to do when the slider changes. It needs a trigger -(state of the ``stepper_control`` slider) and an action. In the trigger section, ``entity_id`` must refer +(state of the ``stepper_control`` slider) and an action. In the trigger section, ``entity_id`` must refer back to the configuration ID that triggers the automation. For us, that is the ``stepper_control`` field in the ``input_number`` item. That's why the value is ``input_number.stepper_control``. @@ -276,7 +284,7 @@ the correct syntax is to join the device ID to the API service ID with an unders as in ``esphome.livingroom_control_stepper`` where "Livingroom" is a device in ESPHome and "control_stepper" is an API service for that device. -The template string is used to get the "state" value from the ``target`` field (defined in the target section) on the +The template string is used to get the "state" value from the ``target`` field (defined in the target section) on the ``input_number`` component of the Home Assistant front-end. This value is then passed to the API service as defined in the ESPHome device's configuration. The ``data_template`` section lists one value for each of the input parameters on the service being called by the automation. In our case, the ESPHome device has an API service with a single parameter, @@ -285,7 +293,7 @@ Getting this linkage right is very important. The following code needs to go in the ESPHome configuration file for this device. Above, we mention "API service" a lot. This code is where that is defined. You may have already added it (or something similar). Note -that the input variable for the ``control_stepper`` service is called ``target``. That's what matches with the +that the input variable for the ``control_stepper`` service is called ``target``. That's what matches with the automation configuration above. Also note that the variable ``target`` is defined as an integer. That means it must be an integer number, not a string. diff --git a/components/sun.rst b/components/sun.rst index 345063255..dda62a5a3 100644 --- a/components/sun.rst +++ b/components/sun.rst @@ -57,8 +57,8 @@ Automation: - **elevation** (*Optional*, float): The elevation to cross. Defaults to 0° (horizon). -Sensor Platform ---------------- +``sun`` Sensor +-------------- Additionally, the sun component exposes its values over a sensor platform. @@ -85,8 +85,8 @@ Configuration variables: - **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation. - All other options from :ref:`Sensor `. -Text Sensor Platform --------------------- +``sun`` Text Sensor +------------------- Other properties like the next sunset time can be read out with the sun text_sensor platform. diff --git a/components/switch/uart.rst b/components/switch/uart.rst index 3a875751b..4aefa9344 100644 --- a/components/switch/uart.rst +++ b/components/switch/uart.rst @@ -22,6 +22,10 @@ The ``uart`` switch platform allows you to send a pre-defined sequence of bytes - platform: uart name: "UART Bytes Output" data: [0xDE, 0xAD, 0xBE, 0xEF] + - platform: uart + name: "UART Recurring Output" + data: [0xDE, 0xAD, 0xBE, 0xEF] + send_every: 1s Configuration variables: ------------------------ @@ -31,6 +35,7 @@ Configuration variables: - **name** (**Required**, string): The name for the switch. - **uart_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the UART hub. - **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation. +- **send_every** (*Optional*, :ref:`config-time`): Sends recurring data instead of sending once. - All other options from :ref:`Switch `. See Also diff --git a/components/sx1509.rst b/components/sx1509.rst index 1d213d192..0da937534 100644 --- a/components/sx1509.rst +++ b/components/sx1509.rst @@ -41,8 +41,8 @@ complicated components that use the pin schema will not work. For example the I scan_time: 2 debounce_time: 1 -Configuration variables for the SX1509 device: ----------------------------------------------- +Configuration variables: +------------------------ - **id** (**Required**, :ref:`config-id`): The id to use for this SX1509 component. - **address** (*Optional*, int): The I²C address of the driver. @@ -53,9 +53,9 @@ up to 8x8 matrix (i.e. 64 keys). - **keypad** (*Optional*): Add this to enable the keypad. - - **key_row** (*Required*, int): The number of keypad rows to use. This enables any number of the first 7 pins. + - **key_rows** (**Required**, int): The number of keypad rows to use. This enables any number of the first 7 pins. So a value of 3 enables pins 0,1,2 to be used as the rows for the keypad matrix. This value must be between 1 and 8. - - **key_columns** (*Required*, int): The number of keypad columns to use. This enables any number of the last 7 pins. + - **key_columns** (**Required**, int): The number of keypad columns to use. This enables any number of the last 7 pins. So a value of 4 enables pins 8,9,10,11 to be used as the columns for the keypad matrix. This value must be between 1 and 8. - **sleep_time** (*Optional*, int): No key press within this time will set keypad engine to sleep. - **scan_time** (*Optional*, int): Scan time per row (must be set above debounce time). @@ -108,6 +108,9 @@ Attention should be paid to the capabilities of the I/O pins. | 15 | ✓ | | ✓ | +-----+------------------+-----+--------+ +Binary Sensor +============= + To use the individual keys on the keypad you need to add individual binary_sensor entries in the config. .. code-block:: yaml @@ -125,12 +128,16 @@ To use the individual keys on the keypad you need to add individual binary_senso row: 0 col: 1 -Configuration variables for the SX1509 keypad keys: ---------------------------------------------------- +Configuration variables: +------------------------ - **row** (**Required**, int): The row number for this key on the keypad. - **col** (**Required**, int): The column number for this key on the keypad. + +Pin configuration variables: +---------------------------- + With the following configuration items you may use the individual pins of the SX1509 as the pins for binary_sensor, switch, or output. The outputs can in turn be used to add PWM-enabled lights like the monochromatic light. @@ -174,7 +181,14 @@ The outputs can in turn be used to add PWM-enabled lights like the monochromatic name: "light0" output: sx1509_output -- All other options from :ref:`Output `. + +- **sx1509** (**Required**, :ref:`config-id`): The id of the SX1509 component of the pin. +- **number** (**Required**, integer): The pin number. +- **inverted** (*Optional*, boolean): If all read and written values + should be treated as inverted. Defaults to ``False``. +- **mode** (*Optional*, string): A pin mode to set for the pin at. One of ``INPUT``, + ``INPUT_PULLUP`` or ``OUTPUT``. + And naturally you may use all automation functions with these SX1509 binary_sensors, switches and output (lights). diff --git a/components/time.rst b/components/time.rst index 263787efc..9d61eb48a 100644 --- a/components/time.rst +++ b/components/time.rst @@ -215,8 +215,8 @@ Configuration variables: - All other from :ref:`base_time_config`. -SNTP Configuration ------------------- +SNTP Time Source +---------------- .. code-block:: yaml @@ -234,7 +234,7 @@ Configuration variables: .. note:: If your are using :ref:`wifi-manual_ip` make sure to configure a DNS Server (dns1, dns2) or use only IP addresses for the NTP servers. - + .. warning:: Due to limitations of the SNTP implementation, this component will trigger ``on_time_sync`` only once when it detects that the diff --git a/components/uart.rst b/components/uart.rst index 064c3c882..50bc100dc 100644 --- a/components/uart.rst +++ b/components/uart.rst @@ -52,6 +52,10 @@ Configuration variables: - **stop_bits** (*Optional*, int): The number of stop bits to send. Options: 1, 2. Defaults to 1. - **id** (*Optional*, :ref:`config-id`): Manually specify the ID for this UART hub if you need multiple UART hubs. +ESP32 options: + +- **invert** (*Optional*, boolean): Invert the logic levels of the RX and TX pins. Options: ``True`` or ``False``. Defaults to ``False``. + .. _uart-hardware_uarts: Hardware UARTs diff --git a/components/wifi.rst b/components/wifi.rst index a4738e46c..4a3a9b083 100644 --- a/components/wifi.rst +++ b/components/wifi.rst @@ -38,9 +38,9 @@ Configuration variables: that is reachable will be connected to. See :ref:`wifi-networks`. - **manual_ip** (*Optional*): Manually configure the static IP of the node. - - **static_ip** (*Required*, IPv4 address): The static IP of your node. - - **gateway** (*Required*, IPv4 address): The gateway of the local network. - - **subnet** (*Required*, IPv4 address): The subnet of the local network. + - **static_ip** (**Required**, IPv4 address): The static IP of your node. + - **gateway** (**Required**, IPv4 address): The gateway of the local network. + - **subnet** (**Required**, IPv4 address): The subnet of the local network. - **dns1** (*Optional*, IPv4 address): The main DNS server to use. - **dns2** (*Optional*, IPv4 address): The backup DNS server to use. @@ -49,8 +49,8 @@ Configuration variables: - **ap** (*Optional*): Enable an access point mode on the node. - - **ssid** (*Required*, string): The name of the access point to create. - - **password** (*Optional* string): The password for the access point. Leave empty for + - **ssid** (**Required**, string): The name of the access point to create. + - **password** (*Optional*, string): The password for the access point. Leave empty for no password. - **channel** (*Optional*, int): The channel the AP should operate on from 1 to 14. Defaults to 1. diff --git a/conf.py b/conf.py index a49fa08ab..357202291 100644 --- a/conf.py +++ b/conf.py @@ -22,14 +22,10 @@ # sys.path.insert(0, os.path.abspath('.')) import hashlib import os -import subprocess -from sphinx import addnodes -from sphinx.util.docfields import Field, GroupedField -import re import sys -sys.path.append(os.path.abspath('.')) +sys.path.append(os.path.abspath(".")) # -- General configuration ------------------------------------------------ @@ -41,58 +37,59 @@ sys.path.append(os.path.abspath('.')) # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'github', - 'seo', - 'sitemap', + "github", + "seo", + "sitemap", + "schema_doc", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ".rst" # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = 'ESPHome' -copyright = '2019, Otto Winter' +project = "ESPHome" +copyright = "2019, Otto Winter" html_show_copyright = False html_show_sphinx = False -author = 'Otto Winter' +author = "Otto Winter" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '1.16' +version = "1.17" # The full version, including alpha/beta/rc tags. -release = '1.16.2' +release = "1.17.0b1" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = 'en' +language = "en" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # The reST default role (used for this markup: `text`) to use for all documents. # default_role = 'cpp:any' # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'xcode' +pygments_style = "xcode" -highlight_language = 'yaml' +highlight_language = "yaml" primary_domain = None @@ -105,40 +102,40 @@ todo_include_todos = False # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +html_theme = "alabaster" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # -html_baseurl = os.getenv('BASE_URL', 'https://esphome.io') -with open('_static/custom.css', 'rb') as f: +html_baseurl = os.getenv("BASE_URL", "https://esphome.io") +with open("_static/custom.css", "rb") as f: custom_css_hash = hashlib.md5(f.read()).hexdigest()[:8] html_theme_options = { # 'logo': 'logo-full.png', - 'logo_name': False, - 'show_related': False, - 'sidebar_collapse': True, - 'fixed_sidebar': True, - 'show_powered_by': False, + "logo_name": False, + "show_related": False, + "sidebar_collapse": True, + "fixed_sidebar": True, + "show_powered_by": False, } html_context = { - 'custom_css_hash': custom_css_hash, + "custom_css_hash": custom_css_hash, } -html_logo = 'images/logo-text.svg' +html_logo = "images/logo-text.svg" html_copy_source = True html_show_sourcelink = False html_last_updated_fmt = None html_use_smartypants = False -html_title = 'ESPHome' +html_title = "ESPHome" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Custom sidebar templates, must be a dictionary that maps document names # to template names. @@ -146,10 +143,10 @@ html_static_path = ['_static'] # This is required for the alabaster theme # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars html_sidebars = { - '**': [ + "**": [ # 'about.html', - 'searchbox.html', - 'localtoc.html', + "searchbox.html", + "localtoc.html", ] } @@ -157,7 +154,7 @@ html_sidebars = { # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. -htmlhelp_basename = 'esphomedoc' +htmlhelp_basename = "esphomedoc" # -- Options for LaTeX output --------------------------------------------- @@ -166,15 +163,12 @@ latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. # # 'preamble': '', - # Latex figure (float) alignment # # 'figure_align': 'htbp', @@ -184,21 +178,17 @@ latex_elements = { # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'esphome.tex', 'ESPHome Documentation', - 'Otto Winter', 'manual'), + (master_doc, "esphome.tex", "ESPHome Documentation", "Otto Winter", "manual"), ] -latex_engine = 'xelatex' +latex_engine = "xelatex" # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'esphome', 'ESPHome Documentation', - [author], 1) -] +man_pages = [(master_doc, "esphome", "ESPHome Documentation", [author], 1)] # -- Options for Texinfo output ------------------------------------------- @@ -207,8 +197,14 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'esphome', 'ESPHome Documentation', - author, 'esphome', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "esphome", + "ESPHome Documentation", + author, + "esphome", + "One line description of project.", + "Miscellaneous", + ), ] -linkcheck_ignore = [r'https://github.com/.*', r'https://discord.gg/.*'] +linkcheck_ignore = [r"https://github.com/.*", r"https://discord.gg/.*"] diff --git a/components/text_sensor/uart.rst b/cookbook/uart_text_sensor.rst similarity index 100% rename from components/text_sensor/uart.rst rename to cookbook/uart_text_sensor.rst diff --git a/custom/custom_component.rst b/custom/custom_component.rst index 3c83c50c0..926e54c34 100644 --- a/custom/custom_component.rst +++ b/custom/custom_component.rst @@ -54,6 +54,9 @@ Configuration variables: - **lambda** (**Required**, :ref:`lambda `): The lambda to run for instantiating the binary sensor(s). +- **components** (*Optional*, list): A list of components to initialize. The length here + must equal the number of items in the ``return`` statement of the ``lambda``. This is useful + if you need to give an ``id`` to the component you created. See also :apiclass:`Component`. diff --git a/github.py b/github.py index b0e986710..a9e3f14d0 100644 --- a/github.py +++ b/github.py @@ -9,39 +9,35 @@ from docutils.parsers.rst import directives from docutils.parsers.rst.directives.tables import Table -def libpr_role(name, rawtext, text, lineno, inliner, options=None, - content=None): - ref = 'https://github.com/esphome/esphome-core/pull/{}'.format(text) - return [make_link_node(rawtext, 'core#{}'.format(text), ref, options)], [] +def libpr_role(name, rawtext, text, lineno, inliner, options=None, content=None): + ref = "https://github.com/esphome/esphome-core/pull/{}".format(text) + return [make_link_node(rawtext, "core#{}".format(text), ref, options)], [] -def yamlpr_role(name, rawtext, text, lineno, inliner, options=None, - content=None): - ref = 'https://github.com/esphome/esphome/pull/{}'.format(text) - return [make_link_node(rawtext, 'esphome#{}'.format(text), ref, options)], [] +def yamlpr_role(name, rawtext, text, lineno, inliner, options=None, content=None): + ref = "https://github.com/esphome/esphome/pull/{}".format(text) + return [make_link_node(rawtext, "esphome#{}".format(text), ref, options)], [] -def docspr_role(name, rawtext, text, lineno, inliner, options=None, - content=None): - ref = 'https://github.com/esphome/esphome-docs/pull/{}'.format(text) - return [make_link_node(rawtext, 'docs#{}'.format(text), ref, options)], [] +def docspr_role(name, rawtext, text, lineno, inliner, options=None, content=None): + ref = "https://github.com/esphome/esphome-docs/pull/{}".format(text) + return [make_link_node(rawtext, "docs#{}".format(text), ref, options)], [] -def ghuser_role(name, rawtext, text, lineno, inliner, options=None, - content=None): - ref = 'https://github.com/{}'.format(text) - return [make_link_node(rawtext, '@{}'.format(text), ref, options)], [] +def ghuser_role(name, rawtext, text, lineno, inliner, options=None, content=None): + ref = "https://github.com/{}".format(text) + return [make_link_node(rawtext, "@{}".format(text), ref, options)], [] -value_re = re.compile(r'^(.*)\s*<(.*)>$') +value_re = re.compile(r"^(.*)\s*<(.*)>$") DOXYGEN_LOOKUP = {} for s in string.ascii_lowercase + string.digits: DOXYGEN_LOOKUP[s] = s for s in string.ascii_uppercase: - DOXYGEN_LOOKUP[s] = '_{}'.format(s.lower()) -DOXYGEN_LOOKUP[':'] = '_1' -DOXYGEN_LOOKUP['_'] = '__' -DOXYGEN_LOOKUP['.'] = '_8' + DOXYGEN_LOOKUP[s] = "_{}".format(s.lower()) +DOXYGEN_LOOKUP[":"] = "_1" +DOXYGEN_LOOKUP["_"] = "__" +DOXYGEN_LOOKUP["."] = "_8" def split_text_value(value): @@ -52,60 +48,57 @@ def split_text_value(value): def encode_doxygen(value): - value = value.split('/')[-1] + value = value.split("/")[-1] try: - return ''.join(DOXYGEN_LOOKUP[s] for s in value) + return "".join(DOXYGEN_LOOKUP[s] for s in value) except KeyError: raise ValueError("Unknown character in doxygen string! '{}'".format(value)) -def apiref_role(name, rawtext, text, lineno, inliner, options=None, - content=None): +def apiref_role(name, rawtext, text, lineno, inliner, options=None, content=None): text, value = split_text_value(text) if text is None: - text = 'API Reference' - ref = '/api/{}.html'.format(encode_doxygen(value)) + text = "API Reference" + ref = "/api/{}.html".format(encode_doxygen(value)) return [make_link_node(rawtext, text, ref, options)], [] -def apiclass_role(name, rawtext, text, lineno, inliner, options=None, - content=None): +def apiclass_role(name, rawtext, text, lineno, inliner, options=None, content=None): text, value = split_text_value(text) if text is None: text = value - ref = '/api/classesphome_1_1{}.html'.format(encode_doxygen(value)) + ref = "/api/classesphome_1_1{}.html".format(encode_doxygen(value)) return [make_link_node(rawtext, text, ref, options)], [] -def apistruct_role(name, rawtext, text, lineno, inliner, options=None, - content=None): +def apistruct_role(name, rawtext, text, lineno, inliner, options=None, content=None): text, value = split_text_value(text) if text is None: text = value - ref = '/api/structesphome_1_1{}.html'.format(encode_doxygen(value)) + ref = "/api/structesphome_1_1{}.html".format(encode_doxygen(value)) return [make_link_node(rawtext, text, ref, options)], [] -def ghedit_role(name, rawtext, text, lineno, inliner, options=None, - content=None): - path = os.path.relpath(inliner.document.current_source, - inliner.document.settings.env.app.srcdir) - ref = 'https://github.com/esphome/esphome-docs/blob/current/{}'.format(path) - return [make_link_node(rawtext, 'Edit this page on GitHub', ref, options)], [] +def ghedit_role(name, rawtext, text, lineno, inliner, options=None, content=None): + path = os.path.relpath( + inliner.document.current_source, inliner.document.settings.env.app.srcdir + ) + ref = "https://github.com/esphome/esphome-docs/blob/current/{}".format(path) + return [make_link_node(rawtext, "Edit this page on GitHub", ref, options)], [] def make_link_node(rawtext, text, ref, options=None): options = options or {} - node = nodes.reference(rawtext, - utils.unescape(text), - refuri=ref, - **options) + node = nodes.reference(rawtext, utils.unescape(text), refuri=ref, **options) return node # https://stackoverflow.com/a/3415150/8924614 def grouper(n, iterable, fillvalue=None): - """grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx""" + """Pythonic way to iterate over sequence, 4 items at a time. + + grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx + """ args = [iter(iterable)] * n return zip_longest(fillvalue=fillvalue, *args) @@ -114,12 +107,11 @@ def grouper(n, iterable, fillvalue=None): class ImageTableDirective(Table): option_spec = { - 'columns': directives.positive_int, + "columns": directives.positive_int, } def run(self): - env = self.state.document.settings.env - cols = self.options.get('columns', 3) + cols = self.options.get("columns", 3) items = [] @@ -129,31 +121,30 @@ class ImageTableDirective(Table): continue name, page, image = row link = page.strip() - if link.startswith('http'): + if link.startswith("http"): pass else: - if not link.startswith('/'): - link = '/{}'.format(link) - if '.html' not in link: - link += '.html' - items.append({ - 'name': name.strip(), - 'link': link, - 'image': '/images/{}'.format(image.strip()), - }) + if not link.startswith("/"): + link = "/{}".format(link) + if ".html" not in link: + link += ".html" + items.append( + { + "name": name.strip(), + "link": link, + "image": "/images/{}".format(image.strip()), + } + ) col_widths = self.get_column_widths(cols) title, messages = self.make_title() table = nodes.table() - table['classes'].append('table-center') + table["classes"].append("table-center") # Set up column specifications based on widths tgroup = nodes.tgroup(cols=cols) table += tgroup - tgroup.extend( - nodes.colspec(colwidth=col_width) - for col_width in col_widths - ) + tgroup.extend(nodes.colspec(colwidth=col_width) for col_width in col_widths) tbody = nodes.tbody() tgroup += tbody @@ -166,12 +157,12 @@ class ImageTableDirective(Table): entry += nodes.paragraph() trow += entry continue - name = cell['name'] - link = cell['link'] - image = cell['image'] + name = cell["name"] + link = cell["link"] + image = cell["image"] reference_node = nodes.reference(refuri=link) img = nodes.image(uri=directives.uri(image), alt=name) - img['classes'].append('component-image') + img["classes"].append("component-image") reference_node += img para = nodes.paragraph() para += reference_node @@ -186,8 +177,8 @@ class ImageTableDirective(Table): entry += nodes.paragraph() trow += entry continue - name = cell['name'] - link = cell['link'] + name = cell["name"] + link = cell["link"] ref = nodes.reference(name, name, refuri=link) para = nodes.paragraph() para += ref @@ -207,8 +198,6 @@ class PinTableDirective(Table): option_spec = {} def run(self): - env = self.state.document.settings.env - items = [] data = list(csv.reader(self.content)) @@ -227,18 +216,14 @@ class PinTableDirective(Table): # Set up column specifications based on widths tgroup = nodes.tgroup(cols=2) table += tgroup - tgroup.extend( - nodes.colspec(colwidth=col_width) - for col_width in col_widths - ) + tgroup.extend(nodes.colspec(colwidth=col_width) for col_width in col_widths) thead = nodes.thead() tgroup += thead trow = nodes.row() thead += trow trow.extend( - nodes.entry(h, nodes.paragraph(text=h)) - for h in ('Pin', 'Function') + nodes.entry(h, nodes.paragraph(text=h)) for h in ("Pin", "Function") ) tbody = nodes.tbody() @@ -269,18 +254,16 @@ class PinTableDirective(Table): def setup(app): - app.add_role('libpr', libpr_role) - app.add_role('corepr', libpr_role) - app.add_role('yamlpr', yamlpr_role) - app.add_role('esphomepr', yamlpr_role) - app.add_role('docspr', docspr_role) - app.add_role('ghuser', ghuser_role) - app.add_role('apiref', apiref_role) - app.add_role('apiclass', apiclass_role) - app.add_role('apistruct', apistruct_role) - app.add_role('ghedit', ghedit_role) - app.add_directive('imgtable', ImageTableDirective) - app.add_directive('pintable', PinTableDirective) - return {"version": "1.0.0", - "parallel_read_safe": True, - "parallel_write_safe": True} + app.add_role("libpr", libpr_role) + app.add_role("corepr", libpr_role) + app.add_role("yamlpr", yamlpr_role) + app.add_role("esphomepr", yamlpr_role) + app.add_role("docspr", docspr_role) + app.add_role("ghuser", ghuser_role) + app.add_role("apiref", apiref_role) + app.add_role("apiclass", apiclass_role) + app.add_role("apistruct", apistruct_role) + app.add_role("ghedit", ghedit_role) + app.add_directive("imgtable", ImageTableDirective) + app.add_directive("pintable", PinTableDirective) + return {"version": "1.0.0", "parallel_read_safe": True, "parallel_write_safe": True} diff --git a/guides/automations.rst b/guides/automations.rst index 1bab12aad..35bbb7279 100644 --- a/guides/automations.rst +++ b/guides/automations.rst @@ -256,8 +256,8 @@ all of the usual lambda syntax. .. _config-globals: -Bonus 2: Global Variables -************************* +Global Variables +---------------- In some cases you might require to share a global variable across multiple lambdas. For example, global variables can be used to store the state of a garage door. @@ -284,7 +284,7 @@ global variables can be used to store the state of a garage door. ESP_LOGD(TAG, "Global value is: %d", id(my_global_int)); -Configuration options: +Configuration variables: - **id** (**Required**, :ref:`config-id`): Give the global variable an ID so that you can refer to it later in :ref:`lambdas `. @@ -300,7 +300,7 @@ Configuration options: .. _automation-networkless: Do Automations Work Without a Network Connection -************************************************ +------------------------------------------------ YES! All automations you define in ESPHome are execute on the ESP itself and will continue to work even if the WiFi network is down or the MQTT server is not reachable. @@ -517,7 +517,7 @@ turns on a light for 5 seconds. Otherwise, the light is turned off immediately. - light.turn_off: my_light -Configuration options: +Configuration variables: - **condition** (**Required**, :ref:`config-condition`): The condition to check which branch to take. See :ref:`Conditions `. - **then** (*Optional*, :ref:`config-action`): The action to perform if the condition evaluates to true. @@ -545,7 +545,7 @@ a block until a given condition evaluates to false. - light.toggle: some_light - delay: 5s -Configuration options: +Configuration variables: - **condition** (**Required**): The condition to check whether to execute. See :ref:`Conditions `. - **then** (**Required**, :ref:`config-action`): The action to perform until the condition evaluates to false. @@ -610,8 +610,8 @@ Configuration variables: variable to. -``script`` ----------- +``script`` Component +-------------------- With the ``script:`` component you can define a list of steps in a central place, and then execute the script with a single call. @@ -627,7 +627,7 @@ execute the script with a single call. - switch.turn_off: my_switch -Configuration options: +Configuration variables: - **id** (**Required**, :ref:`config-id`): The :ref:`config-id` of the script. Use this to interact with the script using the script actions. @@ -759,8 +759,8 @@ Configuration variables: .. _interval: -``interval`` ------------- +``interval`` Component +---------------------- This component allows you to run actions at fixed time intervals. For example if you want to toggle a switch every minute, you can use this component. @@ -775,7 +775,7 @@ trigger, but this technique is more light-weight and user-friendly. then: - switch.toggle: relay_1 -Configuration options: +Configuration variables: - **interval** (**Required**, :ref:`config-time`): The interval to execute the action with. - **then** (**Required**, :ref:`config-action`): The action to perform. diff --git a/guides/configuration-types.rst b/guides/configuration-types.rst index 8a87494bd..4c4f0e21c 100644 --- a/guides/configuration-types.rst +++ b/guides/configuration-types.rst @@ -108,25 +108,6 @@ More exotic Pin Modes are also supported, but rarely used: - ``FUNCTION_5`` (only on ESP32) - ``FUNCTION_6`` (only on ESP32) -.. _config-color: - -Color ------ - -When using RGB-capable displays or LEDs/lighting in ESPHome you may wish to use custom colors. -A ``color`` component exists for just this purpose: - -.. code-block:: yaml - - color: - - id: my_light_red - red: 100% - green: 20% - blue: 25% - white: 0% - -RGB displays use red, green, and blue, while grayscale displays may use white. LEDs or LED-based light bulbs -may use all four color elements depending on their capabilities. .. _config-time: diff --git a/guides/contributing.rst b/guides/contributing.rst index 45ddca6ce..8cf95b127 100644 --- a/guides/contributing.rst +++ b/guides/contributing.rst @@ -31,9 +31,10 @@ The ESPHome documentation is built using `sphinx `__ Syntax ****** -In my opinion, Markdown would have been the much better choice in hindsight, but at the time -I was setting up the documentation good Doxygen integration was key to me. Anyway, here's a quick -RST primer: +Here's a quick RST primer: + +Title hierarchy is based on order of occurence, not on type of character used to underline it. This +documents establish the following character order for better consistency. - **Headers**: You can write titles like this: @@ -547,8 +548,8 @@ loader. These are: has one of them in the config, a validation error will be generated. - ``ESP_PLATFORMS``: Provide a list of allowed ESP types this integration works with. -- ``CODEOWNERS``: GitHub usernames or team names of people that are responsible for this integration. - You should add at least your GitHub username here, as well as anyone who helped you to write code +- ``CODEOWNERS``: GitHub usernames or team names of people that are responsible for this integration. + You should add at least your GitHub username here, as well as anyone who helped you to write code that is being included. Codebase Standards diff --git a/guides/supporters.rst b/guides/supporters.rst index 99dd38928..690ac643f 100644 --- a/guides/supporters.rst +++ b/guides/supporters.rst @@ -94,7 +94,7 @@ that have made it into the `ESPHome organization's ` Author & Main Developer *********************** -- `Otto Winter (@OttoWinter) `__ - 2356 contributions +- `Otto Winter (@OttoWinter) `__ - 2361 contributions Contributors ************ @@ -113,7 +113,6 @@ Contributors - `Attila Darazs (@adarazs) `__ - 2 contributions - `adezerega (@adezerega) `__ - 1 contribution - `Andrea Donno (@adonno) `__ - 1 contribution -- `Adrian Cuzman (@adriancuzman) `__ - 2 contributions - `Johan Bloemberg (@aequitas) `__ - 6 contributions - `Anders (@ahd71) `__ - 1 contribution - `Alexander Pohl (@ahpohl) `__ - 4 contributions @@ -121,6 +120,7 @@ Contributors - `akoivist (@akoivist) `__ - 1 contribution - `Andrej Komelj (@akomelj) `__ - 3 contributions - `Alone (@al-one) `__ - 2 contributions +- `Alex (@alex-richards) `__ - 1 contribution - `Alexander Leisentritt (@Alex9779) `__ - 10 contributions - `Alexandre Danault (@AlexDanault) `__ - 1 contribution - `Alex Mekkering (@AlexMekkering) `__ - 3 contributions @@ -143,13 +143,14 @@ Contributors - `Florian Mösch (@badbadc0ffee) `__ - 10 contributions - `balk77 (@balk77) `__ - 2 contributions - `Paulus Schoutsen (@balloob) `__ - 41 contributions -- `Andrew Zaborowski (@balrog-kun) `__ - 8 contributions +- `Andrew Zaborowski (@balrog-kun) `__ - 9 contributions - `Rutger Nijhuis (@BananaPukeh) `__ - 1 contribution - `J. Nick Koston (@bdraco) `__ - 2 contributions - `Ben Suffolk (@bensuffolk) `__ - 1 contribution - `Bierchermuesli (@Bierchermuesli) `__ - 1 contribution -- `Jim Ekman (@blejdfist) `__ - 4 contributions +- `Jim Ekman (@blejdfist) `__ - 6 contributions - `Mauricio Bonani (@bonanitech) `__ - 1 contribution +- `boradwell (@boradwell) `__ - 1 contribution - `Patrik Hermansson (@bphermansson) `__ - 1 contribution - `Bram Kragten (@bramkragten) `__ - 2 contributions - `Brad Davidson (@brandond) `__ - 19 contributions @@ -165,6 +166,7 @@ Contributors - `chris-jennings (@chris-jennings) `__ - 1 contribution - `John (@CircuitSetup) `__ - 5 contributions - `Chris Debenham (@cjd) `__ - 1 contribution +- `Cody James (@codyjamestechnical) `__ - 1 contribution - `James Crook (@cooljimy84) `__ - 1 contribution - `Corban Mailloux (@corbanmailloux) `__ - 5 contributions - `Dmitry Berezovsky (@corvis) `__ - 2 contributions @@ -187,12 +189,14 @@ Contributors - `David De Sloovere (@DavidDeSloovere) `__ - 3 contributions - `David Beitey (@davidjb) `__ - 1 contribution - `David Zovko (@davidzovko) `__ - 1 contribution +- `dckiller51 (@dckiller51) `__ - 1 contribution - `Debashish Sahu (@debsahu) `__ - 1 contribution - `declanshanaghy (@declanshanaghy) `__ - 3 contributions - `deftdawg (@deftdawg) `__ - 1 contribution +- `Christiaan Blom (@Deinara) `__ - 1 contribution - `Rsan (@deltazerorsan) `__ - 1 contribution - `Mickaël Le Baillif (@demikl) `__ - 3 contributions -- `dependabot[bot] (@dependabot[bot]) `__ - 43 contributions +- `dependabot[bot] (@dependabot[bot]) `__ - 53 contributions - `Destix (@Destix) `__ - 1 contribution - `Alain Turbide (@Dilbert66) `__ - 2 contributions - `Mark (@Diramu) `__ - 1 contribution @@ -202,6 +206,7 @@ Contributors - `Marcos Pérez Ferro (@djwmarcx) `__ - 2 contributions - `Dan Mannock (@dmannock) `__ - 1 contribution - `dmkif (@dmkif) `__ - 1 contribution +- `DrZoid (@docteurzoidberg) `__ - 1 contribution - `Jiang Sheng (@doskoi) `__ - 1 contribution - `Robert Schütz (@dotlambda) `__ - 3 contributions - `Daniel Hyles (@DotNetDann) `__ - 4 contributions @@ -209,10 +214,12 @@ Contributors - `Drew Perttula (@drewp) `__ - 2 contributions - `DrRob (@DrRob) `__ - 1 contribution - `dubit0 (@dubit0) `__ - 1 contribution +- `Sergey V. DUDANOV (@dudanov) `__ - 1 contribution - `Dimitris Zervas (@dzervas) `__ - 2 contributions - `dziobson (@dziobson) `__ - 1 contribution - `Dan Jackson (@e28eta) `__ - 1 contribution - `Ermanno Baschiera (@ebaschiera) `__ - 1 contribution +- `Robert Resch (@edenhaus) `__ - 1 contribution - `Niclas Larsson (@edge90) `__ - 1 contribution - `Eenoo (@Eenoo) `__ - 1 contribution - `Erwin Kooi (@egeltje) `__ - 2 contributions @@ -230,12 +237,12 @@ Contributors - `Eric Hiller (@erichiller) `__ - 1 contribution - `Ernst Klamer (@Ernst79) `__ - 1 contribution - `escoand (@escoand) `__ - 7 contributions -- `esphomebot (@esphomebot) `__ - 15 contributions +- `esphomebot (@esphomebot) `__ - 16 contributions - `Evan Coleman (@evandcoleman) `__ - 3 contributions - `Malte Franken (@exxamalte) `__ - 2 contributions - `Fabian Affolter (@fabaff) `__ - 29 contributions - `C W (@fake-name) `__ - 2 contributions -- `Christian Ferbar (@ferbar) `__ - 2 contributions +- `Christian Ferbar (@ferbar) `__ - 3 contributions - `fkirill (@fkirill) `__ - 1 contribution - `foxsam21 (@foxsam21) `__ - 2 contributions - `Fractal147 (@Fractal147) `__ - 1 contribution @@ -249,13 +256,14 @@ Contributors - `Fritz Mueller (@fritzm) `__ - 1 contribution - `Marc Egli (@frog32) `__ - 1 contribution - `mr G1K (@G1K) `__ - 2 contributions +- `Gabe Cook (@gabe565) `__ - 2 contributions - `galagaking (@galagaking) `__ - 1 contribution - `Geoff Davis (@geoffdavis) `__ - 2 contributions - `Gerard (@gerard33) `__ - 2 contributions - `Giovanni (@Gio-dot) `__ - 2 contributions - `gitolicious (@gitolicious) `__ - 16 contributions - `The Gitter Badger (@gitter-badger) `__ - 1 contribution -- `Guillermo Ruffino (@glmnet) `__ - 202 contributions +- `Guillermo Ruffino (@glmnet) `__ - 240 contributions - `Giorgos Logiotatidis (@glogiotatidis) `__ - 1 contribution - `Germain Masse (@gmasse) `__ - 2 contributions - `Jelle Raaijmakers (@GMTA) `__ - 1 contribution @@ -283,6 +291,7 @@ Contributors - `Ivan Shvedunov (@ivan4th) `__ - 1 contribution - `Ivan Kravets (@ivankravets) `__ - 1 contribution - `Ivo-tje (@Ivo-tje) `__ - 1 contribution +- `Jakob Reiter (@jakommo) `__ - 1 contribution - `James Gao (@jamesgao) `__ - 1 contribution - `Jan Pieper (@janpieper) `__ - 2 contributions - `Jason-nz (@Jason-nz) `__ - 1 contribution @@ -291,7 +300,7 @@ Contributors - `Joshua Dadswell (@jdads1) `__ - 1 contribution - `jeff-h (@jeff-h) `__ - 2 contributions - `Jeff Rescignano (@JeffResc) `__ - 11 contributions -- `Jesse Hills (@jesserockz) `__ - 119 contributions +- `Jesse Hills (@jesserockz) `__ - 133 contributions - `Jérémy JOURDIN (@JJK801) `__ - 1 contribution - `Jonathan Jefferies (@jjok) `__ - 1 contribution - `Justin Maxwell (@jkmaxwell) `__ - 1 contribution @@ -306,20 +315,22 @@ Contributors - `Joppy (@JoppyFurr) `__ - 2 contributions - `junnikokuki (@junnikokuki) `__ - 1 contribution - `Justahobby01 (@Justahobby01) `__ - 1 contribution +- `Mike Ryan (@justfalter) `__ - 1 contribution - `Justin Gerhardt (@justin-gerhardt) `__ - 1 contribution - `Justyn Shull (@justyns) `__ - 1 contribution - `Jasper van der Neut - Stulen (@jvanderneutstulen) `__ - 2 contributions - `João Vitor M. Roma (@jvmr1) `__ - 1 contribution - `Jack Wozny (@jwozny) `__ - 1 contribution -- `Kris (@K-r-i-s-t-i-a-n) `__ - 1 contribution +- `Kris (@K-r-i-s-t-i-a-n) `__ - 2 contributions - `Harald Nagel (@k7hpn) `__ - 2 contributions - `kalebzettl (@kalebzettl) `__ - 1 contribution - `Krasimir Nedelchev (@kaykayehnn) `__ - 1 contribution - `kbouchard111 (@kbouchard111) `__ - 1 contribution -- `Keith Burzinski (@kbx81) `__ - 26 contributions +- `Keith Burzinski (@kbx81) `__ - 27 contributions - `Robert Kiss (@kepten) `__ - 2 contributions - `Kevin O'Rourke (@kevinior) `__ - 1 contribution - `kimonm (@kimonm) `__ - 1 contribution +- `Kurt Kellner (@kkellner) `__ - 1 contribution - `Klaas Schoute (@klaasnicolaas) `__ - 1 contribution - `Klarstein (@Klarstein) `__ - 3 contributions - `Kevin Lewis (@kll) `__ - 1 contribution @@ -339,20 +350,23 @@ Contributors - `Steffen Weinreich (@lairsdragon) `__ - 1 contribution - `Fredrik Lindqvist (@Landrash) `__ - 1 contribution - `lein1013 (@lein1013) `__ - 1 contribution +- `Riku Lindblad (@lepinkainen) `__ - 1 contribution - `Lazar Obradovic (@lobradov) `__ - 4 contributions -- `Joakim Sørensen (@ludeeus) `__ - 11 contributions +- `Joakim Sørensen (@ludeeus) `__ - 12 contributions - `Lukas Klass (@LukasK13) `__ - 1 contribution +- `lukaszrud (@lukaszrud) `__ - 1 contribution - `Lumpusz (@Lumpusz) `__ - 2 contributions - `Luke Fitzgerald (@lwfitzgerald) `__ - 1 contribution - `Lewis Juggins (@lwis) `__ - 1 contribution - `Michael Klamminger (@m1ch) `__ - 1 contribution - `M95D (@M95D) `__ - 1 contribution - `Marc-Antoine Courteau (@macourteau) `__ - 1 contribution +- `Massimiliano Ravelli (@madron) `__ - 1 contribution - `magnus (@magnusja) `__ - 1 contribution - `Magnus Øverli (@magnusoverli) `__ - 1 contribution - `Major Péter (@majorpeter) `__ - 2 contributions - `Marcel van der Veldt (@marcelveldt) `__ - 2 contributions -- `marecabo (@marecabo) `__ - 2 contributions +- `marecabo (@marecabo) `__ - 4 contributions - `Marvin Gaube (@margau) `__ - 4 contributions - `Martynas Griškonis (@Margriko) `__ - 1 contribution - `Mario (@mario-tux) `__ - 3 contributions @@ -361,7 +375,7 @@ Contributors - `Martin Hjelmare (@MartinHjelmare) `__ - 1 contribution - `MartinWelsch (@MartinWelsch) `__ - 1 contribution - `MasterTim17 (@MasterTim17) `__ - 1 contribution -- `matikij (@matikij) `__ - 1 contribution +- `matikij (@matikij) `__ - 2 contributions - `Michel Marti (@matoxp) `__ - 4 contributions - `Maurice Schleußinger (@maurice-schleussinger) `__ - 1 contribution - `mbo18 (@mbo18) `__ - 1 contribution @@ -374,6 +388,7 @@ Contributors - `micw (@micw) `__ - 1 contribution - `Pauline Middelink (@middelink) `__ - 2 contributions - `mikosoft83 (@mikosoft83) `__ - 1 contribution +- `Minideezel (@minideezel) `__ - 1 contribution - `Matthew Edwards (@mje-nz) `__ - 1 contribution - `Maarten (@mjkl-gh) `__ - 1 contribution - `mjoshd (@mjoshd) `__ - 2 contributions @@ -382,6 +397,7 @@ Contributors - `mnaz (@mnaz) `__ - 1 contribution - `Michael Nieß (@mniess) `__ - 1 contribution - `Matt N. (@mnoorenberghe) `__ - 1 contribution +- `Moritz Glöckl (@moritzgloeckl) `__ - 1 contribution - `morph027 (@morph027) `__ - 1 contribution - `Matthew Pettitt (@mpettitt) `__ - 1 contribution - `Ryan Matthews (@mrrsm) `__ - 1 contribution @@ -395,14 +411,16 @@ Contributors - `Oskar Napieraj (@napieraj) `__ - 7 contributions - `Bergont Nicolas (@nbergont) `__ - 1 contribution - `Nebula (@nebula-it) `__ - 1 contribution +- `needspeed (@needspeed) `__ - 1 contribution - `nepozs (@nepozs) `__ - 1 contribution - `nickrout (@nickrout) `__ - 1 contribution - `Nick Whyte (@nickw444) `__ - 3 contributions - `nicuh (@nicuh) `__ - 1 contribution -- `nikito7 (@nikito7) `__ - 2 contributions +- `nikito7 (@nikito7) `__ - 3 contributions - `Zvonimir Haramustek (@nitko12) `__ - 1 contribution - `Nikolay Kitanov (@nkitanov) `__ - 1 contribution - `nldroid (@nldroid) `__ - 2 contributions +- `Niccolò Maggioni (@nmaggioni) `__ - 1 contribution - `Alex (@nnmalex) `__ - 1 contribution - `ffabi (@norges) `__ - 2 contributions - `Greg Johnson (@notgwj) `__ - 1 contribution @@ -413,6 +431,7 @@ Contributors - `Omar Ghader (@omarghader) `__ - 1 contribution - `Oncleben31 (@oncleben31) `__ - 1 contribution - `Oscar Bolmsten (@oscar-b) `__ - 4 contributions +- `Otamay (@Otamay) `__ - 2 contributions - `Pack3tL0ss (@Pack3tL0ss) `__ - 1 contribution - `Panuruj Khambanonda (PK) (@panuruj) `__ - 2 contributions - `Paul Deen (@PaulAntonDeen) `__ - 2 contributions @@ -423,7 +442,7 @@ Contributors - `perjury (@perjury) `__ - 1 contribution - `Philip Rosenberg-Watt (@PhilRW) `__ - 1 contribution - `phjr (@phjr) `__ - 2 contributions -- `pieterbrink123 (@pieterbrink123) `__ - 1 contribution +- `pieterbrink123 (@pieterbrink123) `__ - 2 contributions - `pille (@pille) `__ - 2 contributions - `pixiandreas (@pixiandreas) `__ - 1 contribution - `Peter Kuehne (@pkuehne) `__ - 5 contributions @@ -457,19 +476,21 @@ Contributors - `Rob de Jonge (@robdejonge) `__ - 1 contribution - `Robin Smidsrød (@robinsmidsrod) `__ - 2 contributions - `RockBomber (@RockBomber) `__ - 1 contribution +- `RoganDawes (@RoganDawes) `__ - 1 contribution - `Jérôme W. (@RomRider) `__ - 1 contribution - `Robbie Page (@rorpage) `__ - 1 contribution -- `rradar (@rradar) `__ - 7 contributions +- `rradar (@rradar) `__ - 8 contributions - `rspaargaren (@rspaargaren) `__ - 7 contributions - `Rubén G. (@rubengargar) `__ - 1 contribution - `rudgr (@rudgr) `__ - 1 contribution - `ryanalden (@ryanalden) `__ - 2 contributions - `Ryan Nazaretian (@ryannazaretian) `__ - 1 contribution +- `samnewman86 (@samnewman86) `__ - 1 contribution - `Sascha (@Scarbous) `__ - 1 contribution - `Nils Schulte (@Schnilz) `__ - 1 contribution - `Ville Skyttä (@scop) `__ - 5 contributions - `sekkr1 (@sekkr1) `__ - 1 contribution -- `SenexCrenshaw (@SenexCrenshaw) `__ - 14 contributions +- `SenexCrenshaw (@SenexCrenshaw) `__ - 17 contributions - `Sergio (@sergio303) `__ - 2 contributions - `Sergio Mayoral Martínez (@sermayoral) `__ - 3 contributions - `sethcohn (@sethcohn) `__ - 1 contribution @@ -478,18 +499,21 @@ Contributors - `shaeed (@shaeed) `__ - 1 contribution - `shbatm (@shbatm) `__ - 1 contribution - `sherbang (@sherbang) `__ - 4 contributions +- `Shish (@shish) `__ - 2 contributions - `SiliconAvatar (@SiliconAvatar) `__ - 1 contribution - `sillyfrog (@sillyfrog) `__ - 1 contribution -- `Derek Hageman (@Sizurka) `__ - 2 contributions +- `Derek Hageman (@Sizurka) `__ - 3 contributions - `Stephen Tierney (@sjtrny) `__ - 1 contribution - `Niklas Wagner (@Skaronator) `__ - 9 contributions - `spattinson (@spattinson) `__ - 1 contribution +- `spilin (@spilin) `__ - 1 contribution - `square99 (@square99) `__ - 2 contributions - `Paul Krischer (@SqyD) `__ - 1 contribution - `sredfern (@sredfern) `__ - 2 contributions - `srg74 (@srg74) `__ - 1 contribution -- `Samuel Sieb (@ssieb) `__ - 15 contributions -- `stubs12 (@stubs12) `__ - 2 contributions +- `Samuel Sieb (@ssieb) `__ - 18 contributions +- `Steve Baxter (@stevebaxter) `__ - 1 contribution +- `stubs12 (@stubs12) `__ - 3 contributions - `Jordan Vohwinkel (@sublime93) `__ - 1 contribution - `Marcel Feix (@Syndlex) `__ - 2 contributions - `Teemu Mikkonen (@T3m3z) `__ - 2 contributions @@ -516,6 +540,7 @@ Contributors - `Tijs-B (@Tijs-B) `__ - 1 contribution - `Tim P (@timpur) `__ - 2 contributions - `Tim Savage (@timsavage) `__ - 7 contributions +- `Max Efremov (@Tmin10) `__ - 1 contribution - `Philipp Tölke (@toelke) `__ - 1 contribution - `Tom Brien (@TomBrien) `__ - 1 contribution - `TomFahey (@TomFahey) `__ - 2 contributions @@ -531,6 +556,7 @@ Contributors - `tubalainen (@tubalainen) `__ - 3 contributions - `Tuckie (@Tuckie) `__ - 1 contribution - `Alexey Vlasov (@turbulator) `__ - 1 contribution +- `Seppel Hardt (@tuxBurner) `__ - 1 contribution - `tyomikh (@tyomikh) `__ - 1 contribution - `ukewea (@ukewea) `__ - 1 contribution - `Vc (@Valcob) `__ - 4 contributions @@ -541,10 +567,14 @@ Contributors - `vxider (@Vxider) `__ - 7 contributions - `warpzone (@warpzone) `__ - 1 contribution - `Wauter (@Wauter) `__ - 3 contributions +- `webeling67 (@webeling67) `__ - 1 contribution +- `WeekendWarrior1 (@WeekendWarrior1) `__ - 1 contribution - `Ian Wells (@wellsi) `__ - 1 contribution - `Werner Beroux (@wernight) `__ - 1 contribution +- `wifwucite (@wifwucite) `__ - 1 contribution - `Wilmar den Ouden (@wilmardo) `__ - 1 contribution - `Emil Hesslow (@WizKid) `__ - 1 contribution +- `WJCarpenter (@wjcarpenter) `__ - 1 contribution - `Artur 'Wodor' Wielogorski (@wodor) `__ - 1 contribution - `Rick van Hattem (@WoLpH) `__ - 2 contributions - `wutr (@wutr) `__ - 1 contribution @@ -559,4 +589,4 @@ Contributors - `San (@zhujunsan) `__ - 2 contributions - `Christian Zufferey (@zuzu59) `__ - 1 contribution -*This page was last updated February 20, 2021.* +*This page was last updated March 22, 2021.* diff --git a/images/addressable_light.jpg b/images/addressable_light.jpg new file mode 100644 index 000000000..d21c207de Binary files /dev/null and b/images/addressable_light.jpg differ diff --git a/images/inkbird_isbth1_mini.jpg b/images/inkbird_isbth1_mini.jpg new file mode 100644 index 000000000..b7aa22837 Binary files /dev/null and b/images/inkbird_isbth1_mini.jpg differ diff --git a/images/inkplate.jpg b/images/inkplate.jpg new file mode 100644 index 000000000..a373c8082 Binary files /dev/null and b/images/inkplate.jpg differ diff --git a/images/mcp4725.jpg b/images/mcp4725.jpg new file mode 100644 index 000000000..edcfb3654 Binary files /dev/null and b/images/mcp4725.jpg differ diff --git a/images/midea.svg b/images/midea.svg new file mode 100644 index 000000000..a152068c1 --- /dev/null +++ b/images/midea.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/sm300d2.jpg b/images/sm300d2.jpg new file mode 100644 index 000000000..38ab6f951 Binary files /dev/null and b/images/sm300d2.jpg differ diff --git a/images/vl53l0x.png b/images/vl53l0x.png new file mode 100644 index 000000000..41dde9a26 Binary files /dev/null and b/images/vl53l0x.png differ diff --git a/images/vl53l0x.svg b/images/vl53l0x.svg deleted file mode 100644 index caa00f2b9..000000000 --- a/images/vl53l0x.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/images/xiaomi_miscale.jpg b/images/xiaomi_miscale.jpg new file mode 100644 index 000000000..6f6547db9 Binary files /dev/null and b/images/xiaomi_miscale.jpg differ diff --git a/images/xiaomi_miscale2.jpg b/images/xiaomi_miscale2.jpg new file mode 100644 index 000000000..e9f8dac08 Binary files /dev/null and b/images/xiaomi_miscale2.jpg differ diff --git a/index.rst b/index.rst index 90e162835..0338b36d5 100644 --- a/index.rst +++ b/index.rst @@ -126,6 +126,7 @@ Sensor Components INA219, components/sensor/ina219, ina219.jpg INA226, components/sensor/ina226, ina226.jpg INA3221, components/sensor/ina3221, ina3221.jpg + Inkbird IBS-TH1 Mini, components/sensor/inkbird_ibsth1_mini, inkbird_isbth1_mini.jpg Integration, components/sensor/integration, sigma.svg HTU21D, components/sensor/htu21d, htu21d.jpg HM3301, components/sensor/hm3301, hm3301.jpg @@ -142,6 +143,7 @@ Sensor Components NTC Thermistor, components/sensor/ntc, ntc.jpg PMSX003, components/sensor/pmsx003, pmsx003.svg Pulse Counter, components/sensor/pulse_counter, pulse.svg + Pulse Meter, components/sensor/pulse_meter, pulse.svg Pulse Width, components/sensor/pulse_width, pulse.svg PZEM004T, components/sensor/pzem004t, pzem004t.svg PZEM AC, components/sensor/pzemac, pzemac.svg @@ -154,6 +156,7 @@ Sensor Components SCD30, components/sensor/scd30, scd30.jpg SHTCx, components/sensor/shtcx, shtc3.jpg SHT3X-D, components/sensor/sht3xd, sht3xd.jpg + SM300D2, components/sensor/sm300d2, sm300d2.jpg SPS30, components/sensor/sps30, sps30.jpg STS3X, components/sensor/sts3x, sts3x.jpg SGP30, components/sensor/sgp30, sgp30.jpg @@ -168,9 +171,11 @@ Sensor Components TX20, components/sensor/tx20, tx20.jpg Ultrasonic Sensor, components/sensor/ultrasonic, ultrasonic.jpg Uptime Sensor, components/sensor/uptime, timer.svg - VL53L0x, components/sensor/vl53l0x, vl53l0x.jpg + VL53L0x, components/sensor/vl53l0x, vl53l0x.png WiFi Signal Strength, components/sensor/wifi_signal, network-wifi.svg Xiaomi BLE, components/sensor/xiaomi_ble, xiaomi_mijia_logo.jpg + Xiaomi Miscale, components/sensor/xiaomi_miscale, xiaomi_miscale.jpg + Xiaomi Miscale2, components/sensor/xiaomi_miscale2, xiaomi_miscale2.jpg ZyAura, components/sensor/zyaura, zgm053.jpg Custom Sensor, components/sensor/custom, language-cpp.svg @@ -216,6 +221,7 @@ Output Components TLC59208F, components/output/tlc59208f, tlc59208f.jpg MY9231/MY9291, components/output/my9231, my9231.svg SM16716, components/output/sm16716, sm16716.svg + MCP4725, components/output/mcp4725, mcp4725.jpg Custom Output, components/output/custom, language-cpp.svg Template Output, components/output/template, description.svg @@ -276,6 +282,7 @@ Display Components .. imgtable:: Display Core, components/display/index, folder-open.svg + Addressable Light, components/display/addressable_light, addressable_light.jpg LCD Display, components/display/lcd_display, lcd.jpg MAX7219, components/display/max7219, max7219.jpg MAX7219 Dot Matrix, components/display/max7219digit, max7219digit.png @@ -291,7 +298,7 @@ Display Components ST7789V, components/display/st7789v, st7789v.jpg ILI9341, components/display/ili9341, ili9341.jpg Waveshare E-Paper, components/display/waveshare_epaper, waveshare_epaper.jpg - Inkplate 6, components/display/Inkplate, Inkplate.jpg + Inkplate 6, components/display/inkplate, inkplate.jpg PCD8544 (Nokia 5110/ 3310), components/display/pcd8544, pcd8544.jpg Cover Components @@ -318,7 +325,6 @@ Text Sensor Components BLE Scanner, components/text_sensor/ble_scanner, bluetooth.svg Template Text Sensor, components/text_sensor/template, description.svg Custom Text Sensor, components/text_sensor/custom, language-cpp.svg - Custom UART Text Sensor, components/text_sensor/uart, language-cpp.svg Climate Components ------------------ @@ -332,6 +338,7 @@ Climate Components PID Controller, components/climate/pid, function.svg IR Remote Climate, components/climate/ir_climate, air-conditioner-ir.svg Tuya Climate, components/climate/tuya, tuya.png + Midea Air Conditioner, components/climate/midea_ac, midea.svg Misc Components --------------- @@ -410,6 +417,7 @@ Cookbook Sonoff light switch options, cookbook/sonoff-light-switch, light_switch.png ESP32 Water Leak Detector, cookbook/leak-detector-m5stickC, leak-detector-m5stickC_main_index.jpg IAQ (Indoor Air Quality) Board, cookbook/iaq_board, iaq_board2.jpg + Custom UART Text Sensor, cookbook/uart_text_sensor, language-cpp.svg IWOOLE Table Lamp, cookbook/iwoole_rgbw_table_lamp, iwoole_rgbw_table_lamp.png Do you have other awesome automations or cool setups? Please feel free to add them to the diff --git a/markdown.py b/markdown.py new file mode 100644 index 000000000..1043117e8 --- /dev/null +++ b/markdown.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python +# reStructuredText (RST) to GitHub-flavored Markdown converter + +import re +import sys +from docutils import core, nodes, writers +from urllib import parse + + +class Translator(nodes.NodeVisitor): + def __init__(self, base_url, document): + nodes.NodeVisitor.__init__(self, document) + self.output = "" + self.indent = 0 + self.preserve_newlines = False + self.base_url = base_url + + def write(self, text): + self.output += text.replace("\n", "\n" + " " * self.indent) + + def visit_document(self, node): + pass + + def depart_document(self, node): + pass + + def visit_section(self, node): + pass + + def depart_section(self, node): + # Skip all sections except the first one. + raise nodes.StopTraversal + + def visit_title(self, node): + self.version = re.match(r"(\d+\.\d+\.\d+).*", node.children[0]).group(1) + raise nodes.SkipChildren + + def visit_title_reference(self, node): + raise Exception( + f'Markdown conversion: Improper format or not supported feature in "{node.parent.rawsource}". Check "`"' + ) + + def depart_title(self, node): + pass + + def visit_Text(self, node): + if not self.preserve_newlines: + node = node.replace("\n", " ") + self.write(node) + + def depart_Text(self, node): + pass + + def visit_bullet_list(self, node): + self.write("\n") + pass + + def depart_bullet_list(self, node): + pass + + def visit_list_item(self, node): + self.write("* ") + self.indent += 2 + + def depart_list_item(self, node): + self.indent -= 2 + self.write("\n\n") + + def visit_paragraph(self, node): + pass + + def depart_paragraph(self, node): + pass + + def visit_reference(self, node): + # if not is_github_ref(node): + self.write("[") + + def depart_reference(self, node): + # if not is_github_ref(node): + # self.write('](' + node['refuri'] + ')') + refid = node.get("refid") + if refid: + self.write("](" + parse.urljoin(self.base_url, "#" + refid) + ")") + else: + refuri = node.get("refuri") + if refuri: + # if refuri.startswith('../'): + # refuri = parse.urljoin(self.base_url, refuri) + # self.write('](' + refuri + ')') + self.write("](" + parse.urljoin(self.base_url, refuri) + ")") + + def visit_emphasis(self, node): + self.write("*") + pass + + def depart_emphasis(self, node): + self.write("*") + pass + + def visit_target(self, node): + pass + + def depart_target(self, node): + pass + + def visit_literal(self, node): + self.write("`") + + def depart_literal(self, node): + self.write("`") + + def visit_literal_block(self, node): + self.write("\n\n```") + if "c++" in node["classes"]: + self.write("c++") + self.write("\n") + self.preserve_newlines = True + + def depart_literal_block(self, node): + self.write("\n```\n") + self.preserve_newlines = False + + def visit_inline(self, node): + pass + + def depart_inline(self, node): + pass + + def visit_image(self, node): + self.write("![](" + node["uri"] + ")") + + def depart_image(self, node): + pass + + def write_row(self, row, widths): + for i, entry in enumerate(row): + text = entry[0][0] if len(entry) > 0 else "" + if i != 0: + self.write("|") + self.write("{:{}}".format(text, widths[i])) + self.write("\n") + + def visit_table(self, node): + table = node.children[0] + colspecs = table[:-2] + thead = table[-2] + tbody = table[-1] + widths = [int(cs["colwidth"]) for cs in colspecs] + sep = "|".join(["-" * w for w in widths]) + "\n" + self.write("\n\n") + self.write_row(thead[0], widths) + self.write(sep) + for row in tbody: + self.write_row(row, widths) + raise nodes.SkipChildren + + def depart_table(self, node): + pass + + def visit_strong(self, node): + self.write("**") + pass + + def depart_strong(self, node): + self.write("**") + pass + + def visit_block_quote(self, node): + pass + + def depart_block_quote(self, node): + pass + + +class MDWriter(writers.Writer): + """GitHub-flavored markdown writer""" + + supported = ("md",) + """Formats this writer supports.""" + + def translate(self): + translator = Translator(self.document) + self.document.walkabout(translator) + self.output = (translator.output, translator.version) + + +def convert(rst_path): + """Converts RST file to Markdown.""" + return core.publish_file(source_path=rst_path, writer=MDWriter()) + + +if __name__ == "__main__": + convert(sys.argv[1]) diff --git a/schema_doc.py b/schema_doc.py new file mode 100644 index 000000000..4eff4d99f --- /dev/null +++ b/schema_doc.py @@ -0,0 +1,992 @@ +import re +import json +import urllib + +from typing import MutableMapping +from sphinx.util import logging +from docutils import nodes + +SCHEMA_PATH = "schema.json" +CONFIGURATION_VARIABLES = "Configuration variables:" +PIN_CONFIGURATION_VARIABLES = "Pin configuration variables:" +COMPONENT_HUB = "Component/Hub" + +props_missing = 0 +props_verified = 0 +props_documented = 0 + + +def setup(app): + """Setup connects events to the sitemap builder""" + + import os + + if not os.path.isfile(SCHEMA_PATH): + logger = logging.getLogger(__name__) + logger.info(f"{SCHEMA_PATH} not found. Not documenting schema.") + else: + app.connect("doctree-resolved", doctree_resolved) + app.connect("build-finished", build_finished) + + f = open(SCHEMA_PATH, "r", encoding="utf-8-sig") + str = f.read() + app.jschema = json.loads(str) + + return {"version": "1.0.0", "parallel_read_safe": True, "parallel_write_safe": True} + + +def find_component(jschema, component): + return jschema["properties"].get(component) + + +def find_platform_component(jschema, platform, component): + platform_items = jschema["properties"][platform].get("items") + if not platform_items: + return None + ar = platform_items["allOf"] + for p in ar: + if "if" in p: + if p["if"]["properties"]["platform"]["const"] == component: + return p + + +def doctree_resolved(app, doctree, docname): + if docname == "components/index": + # nothing useful here + return + try: + handle_component(app, doctree, docname) + + except Exception as e: + err_str = f"In {docname}: {str(e)}" + logger = logging.getLogger(__name__) + logger.warning(err_str) + + +PLATFORMS_TITLES = { + "Sensor": "sensor", + "Binary Sensor": "binary_sensor", + "Text Sensor": "text_sensor", + "Output": "output", + "Cover": "cover", + "Climate": "climate", + "CAN Bus": "canbus", + "Stepper": "stepper", +} + +CUSTOM_DOCS = { + "guides/automations": { + "Global Variables": "properties/globals", + }, + "guides/configuration-types": { + "Color": "properties/color", + "Pin Schema": [ + "definitions/PIN.INPUT_INTERNAL", + "definitions/PIN.OUTPUT_INTERNAL", + ], + }, + "components/binary_sensor/index": { + "Binary Sensor Filters": "binary_sensor.FILTER_REGISTRY", + }, + "components/climate/ir_climate": { + "IR Remote Climate": [ + "properties/climate/coolix", + "properties/climate/daikin", + "properties/climate/fujitsu_general", + "properties/climate/mitsubishi", + "properties/climate/tcl112", + "properties/climate/toshiba", + "properties/climate/yashima", + "properties/climate/whirlpool", + "properties/climate/climate_ir_lg", + "properties/climate/hitachi_ac344", + ] + }, + "components/display/index": { + "Images": "properties/image", + "Drawing Static Text": "properties/font", + "Color": "properties/color", + "Animation": "properties/animation", + }, + "components/light/index": { + "Base Light Configuration": [ + "definitions/light.ADDRESSABLE_LIGHT_SCHEMA", + "definitions/light.BINARY_LIGHT_SCHEMA", + "definitions/light.BRIGHTNESS_ONLY_LIGHT_SCHEMA", + "definitions/light.LIGHT_SCHEMA", + ], + "Light Effects": "light.EFFECTS_REGISTRY", + }, + "components/light/fastled": { + "Clockless": "properties/light/fastled_clockless", + "SPI": "properties/light/fastled_spi", + }, + "components/mcp230xx": { + PIN_CONFIGURATION_VARIABLES: [ + "definitions/PIN.INPUT_mcp23xxx", + "definitions/PIN.OUTPUT_mcp23xxx", + ] + }, + "components/mqtt": { + "MQTT Component Base Configuration": "definitions/CONFIG.MQTT_COMMAND_COMPONENT_SCHEMA", + }, + "components/output/index": { + "Base Output Configuration": "definitions/output.FLOAT_OUTPUT_SCHEMA", + }, + "components/remote_transmitter": { + "Remote Transmitter Actions": "definitions/REMOTE_BASE.BASE_REMOTE_TRANSMITTER_SCHEMA", + }, + "components/sensor/index": { + "Sensor Filters": "sensor.FILTER_REGISTRY", + }, + "components/time": { + "Home Assistant Time Source": "properties/time/homeassistant", + "SNTP Time Source": "properties/time/sntp", + "GPS Time Source": "properties/time/gps", + "DS1307 Time Source": "properties/time/ds1307", + }, + "components/wifi": { + "Connecting to Multiple Networks": "definitions/wifi-networks", + "Enterprise Authentication": "definitions/wifi-networks/eap", + }, + "custom/custom_component": { + "Generic Custom Component": "properties/custom_component" + }, +} + + +def get_node_title(node): + return list(node.traverse(nodes.title))[0].astext() + + +class SchemaGeneratorVisitor(nodes.NodeVisitor): + def __init__(self, app, doctree, docname): + nodes.NodeVisitor.__init__(self, doctree) + self.app = app + self.doctree = doctree + self.docname = docname + self.path = docname.split("/") + self.json_component = None + self.props = None + self.platform = None + self.json_platform_component = None + self.json_base_config = None + self.title_id = None + self.props_section_title = None + self.find_registry = None + self.section_level = 0 + if self.path[0] == "components": + if len(self.path) == 2: # root component, e.g. dfplayer, logger + component = docname[11:] + self.json_component = app.jschema["properties"].get(component) + else: # sub component, e.g. output/esp8266_pwm + + # components here might have a core / hub, eg. dallas, ads1115 + # and then they can be a binary_sensor, sensor, etc. + + component = self.path[2] + + if component == "ssd1331": + component = "ssd1331_spi" + + self.platform = self.path[1] + if component == "index": + # these are e.g. sensor, binary sensor etc. + p = self.platform.replace(" ", "_").lower() + self.json_component = find_component( + self.app.jschema, self.platform + ) + self.json_base_config = self.app.jschema["definitions"].get( + p + "." + p.upper() + "_SCHEMA" + ) + + else: + self.json_component = find_component(self.app.jschema, component) + + self.json_platform_component = find_platform_component( + self.app.jschema, self.platform, component + ) + + self.custom_doc = CUSTOM_DOCS.get(docname) + + self.previous_title_text = "No title" + + self.is_component_hub = False + + # used in custom_docs when titles are mapped to array of components, this + # allows for same configuration text be applied to different json schemas + self.multi_component = None + + # a stack for props, used when there are nested props to save high level props. + self.prop_stack = [] + + # The prop just filled in, used when there are nested props and need to know which + # want to dig + self.current_prop = None + + # self.filled_props used to know when any prop is added to props, + # we dont invalidate props on exiting bullet lists but just when entering a new title + self.filled_props = False + + # Found a Configuration variables: heading, this is to increase docs consistency + self.accept_props = False + + self.props_level = 0 + + def visit_document(self, node): + # ESPHome page docs follows strict formating guidelines which allows + # for docs to be parsed directly into yaml schema + + if self.docname in ["components/sensor/binary_sensor_map"]: + # temporarly not supported + raise nodes.SkipChildren + + if len(list(node.traverse(nodes.paragraph))) == 0: + # this is empty, not much to do + raise nodes.SkipChildren + + self.props_section_title = get_node_title(node) + + # Document first paragraph is description of this thing + description = self.getMarkdownParagraph(node) + + if self.json_platform_component: + self.json_platform_component["markdownDescription"] = description + elif self.json_component: + self.json_component["markdownDescription"] = description + + if self.json_base_config: + self.json_component = self.json_base_config + + # for most components / platforms get the props, this allows for a less restrictive + # first title on the page + if self.json_component or self.json_platform_component: + self.props = self.find_props( + self.json_platform_component + if self.json_platform_component + else self.json_component + ) + + if not self.props: + # get props for base components, Sensor, Binary Sensor, Light, etc. + + if len(self.path) == 2: + # "#/definitions/schema_canbus.CONFIG_SCHEMA" + self.json_base_config = self.app.jschema["definitions"].get( + f"{self.path[1]}.{self.path[1].upper()}_SCHEMA" + ) + if self.json_base_config: + self.props = self.find_props(self.json_base_config) + + def depart_document(self, node): + pass + + def visit_section(self, node): + self.section_level += 1 + section_title = get_node_title(node) + if self.custom_doc and section_title in self.custom_doc: + r = self.custom_doc[section_title] + if ( + isinstance(r, list) + or r.startswith("properties") + or r.startswith("definitions") + ): + return + self.find_registry = r + + def depart_section(self, node): + self.section_level -= 1 + if self.section_level == 1: + self.find_registry = None + + def unknown_visit(self, node): + pass + + def unknown_departure(self, node): + pass + + def visit_title(self, node): + title_text = node.astext() + + if "interval" in title_text: + title_text = title_text + if self.custom_doc is not None and title_text in self.custom_doc: + if isinstance(self.custom_doc[title_text], list): + self.multi_component = self.custom_doc[title_text] + self.filled_props = False + self.props = None + # TODO: add same markdown description to each? + + return + + json_component = self.find_component(self.custom_doc[title_text]) + if not json_component: + return + + json_component["markdownDescription"] = self.getMarkdownParagraph( + node.parent + ) + self.props_section_title = title_text + self.props = self.find_props(json_component) + + return + + if title_text == COMPONENT_HUB: + # here comes docs for the component, make sure we have props of the component + # Needed for e.g. ads1115 + self.props_section_title = f"{self.path[-1]} {title_text}" + json_component = find_component(self.app.jschema, self.path[-1]) + if json_component: + self.props = self.find_props(json_component) + + json_component["markdownDescription"] = self.getMarkdownParagraph( + node.parent + ) + + # mark this to retrieve components instead of platforms + self.is_component_hub = True + + if title_text == CONFIGURATION_VARIABLES: + if not self.props and self.multi_component is None: + raise ValueError( + f'Found a "{CONFIGURATION_VARIABLES}": title after {self.previous_title_text}. Unkown object.' + ) + + if title_text == "Over SPI" or title_text == "Over I²C": + suffix = "_spi" if "SPI" in title_text else "_i2c" + + # these could be platform components, like the display's ssd1306 + # but also there are components which are component/hub + # and there are non platform components with the SPI/I2C versions, + # like pn532, those need to be marked with the 'Component/Hub' title + component = self.path[-1] + suffix + + self.props_section_title = self.path[-1] + " " + title_text + + if self.platform is not None and not self.is_component_hub: + json_platform_component = find_platform_component( + self.app.jschema, self.platform, component + ) + if not json_platform_component: + raise ValueError( + f"Cannot find platform {self.platform} component '{component}' after found title: '{title_text}'." + ) + self.props = self.find_props(json_platform_component) + + # Document first paragraph is description of this thing + json_platform_component[ + "markdownDescription" + ] = self.getMarkdownParagraph(node.parent) + + else: + json_component = find_component(self.app.jschema, component) + if not json_component: + raise ValueError( + f"Cannot find component '{component}' after found title: '{title_text}'." + ) + self.props = self.find_props(json_component) + + # Document first paragraph is description of this thing + json_component["markdownDescription"] = self.getMarkdownParagraph( + node.parent + ) + + # Title is description of platform component, those ends with Sensor, Binary Sensor, Cover, etc. + if ( + len( + list( + filter( + lambda x: title_text.endswith(x), list(PLATFORMS_TITLES.keys()) + ) + ) + ) + > 0 + ): + if title_text in PLATFORMS_TITLES: + # this omits the name of the component, but we know the platform + platform_name = PLATFORMS_TITLES[title_text] + component_name = self.path[-1] + self.props_section_title = self.path[-1] + " " + title_text + else: + # title first word is the component name + component_name = title_text.split(" ")[0] + # and the rest is the platform + platform_name = PLATFORMS_TITLES.get( + title_text[len(component_name) + 1 :] + ) + if not platform_name: + # Some general title which does not locate a component directly + return + self.props_section_title = title_text + c = find_platform_component( + self.app.jschema, platform_name, component_name.lower() + ) + if c: + self.json_platform_component = c + + c["markdownDescription"] = self.getMarkdownParagraph(node.parent) + + # Now fill props for the platform element + try: + self.props = self.find_props(self.json_platform_component) + except KeyError: + raise ValueError("Cannot find platform props") + + if title_text.endswith("Component") or title_text.endswith("Bus"): + # if len(path) == 3 and path[2] == 'index': + # # skip platforms index, e.g. sensors/index + # continue + split_text = title_text.split(" ") + self.props_section_title = title_text + if len(split_text) == 2: + # some components are several components in a single platform doc + # e.g. ttp229 binary_sensor has two different named components. + component_name = split_text[0].lower().replace(".", "") + if component_name.lower() == self.platform: + return + c = find_component(self.app.jschema, component_name) + if c: + self.json_component = c + try: + self.props = self.find_props(self.json_component) + self.multi_component = None + except KeyError: + raise ValueError( + "Cannot find props for component " + component_name + ) + return + c = find_platform_component( + self.app.jschema, self.path[1], component_name + ) + if c: + self.json_platform_component = c + try: + self.props = self.find_props(self.json_platform_component) + + except KeyError: + raise ValueError( + f"Cannot find props for platform {self.path[1]} component {self.component_name}" + ) + return + + if title_text.endswith("Trigger"): + # Document first paragraph is description of this thing + description = self.getMarkdownParagraph(node.parent) + split_text = title_text.split(" ") + if len(split_text) != 2: + return + key = split_text[0] + + # handles Time / on_time + c = self.json_base_config or self.json_component + if c: + trigger_schema = self.find_props(c).get(key) + self.props = self.find_props(trigger_schema) + self.props_section_title = title_text + + if title_text == PIN_CONFIGURATION_VARIABLES: + self.multi_component = [] + if self.app.jschema["definitions"].get(f"PIN.INPUT_{self.path[-1]}"): + self.multi_component.append(f"definitions/PIN.INPUT_{self.path[-1]}") + if self.app.jschema["definitions"].get(f"PIN.OUTPUT_{self.path[-1]}"): + self.multi_component.append(f"definitions/PIN.OUTPUT_{self.path[-1]}") + self.accept_props = True + self.filled_props = False + self.props = None + if len(self.multi_component) == 0: + raise ValueError( + f'Found a "{PIN_CONFIGURATION_VARIABLES}" entry but could not find pin schema' + ) + + if title_text.endswith("Action") or title_text.endswith("Condition"): + # Document first paragraph is description of this thing + description = self.getMarkdownParagraph(node.parent) + split_text = title_text.split(" ") + if len(split_text) != 2: + return + key = split_text[0] + + if self.props: + ref = self.props.get(key) + if ref: + ref = self.get_ref(ref) + if ref: + self.props = self.find_props(ref) + return + + registry_name = f"automation.{split_text[1].upper()}_REGISTRY" + self.find_registry_prop(registry_name, key, description) + + if self.section_level == 3 and self.find_registry: + name = title_text + if name.endswith(" Effect"): + name = title_text[: -len(" Effect")] + if name.endswith(" Light"): + name = name[: -len(" Light")] + key = name.replace(" ", "_").replace(".", "").lower() + description = self.getMarkdownParagraph(node.parent) + self.find_registry_prop(self.find_registry, key, description) + self.props_section_title = title_text + + if title_text == PIN_CONFIGURATION_VARIABLES: + self.multi_component = [] + if self.app.jschema["definitions"].get(f"PIN.INPUT_{self.path[-1]}"): + self.multi_component.append(f"definitions/PIN.INPUT_{self.path[-1]}") + if self.app.jschema["definitions"].get(f"PIN.OUTPUT_{self.path[-1]}"): + self.multi_component.append(f"definitions/PIN.OUTPUT_{self.path[-1]}") + self.accept_props = True + self.filled_props = False + self.props = None + if len(self.multi_component) == 0: + raise ValueError( + f'Found a "{PIN_CONFIGURATION_VARIABLES}" entry but could not find pin schema' + ) + + def find_registry_prop(self, registry_name, key, description): + registry = self.app.jschema["definitions"][registry_name]["anyOf"] + for item in registry: + if key in item["properties"]: + item["properties"][key]["markdownDescription"] = description + self.props = self.find_props(item["properties"][key]) + + return + raise ValueError(f"Cannot find {registry_name} {key}") + + def depart_title(self, node): + if self.filled_props: + self.filled_props = False + self.props = None + self.current_prop = None + self.accept_props = False + self.multi_component = None + self.previous_title_text = node.astext() + self.title_id = node.parent["ids"][0] + + def find_props_previous_title(self): + comp = self.json_component or self.json_platform_component + if comp: + props = self.find_props(comp) + + if self.previous_title_text in props: + prop = props[self.previous_title_text] + if prop: + self.props = self.find_props(prop) + else: + # return fake dict so better errors are printed + self.props = {"__": "none"} + + def visit_Text(self, node): + if self.multi_component: + return + if node.astext() == CONFIGURATION_VARIABLES: + if not self.props: + self.find_props_previous_title() + if not self.props: + raise ValueError( + f'Found a "{CONFIGURATION_VARIABLES}" entry for unknown object after {self.previous_title_text}' + ) + self.accept_props = True + + raise nodes.SkipChildren + + def depart_Text(self, node): + pass + + def visit_paragraph(self, node): + if node.astext() == CONFIGURATION_VARIABLES: + if not self.props and not self.multi_component: + self.find_props_previous_title() + if not self.props and not self.multi_component: + raise ValueError( + f'Found a "{CONFIGURATION_VARIABLES}" entry for unknown object after {self.previous_title_text}' + ) + self.accept_props = True + + raise nodes.SkipChildren + + def depart_paragraph(self, node): + pass + + def visit_bullet_list(self, node): + self.props_level = self.props_level + 1 + if self.current_prop and self.props and self.props_level > 1: + + # if '$ref' in self.props[self.current_prop]: + # if self.props[self.current_prop]['$ref'].endswith('_SCHEMA'): + # nowhere put this props info... + # raise nodes.SkipChildren + + # this can be list of values, list of subproperties + + # deep configs + # e.g. wifi manual_ip, could also be a enum list + + # if this prop has a reference + prop = self.props[self.current_prop] + if isinstance(prop, dict): + if "$ref" in prop: + ref = self.get_ref(prop) + self.prop_stack.append(self.props) + self.props = self.find_props(ref) + self.accept_props = True + elif "properties" in prop: + self.prop_stack.append(self.props) + self.props = prop["properties"] + elif ( + "anyOf" in prop + and len(prop["anyOf"]) > 0 + and isinstance(self.get_ref(prop["anyOf"][0]), dict) + and "$ref" in self.get_ref(prop["anyOf"][0]) + ): + ref = self.get_ref(prop["anyOf"][0]) + self.prop_stack.append(self.props) + self.props = self.find_props(ref) + # nowhere put this props info... + # otherwise inner bullet list will be interpreted as property list + if self.props_level > 1: + raise nodes.SkipChildren + else: + # nowhere put this props info... + # otherwise inner bullet list will be interpreted as property list + if self.props_level > 1: + raise nodes.SkipChildren + + if not self.props and self.multi_component is None: + raise nodes.SkipChildren + + def depart_bullet_list(self, node): + self.props_level = self.props_level - 1 + if len(self.prop_stack) > 0: + self.props = self.prop_stack.pop() + self.filled_props = True + + def visit_list_item(self, node): + if self.accept_props and self.props: + self.filled_props = True + try: + self.current_prop = self.update_prop(node, self.props) + except Exception as e: + raise ValueError(f"In '{self.previous_title_text}' {str(e)}") + + elif self.multi_component: + # update prop for each component + for c in self.multi_component: + props = self.find_props(self.find_component(c)) + self.current_prop = self.update_prop(node, props) + self.filled_props = True + + def depart_list_item(self, node): + pass + + def visit_literal(self, node): + raise nodes.SkipChildren + + def depart_literal(self, node): + pass + + def getMarkdown(self, node): + from markdown import Translator + + t = Translator( + urllib.parse.urljoin(self.app.config.html_baseurl, self.docname + ".html"), + self.doctree, + ) + node.walkabout(t) + return t.output + + def getMarkdownParagraph(self, node): + paragraph = list(node.traverse(nodes.paragraph))[0] + markdown = self.getMarkdown(paragraph) + + param_type = None + # Check if there is type information for this item + try: + name_type = markdown[: markdown.index(": ") + 2] + ntr = re.search( + r"(\(((\*\*Required\*\*)|(\*Optional\*))(,\s(.*))*)\):\s", + name_type, + re.IGNORECASE, + ) + if ntr: + param_type = ntr.group(6) + if param_type: + markdown = ( + f"**{param_type}**: {markdown[markdown.index(': ') + 2 :]}" + ) + except ValueError: + # ': ' not found + pass + + title = list(node.traverse(nodes.title))[0] + if len(title) > 0: + url = urllib.parse.urljoin( + self.app.config.html_baseurl, + self.docname + ".html#" + title.parent["ids"][0], + ) + markdown += f"\n\n*See also: [{self.props_section_title}]({url})*" + return markdown + + def update_prop(self, node, props): + prop_name = None + + raw = node.rawsource # this has the full raw rst code for this property + + if not raw.startswith("**"): + # not bolded, most likely not a property definition, + # usually texts like 'All properties from...' etc + return None + + markdown = self.getMarkdown(node) + + markdown += f"\n\n*See also: [{self.props_section_title}]({urllib.parse.urljoin(self.app.config.html_baseurl, self.docname +'.html#'+self.title_id)})*" + + try: + name_type = markdown[: markdown.index(": ") + 2] + except ValueError: + raise ValueError(f'Property format error. Missing ": " in {raw}') + + # Example properties formats are: + # **name** (**Required**, string): Long Description... + # **name** (*Optional*, string): Long Description... Defaults to ``value``. + # **name** (*Optional*): Long Description... Defaults to ``value``. + + ntr = re.search( + r"\* \*\*(\w*)\*\*\s(\(((\*\*Required\*\*)|(\*Optional\*))(,\s(.*))*)\):\s", + name_type, + re.IGNORECASE, + ) + + if ntr: + prop_name = ntr.group(1) + param_type = ntr.group(7) + else: + s2 = re.search( + r"\* \*\*(\w*)\*\*\s(\(((\*\*Required\*\*)|(\*Optional\*))(,\s(.*))*)\):\s", + markdown, + re.IGNORECASE, + ) + if s2: + # this is e.g. when a property has a list inside, and the list inside are the options. + # just validate **prop_name** + s3 = re.search(r"\* \*\*(\w*)\*\*:\s", name_type) + prop_name = s3.group(1) + param_type = None + else: + raise ValueError(f"Invalid property format: {node.rawsource}") + + k = str(prop_name) + jprop = props.get(k) + if not jprop: + # Create docs for common properties when descriptions are overriden + # in the most specific component. + + if k in [ + "id", + "name", + "internal", + # i2c + "address", + "i2c_id", + # polling component + "update_interval", + # uart + "uart_id", + # ligth + "effects", + "gamma_correct", + "default_transition_length", + "color_correct", + # display + "lambda", + "dither", + "pages", + "rotation", + # spi + "spi_id", + "cs_pin", + # output (binary/float output) + "inverted", + "power_supply", + # climate + "receiver_id", + ]: + jprop = props[k] = {} + else: + raise ValueError(f"Cannot find property {k}") + + desc = markdown[markdown.index(": ") + 2 :].strip() + if param_type: + desc = "**" + param_type + "**: " + desc + + jprop["markdownDescription"] = desc + global props_documented + props_documented = props_documented + 1 + + return prop_name + + def get_ref(self, node): + ref = node.get("$ref") + if ref and ref.startswith("#/definitions/"): + return self.app.jschema["definitions"][ref[14:]] + + def find_component(self, component_path): + path = component_path.split("/") + if path[0] not in ("properties", "definitions"): + return None + json_component = self.app.jschema[path[0]][path[1]] + + if len(path) > 2: + # a property path + props = self.find_props(json_component) + if props: + json_component = props.get(path[2]) + else: + # a platform sub element + json_component = find_platform_component( + self.app.jschema, path[1], path[2] + ) + return json_component + + class Props(MutableMapping): + """Smarter props dict. + + Props are mostly a dict, however some constructs have two issues: + - An update is intended on an element which does not own a property, but it is based + on an schema that does have the property, those cases can be handled + - An update is done in a typed schema + """ + + def __init__(self, visitor, component): + self.visitor = visitor + self.component = component + self.store = self._get_props(component) + self.parent = None + + def _get_props(self, component): + # find properties + if "then" in component: + component = component["then"] + props = component.get("properties") + ref = None + if not props: + arr = component.get("anyOf", component.get("allOf")) + if not arr: + if "$ref" in component: + return self._get_props(self.visitor.get_ref(component)) + return None + for x in arr: + props = x.get("properties") + if not ref: + ref = self.visitor.get_ref(x) + if props: + break + if not props and ref: + props = self._get_props(ref) + return props + + def __getitem__(self, key): + if self.store and key in self.store: + return self.store[key] + + if "then" in self.component: + # check if it's typed + schemas = self.component["then"].get("allOf") + if ( + isinstance(schemas, list) + and "properties" in schemas[0] + and "type" in schemas[0]["properties"] + ): + for s in schemas: + if "then" in s: + props = self._get_props(s.get("then")) + if key in props: + return SetObservable( + props[key], + setitem_callback=self._update_typed, + inner_key=key, + ) + return # key not found + + # check if it's a registry and need to reset store + # e.g. remote_receiver binary sensor + if "$ref" in self.component["then"]: + ref = self.visitor.get_ref(self.component["then"]) + prop_set = ref.get("anyOf") + if isinstance(prop_set, list): + for k in prop_set: + if key in k["properties"]: + self.store = k["properties"] + return self.store[key] + + def _update_typed(self, inner_key, key, value): + # Make sure we update all types + if "then" in self.component: + schemas = self.component["then"].get("allOf") + assert "type" in schemas[0].get("properties") + for s in schemas: + if "then" in s: + props = self._get_props(s.get("then")) + if inner_key in props: + props[inner_key][key] = value + + def __setitem__(self, key, value): + self.store[key] = value + + def __delitem__(self, key): + self.store.pop(key) + + def __iter__(self): + return iter(self.store) + + def __len__(self): + return len(self.store) if self.store else 0 + + def find_props(self, component): + props = self.Props(self, component) + + if props: + self.filled_props = False + self.accept_props = False + self.current_prop = None + + return props + + +def handle_component(app, doctree, docname): + path = docname.split("/") + if path[0] == "components": + pass + elif docname not in CUSTOM_DOCS: + return + + v = SchemaGeneratorVisitor(app, doctree, docname) + doctree.walkabout(v) + + +def build_finished(app, exception): + # TODO: create report of missing descriptions + + f = open(SCHEMA_PATH, "w") + f.write(json.dumps(app.jschema)) + + str = f"Documented: {props_documented}" + logger = logging.getLogger(__name__) + logger.info(str) + + +class SetObservable(dict): + """ + a MyDict is like a dict except that when you set an item, before + doing so it will call a callback function that was passed in when the + MyDict instance was created + """ + + def __init__(self, value, setitem_callback=None, inner_key=None, *args, **kwargs): + super(SetObservable, self).__init__(value, *args, **kwargs) + self._setitem_callback = setitem_callback + self.inner_key = inner_key + + def __setitem__(self, key, value): + if self._setitem_callback: + self._setitem_callback(self.inner_key, key, value) + super(SetObservable, self).__setitem__(key, value) diff --git a/script/bump-version.py b/script/bump-version.py index 3517d110b..0a38889f9 100755 --- a/script/bump-version.py +++ b/script/bump-version.py @@ -2,7 +2,6 @@ import argparse import re -import subprocess from dataclasses import dataclass import sys @@ -16,30 +15,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): @@ -55,35 +51,25 @@ def sub(path, pattern, repl, expected_count=1): def write_version(version: Version): # ESPHOME_REF = v1.14.4 sub( - 'Makefile', - r'ESPHOME_REF = .*', - f'ESPHOME_REF = v{version}' if not version.dev else f'ESPHOME_REF = dev' + "Makefile", + r"ESPHOME_REF = .*", + f"ESPHOME_REF = v{version}" if not version.dev else "ESPHOME_REF = dev", ) # PROJECT_NUMBER = 1.14.4 sub( - 'Doxygen', - r'PROJECT_NUMBER = .*', - f'PROJECT_NUMBER = {version}' + "Doxygen", r"PROJECT_NUMBER = .*", f"PROJECT_NUMBER = {version}" ) # version = '1.14' - sub( - 'conf.py', - r"version = '.*'", - f"version = '{version.major}.{version.minor}'" - ) + sub("conf.py", r'version = ".*"', f'version = "{version.major}.{version.minor}"') # release = '1.14.4' - sub( - 'conf.py', - r"release = '.*'", - f"release = '{version}'" - ) - with open('_static/version', 'wt') as fh: + sub("conf.py", r'release = ".*"', f'release = "{version}"') + with open("_static/version", "wt") as fh: fh.write(str(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 = Version.parse(args.new_version) diff --git a/seo.py b/seo.py index 819b0206b..1255a66cf 100644 --- a/seo.py +++ b/seo.py @@ -6,11 +6,18 @@ from docutils.writers._html_base import HTMLTranslator class SEONode(nodes.General, nodes.Element): - def __init__(self, title=None, description=None, image=None, - author=None, author_twitter=None, keywords=None): + def __init__( + self, + title=None, + description=None, + image=None, + author=None, + author_twitter=None, + keywords=None, + ): super(SEONode, self).__init__() self.title = title - self.description = description.replace('\n', ' ') + self.description = description.replace("\n", " ") self.image = image self.author = author self.author_twitter = author_twitter @@ -25,26 +32,34 @@ class RedirectNode(nodes.General, nodes.Element): def seo_visit(self: HTMLTranslator, node: SEONode): def encode_text(text): - special_characters = {ord('&'): '&', - ord('<'): '<', - ord('"'): '"', - ord('>'): '>'} + special_characters = { + ord("&"): "&", + ord("<"): "<", + ord('"'): """, + ord(">"): ">", + } return text.translate(special_characters) def create_content_meta(name, content): if content is None: return - self.meta.append('\n'.format(name, encode_text(content))) + self.meta.append( + '\n'.format(name, encode_text(content)) + ) def create_itemprop_meta(name, content): if content is None: return - self.meta.append('\n'.format(name, encode_text(content))) + self.meta.append( + '\n'.format(name, encode_text(content)) + ) def create_property_meta(name, content): if content is None: return - self.meta.append('\n'.format(name, encode_text(content))) + self.meta.append( + '\n'.format(name, encode_text(content)) + ) # Base create_content_meta("description", node.description) @@ -76,8 +91,11 @@ def seo_visit(self: HTMLTranslator, node: SEONode): def redirect_visit(self: HTMLTranslator, node: RedirectNode): self.meta.append(''.format(node.url)) - self.body.append(self.starttag(node, 'p', - 'Redirecting to {0}'.format(node.url))) + self.body.append( + self.starttag( + node, "p", 'Redirecting to {0}'.format(node.url) + ) + ) def seo_depart(self, _): @@ -85,36 +103,36 @@ def seo_depart(self, _): def redirect_depart(self, _): - self.body.append('

') + self.body.append("

") class SEODirective(Directive): option_spec = { - 'title': directives.unchanged, - 'description': directives.unchanged, - 'image': directives.path, - 'author': directives.unchanged, - 'author_twitter': directives.unchanged, - 'keywords': directives.unchanged, + "title": directives.unchanged, + "description": directives.unchanged, + "image": directives.path, + "author": directives.unchanged, + "author_twitter": directives.unchanged, + "keywords": directives.unchanged, } def run(self): env = self.state.document.settings.env - title_match = re.match(r'.+(.+).+', str(self.state.document)) - if title_match is not None and 'title' not in self.options: - self.options['title'] = title_match.group(1) + title_match = re.match(r".+(.+).+", str(self.state.document)) + if title_match is not None and "title" not in self.options: + self.options["title"] = title_match.group(1) - image = self.options.get('image') + image = self.options.get("image") if image is not None: - if not image.startswith('/'): - image = '/_images/' + image - self.options['image'] = env.config.html_baseurl + image + if not image.startswith("/"): + image = "/_images/" + image + self.options["image"] = env.config.html_baseurl + image return [SEONode(**self.options)] class RedirectDirective(Directive): option_spec = { - 'url': directives.unchanged, + "url": directives.unchanged, } def run(self): @@ -122,10 +140,8 @@ class RedirectDirective(Directive): def setup(app): - app.add_directive('seo', SEODirective) + app.add_directive("seo", SEODirective) app.add_node(SEONode, html=(seo_visit, seo_depart)) - app.add_directive('redirect', RedirectDirective) + app.add_directive("redirect", RedirectDirective) app.add_node(RedirectNode, html=(redirect_visit, redirect_depart)) - return {"version": "1.0.0", - "parallel_read_safe": True, - "parallel_write_safe": True} + return {"version": "1.0.0", "parallel_read_safe": True, "parallel_write_safe": True} diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 000000000..d8e6856d8 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,41 @@ +[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, + diff --git a/sitemap.py b/sitemap.py index 6878b12b5..3f50ff322 100644 --- a/sitemap.py +++ b/sitemap.py @@ -4,15 +4,17 @@ import xml.etree.ElementTree as ET def setup(app): """Setup connects events to the sitemap builder""" - app.connect('html-page-context', add_html_link) - app.connect('build-finished', create_sitemap) + app.connect("html-page-context", add_html_link) + app.connect("build-finished", create_sitemap) app.sitemap_links = [] - is_production = os.getenv('PRODUCTION') == 'YES' + is_production = os.getenv("PRODUCTION") == "YES" - return {"version": "1.0.0", - "parallel_read_safe": True, - "parallel_write_safe": not is_production} + return { + "version": "1.0.0", + "parallel_read_safe": True, + "parallel_write_safe": not is_production, + } def add_html_link(app, pagename, templatename, context, doctree): @@ -29,26 +31,27 @@ def create_sitemap(app, exception): for link in app.sitemap_links: url = ET.SubElement(root, "url") priority = 0.5 - if link == 'index.html': + if link == "index.html": priority = 1.0 - link = '' - elif link.endswith('index.html'): + link = "" + elif link.endswith("index.html"): priority += 0.25 - link = link[:-len('index.html')] - if link.endswith('.html'): - link = link[:-len('.html')] - ET.SubElement(url, "loc").text = app.builder.config.html_baseurl + '/' + link + link = link[: -len("index.html")] + if link.endswith(".html"): + link = link[: -len(".html")] + ET.SubElement(url, "loc").text = app.builder.config.html_baseurl + "/" + link ET.SubElement(url, "priority").text = str(priority) filename = os.path.join(app.outdir, "sitemap.xml") - ET.ElementTree(root).write(filename, - xml_declaration=True, - encoding='utf-8', - method="xml") + ET.ElementTree(root).write( + filename, xml_declaration=True, encoding="utf-8", method="xml" + ) - with open(os.path.join(app.builder.outdir, 'robots.txt'), 'wt') as f: - if os.getenv('PRODUCTION') != 'YES': - f.write('User-agent: *\nDisallow: /\n') + with open(os.path.join(app.builder.outdir, "robots.txt"), "wt") as f: + if os.getenv("PRODUCTION") != "YES": + f.write("User-agent: *\nDisallow: /\n") else: - f.write('User-agent: *\nDisallow: \n\n' - 'Sitemap: https://esphome.io/sitemap.xml\n') + f.write( + "User-agent: *\nDisallow: \n\n" + "Sitemap: https://esphome.io/sitemap.xml\n" + ) diff --git a/svg2png.py b/svg2png.py index 02b3dc4c1..fe5165aeb 100644 --- a/svg2png.py +++ b/svg2png.py @@ -7,13 +7,16 @@ import queue import sys -to_p = Path('svg2png') +to_p = Path("svg2png") to_p.mkdir(exist_ok=True) -for f in to_p.glob('*.png'): +for f in to_p.glob("*.png"): f.unlink() -images = [f for f in Path('_build/html/_images/').glob('*.svg') - if not re.match(r'^seg[0-9A-F]{2}$', f.stem)] +images = [ + f + for f in Path("_build/html/_images/").glob("*.svg") + if not re.match(r"^seg[0-9A-F]{2}$", f.stem) +] q = queue.Queue() @@ -23,18 +26,28 @@ def worker(): if item is None: break - to = to_p / item.with_suffix('.png').name - args = ['inkscape', '-z', '-e', str(to.absolute()), '-w', '800', - '-background', 'white', str(item.absolute())] - print("Running: {}".format(' '.join(shlex.quote(x) for x in args))) + to = to_p / item.with_suffix(".png").name + args = [ + "inkscape", + "-z", + "-e", + str(to.absolute()), + "-w", + "800", + "-background", + "white", + str(item.absolute()), + ] + print("Running: {}".format(" ".join(shlex.quote(x) for x in args))) proc = subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - if b'Bitmap saved as' not in proc.stdout: + if b"Bitmap saved as" not in proc.stdout: print("Error!") print(proc.stdout) sys.exit(1) q.task_done() + NUM_THREADS = 8 threads = [] for i in range(NUM_THREADS): diff --git a/travis.py b/travis.py index c3ca38e31..fd5b96c15 100644 --- a/travis.py +++ b/travis.py @@ -16,32 +16,40 @@ def find_all(a_str, sub): column += len(sub) -section_regex = re.compile(r'^(=+|-+|\*+|~+)$') -directive_regex = re.compile(r'^(\s*)\.\. (.*)::.*$') -directive_arg_regex = re.compile(r'^(\s+):.*:\s*.*$') -esphome_io_regex = re.compile(r'https://esphome.io/') +section_regex = re.compile(r"^(=+|-+|\*+|~+)$") +directive_regex = re.compile(r"^(\s*)\.\. (.*)::.*$") +directive_arg_regex = re.compile(r"^(\s+):.*:\s*.*$") +esphome_io_regex = re.compile(r"https://esphome.io/") -for f in sorted(Path('.').glob('**/*.rst')): +for f in sorted(Path(".").glob("**/*.rst")): try: - content = f.read_text('utf-8') + content = f.read_text("utf-8") except UnicodeDecodeError: - errors.append("File {} is not readable as UTF-8. Please set your editor to UTF-8 mode." - "".format(f)) + errors.append( + "File {} is not readable as UTF-8. Please set your editor to UTF-8 mode." + "".format(f) + ) continue - if not content.endswith('\n'): - errors.append("Newline at end of file missing. Please insert an empty line at end " - "of file {}".format(f)) + if not content.endswith("\n"): + errors.append( + "Newline at end of file missing. Please insert an empty line at end " + "of file {}".format(f) + ) # Check tab character - for line, col in find_all(content, '\t'): - errors.append("File {} contains tab character on line {}:{}. " - "Please convert tabs to spaces.".format(f, line + 1, col)) + for line, col in find_all(content, "\t"): + errors.append( + "File {} contains tab character on line {}:{}. " + "Please convert tabs to spaces.".format(f, line + 1, col) + ) # Check windows newline - for line, col in find_all(content, '\r'): - errors.append("File {} contains windows newline on line {}:{}. " - "Please set your editor to unix newline mode.".format(f, line + 1, col)) + for line, col in find_all(content, "\r"): + errors.append( + "File {} contains windows newline on line {}:{}. " + "Please set your editor to unix newline mode.".format(f, line + 1, col) + ) lines = content.splitlines(keepends=False) @@ -65,7 +73,7 @@ for f in sorted(Path('.').glob('**/*.rst')): continue base_indentation = len(m.group(1)) directive_name = m.group(2) - if directive_name.startswith('|') or directive_name == 'seo': + if directive_name.startswith("|") or directive_name == "seo": continue # Match directive args for j in range(i + 1, len(lines)): @@ -77,8 +85,10 @@ for f in sorted(Path('.').glob('**/*.rst')): # Empty line must follow if lines[j]: - errors.append("Directive '{}' is not followed by an empty line. Please insert an " - "empty line after {}:{}".format(directive_name, f, j)) + errors.append( + "Directive '{}' is not followed by an empty line. Please insert an " + "empty line after {}:{}".format(directive_name, f, j) + ) continue k = j + 1 @@ -93,16 +103,20 @@ for f in sorted(Path('.').glob('**/*.rst')): break num_indent = num_spaces - base_indentation if j == k and num_indent != 4: - errors.append("Directive '{}' must be indented with 4 spaces, not {}. See " - "{}:{}".format(directive_name, num_indent, f, j+1)) + errors.append( + "Directive '{}' must be indented with 4 spaces, not {}. See " + "{}:{}".format(directive_name, num_indent, f, j + 1) + ) break for i, line in enumerate(lines): if esphome_io_regex.search(line): - if 'privacy.rst' in str(f) or 'web_server.rst' in str(f): + if "privacy.rst" in str(f) or "web_server.rst" in str(f): continue - errors.append("All links to esphome.io should be relative, please remove esphome.io " - "from URL. See {}:{}".format(f, i+1)) + errors.append( + "All links to esphome.io should be relative, please remove esphome.io " + "from URL. See {}:{}".format(f, i + 1) + ) for error in errors: diff --git a/web-api/index.rst b/web-api/index.rst index d7a4230e7..a19bbd751 100644 --- a/web-api/index.rst +++ b/web-api/index.rst @@ -194,7 +194,7 @@ GET request to ``/fan/``. "id": "fan-living_room_fan", "state": "ON", "value": true, - "speed": "high", + "speed_level": 2, "oscillation": false } @@ -202,11 +202,11 @@ GET request to ``/fan/``. - **id**: The id of the fan. Prefixed by ``fan-``. - **state**: The text-based state of the fan as a string. - **value**: The binary (``true``/``false``) state of the fan. -- **speed**: The speed setting of the fan if it's supported. Either "off", "low", "medium" or "high". +- **speed_level**: The speed level of the fan if it's supported. Value is between 1 and the maximum supported by the fan. - **oscillation**: Whether the oscillation setting of the fan is on. Only sent if the fan supports it. To control the state of the fan, send POST requests to ``/fan//turn_on``, ``/fan//turn_off`` and ``/fan//toggle``. Turn on additionally supports these optional parameters: -- **speed**: The new speed setting of the fan. Values as above. +- **speed_level**: The new speed level of the fan. Values as above. - **oscillation**: The new oscillation setting of the fan. Values as above.