├── watermeter-waterstarm ├── cc1101-esp32-c3.jpg └── watermeter-waterstarm.yaml ├── air-quality-zn-mt29 ├── air-quality-zn-mt29-case.jpg ├── air-quality-zn-mt29-rx-tx.jpg ├── air-quality-zn-mt29-pcb-top.jpg ├── air-quality-zn-mt29-open-case.jpg └── air-quality-zn-mt29.yaml ├── water-ph-orp-sensor-w2839 ├── water-ph-orp-sensor-w2839-airgap-rx-pin.jpg └── water-ph-orp-sensor-w2839.yaml ├── README.md ├── garden-monitor-hama-gm-300 ├── garden-monitor-hama-gm-300-sensor.yaml └── garden-monitor-hama-gm-300.yaml ├── ultrasonic-range-sensor-jsnsr04t30 └── ultrasonic-range-sensor-jsnsr04t30.yaml ├── electricitymeter-itron-openway-3hz └── electricitymeter-itron-openway-3hz.yaml ├── led-matrix-hub75-huidu-wf2 └── led-matrix-hub75-huidu-wf2.yaml ├── rainsensor-tfa-kw-9015r └── rainsensor-tfa-kw-9015r.yaml ├── liquid-level-sensor-qdy30a └── liquid-level-sensor-qdy30a.yaml └── electricitymeter-iskra-mt681 └── electricitymeter-iskra-mt681.yaml /watermeter-waterstarm/cc1101-esp32-c3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hn/esphome-configs/HEAD/watermeter-waterstarm/cc1101-esp32-c3.jpg -------------------------------------------------------------------------------- /air-quality-zn-mt29/air-quality-zn-mt29-case.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hn/esphome-configs/HEAD/air-quality-zn-mt29/air-quality-zn-mt29-case.jpg -------------------------------------------------------------------------------- /air-quality-zn-mt29/air-quality-zn-mt29-rx-tx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hn/esphome-configs/HEAD/air-quality-zn-mt29/air-quality-zn-mt29-rx-tx.jpg -------------------------------------------------------------------------------- /air-quality-zn-mt29/air-quality-zn-mt29-pcb-top.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hn/esphome-configs/HEAD/air-quality-zn-mt29/air-quality-zn-mt29-pcb-top.jpg -------------------------------------------------------------------------------- /air-quality-zn-mt29/air-quality-zn-mt29-open-case.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hn/esphome-configs/HEAD/air-quality-zn-mt29/air-quality-zn-mt29-open-case.jpg -------------------------------------------------------------------------------- /water-ph-orp-sensor-w2839/water-ph-orp-sensor-w2839-airgap-rx-pin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hn/esphome-configs/HEAD/water-ph-orp-sensor-w2839/water-ph-orp-sensor-w2839-airgap-rx-pin.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESPhome-configs 2 | 3 | A collection of config files to integrate various hardware into [ESPhome](https://esphome.io/). 4 | 5 | Please do me a favor: :thumbsup: If you use any information or code you find here, please link back to this page. 6 | :star: Also, please consider to star this project. I really like to keep track of who is using this to do creative things, especially if you are from other parts of the world. 7 | :smiley: You are welcome to open an issue to report on your personal success project and share it with others. 8 | 9 | - [ISKRA MT681 electricitymeter via infrared](electricitymeter-iskra-mt681/) 10 | 11 | - [Itron Openway 3.HZ electricitymeter via infrared](electricitymeter-itron-openway-3hz/) 12 | 13 | - [TFA KW-9015R rain sensor via 433Mhz wireless](rainsensor-tfa-kw-9015r/) 14 | 15 | - [HAMA GM-300 garden monitor via 433Mhz wireless](garden-monitor-hama-gm-300/) 16 | 17 | - [HUIDU HD-WF2 LED matrix controller](led-matrix-hub75-huidu-wf2/) 18 | 19 | - [JSN-SR04T V3.0 ultrasonic range sensor in serial mode](ultrasonic-range-sensor-jsnsr04t30/) 20 | Superseded by the [JSN-SR04T component](https://esphome.io/components/sensor/jsn_sr04t.html) 21 | 22 | - [W2839 Tuya PH ORP water sensor](water-ph-orp-sensor-w2839/) 23 | 24 | - [M-ETH WaterStarM Brummerhoop Lorenz WMBUS water meter via CC1101 radio module](watermeter-waterstarm/) 25 | 26 | - [ZN-MT29 Tuya Air quality sensor](air-quality-zn-mt29/) 27 | 28 | - [QDY30A RS485 liquid level sensor via ModBus/RS485](liquid-level-sensor-qdy30a/) 29 | 30 | - [B/S/H/ Bosch Siemens home appliances](https://github.com/hn/bsh-home-appliances) 31 | 32 | - [Ginlong Solis solar inverter via ModBus/RS485, using an ESP8266](https://github.com/hn/ginlong-solis#software-esphome) 33 | 34 | - [Ginlong Solis solar inverter, by replacing the firmware of the Solis S3 WiFi stick](https://github.com/hn/ginlong-solis#replacing-the-main-application) 35 | 36 | -------------------------------------------------------------------------------- /garden-monitor-hama-gm-300/garden-monitor-hama-gm-300-sensor.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # garden-monitor-hama-gm-300-sensor.yaml -- HAMA GM-300 garden monitor include file 3 | # 4 | # ! This file is to be included as a package in an ESPhome definition ! 5 | # 6 | # (C) 2023 Hajo Noerenberg 7 | # 8 | # http://www.noerenberg.de/ 9 | # https://github.com/hn/esphome-configs 10 | # 11 | # 12 | # This program is free software: you can redistribute it and/or modify 13 | # it under the terms of the GNU General Public License version 3.0 as 14 | # published by the Free Software Foundation. 15 | # 16 | # This program is distributed in the hope that it will be useful, 17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | # GNU General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License along 22 | # with this program. If not, see . 23 | # 24 | 25 | binary_sensor: 26 | - platform: template 27 | id: gm300_c${channel}_battery_low 28 | name: "${desc}: Battery" 29 | device_class: battery 30 | entity_category: diagnostic 31 | - platform: template 32 | id: gm300_c${channel}_forced_send 33 | name: "${desc}: Forced send" 34 | entity_category: diagnostic 35 | icon: mdi:gesture-tap-button 36 | 37 | sensor: 38 | - platform: template 39 | id: gm300_c${channel}_soil_temperature 40 | name: "${desc}: Soil temperature" 41 | device_class: temperature 42 | state_class: measurement 43 | unit_of_measurement: °C 44 | icon: mdi:coolant-temperature 45 | filters: 46 | - multiply: 0.1 47 | - platform: template 48 | id: gm300_c${channel}_air_temperature 49 | name: "${desc}: Air temperature" 50 | device_class: temperature 51 | state_class: measurement 52 | unit_of_measurement: °C 53 | icon: mdi:sun-thermometer-outline 54 | filters: 55 | - multiply: 0.1 56 | - platform: template 57 | id: gm300_c${channel}_moisture 58 | name: "${desc}: Moisture" 59 | device_class: moisture 60 | state_class: measurement 61 | unit_of_measurement: "%" 62 | accuracy_decimals: 2 63 | filters: 64 | - multiply: 33.333 65 | - platform: template 66 | id: gm300_c${channel}_randomid 67 | name: "${desc}: Random boot id" 68 | entity_category: diagnostic 69 | icon: mdi:numeric 70 | accuracy_decimals: 0 71 | -------------------------------------------------------------------------------- /ultrasonic-range-sensor-jsnsr04t30/ultrasonic-range-sensor-jsnsr04t30.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # ultrasonic-range-sensor-jsnsr04t30.yaml -- ESPhome config to read JSN-SR04T V3.0 in serial mode 3 | # 4 | # (C) 2023 Hajo Noerenberg 5 | # 6 | # Usage: Connect sensor to pin D5/D6, short-circuit solder jumper M2 to set serial mode 7 | # 8 | # http://www.noerenberg.de/ 9 | # https://github.com/hn/esphome-configs 10 | # 11 | # 12 | # This program is free software: you can redistribute it and/or modify 13 | # it under the terms of the GNU General Public License version 3.0 as 14 | # published by the Free Software Foundation. 15 | # 16 | # This program is distributed in the hope that it will be useful, 17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | # GNU General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License along 22 | # with this program. If not, see . 23 | # 24 | 25 | esphome: 26 | name: ultrasonic-range-sensor-jsnsr04t30 27 | friendly_name: Ultrasonic range sensor JSN-SR04T V3.0 28 | 29 | esp8266: 30 | board: d1_mini 31 | 32 | logger: 33 | 34 | api: 35 | encryption: 36 | key: !secret api_encryption_key 37 | 38 | ota: 39 | - platform: esphome 40 | password: !secret ota_password 41 | 42 | wifi: 43 | ssid: !secret wifi_ssid 44 | password: !secret wifi_password 45 | 46 | # Enable fallback hotspot (captive portal) in case wifi connection fails 47 | ap: 48 | ssid: "Range Sensor Fallback Hotspot" 49 | password: !secret wifi_ap_password 50 | 51 | captive_portal: 52 | 53 | uart: 54 | id: jsnsrt04t_uart 55 | rx_pin: D5 56 | tx_pin: D6 57 | baud_rate: 9600 58 | debug: 59 | direction: RX 60 | dummy_receiver: true 61 | sequence: 62 | - lambda: |- 63 | if (bytes[0] != 0xFF) return; 64 | if ((uint8_t) (bytes[0] + bytes[1] + bytes[2]) != bytes[3]) return; 65 | uint16_t d = ( bytes[1] << 8 ) | bytes[2]; 66 | id(jsnsrt04t_distance).publish_state((d == 0) ? NAN : d); 67 | id(jsnsrt04t_avg_distance).publish_state((d == 0) ? NAN : d); 68 | 69 | interval: 70 | - interval: 1s 71 | then: 72 | - uart.write: [0x55] 73 | 74 | sensor: 75 | - platform: template 76 | id: jsnsrt04t_distance 77 | name: Distance 78 | device_class: distance 79 | state_class: measurement 80 | unit_of_measurement: mm 81 | accuracy_decimals: 0 82 | - platform: template 83 | id: jsnsrt04t_avg_distance 84 | name: Average distance 85 | device_class: distance 86 | state_class: measurement 87 | unit_of_measurement: mm 88 | accuracy_decimals: 2 89 | filters: 90 | - throttle_average: 30s 91 | 92 | -------------------------------------------------------------------------------- /electricitymeter-itron-openway-3hz/electricitymeter-itron-openway-3hz.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # electricitymeter-itron-openway-3hz.yaml -- ESPhome config to read Itron OpenWay 3.HZ via IR/SML 3 | # 4 | # (C) 2023 Hajo Noerenberg 5 | # 6 | # Usage: Connect IR receiver to pin D5 7 | # 8 | # http://www.noerenberg.de/ 9 | # https://github.com/hn/esphome-configs 10 | # 11 | # 12 | # This program is free software: you can redistribute it and/or modify 13 | # it under the terms of the GNU General Public License version 3.0 as 14 | # published by the Free Software Foundation. 15 | # 16 | # This program is distributed in the hope that it will be useful, 17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | # GNU General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License along 22 | # with this program. If not, see . 23 | # 24 | 25 | esphome: 26 | name: electricitymeter-itron-openway-3hz 27 | friendly_name: Electricity Meter Itron OpenWay 3.HZ 28 | 29 | esp8266: 30 | board: d1_mini 31 | 32 | substitutions: 33 | throttle_time: "42s" 34 | sml_server_id: "123456789ABCDEF" 35 | 36 | logger: 37 | 38 | api: 39 | encryption: 40 | key: !secret api_encryption_key 41 | 42 | ota: 43 | - platform: esphome 44 | password: !secret ota_password 45 | 46 | wifi: 47 | ssid: !secret wifi_ssid 48 | password: !secret wifi_password 49 | 50 | # Enable fallback hotspot (captive portal) in case wifi connection fails 51 | ap: 52 | ssid: "Electricitymeter Fallback Hotspot" 53 | password: !secret wifi_ap_password 54 | 55 | captive_portal: 56 | 57 | uart: 58 | id: uart_bus 59 | rx_pin: D5 60 | baud_rate: 9600 61 | data_bits: 8 62 | parity: NONE 63 | stop_bits: 1 64 | 65 | sml: 66 | id: ir_sml 67 | uart_id: uart_bus 68 | 69 | sensor: 70 | - platform: sml 71 | name: "Bezug, tariflos" 72 | sml_id: ir_sml 73 | #server_id: ${sml_server_id} 74 | obis_code: "1-0:1.8.0" 75 | unit_of_measurement: Wh 76 | accuracy_decimals: 1 77 | device_class: energy 78 | state_class: total_increasing 79 | filters: 80 | - multiply: 0.1 81 | - throttle: ${throttle_time} 82 | - platform: sml 83 | name: "Einspeisung, tariflos" 84 | sml_id: ir_sml 85 | #server_id: ${sml_server_id} 86 | obis_code: "1-0:2.8.0" 87 | unit_of_measurement: Wh 88 | accuracy_decimals: 1 89 | device_class: energy 90 | state_class: total_increasing 91 | filters: 92 | - multiply: 0.1 93 | - throttle: ${throttle_time} 94 | - platform: sml 95 | name: "Wirkleistung gesamt" 96 | sml_id: ir_sml 97 | #server_id: ${sml_server_id} 98 | obis_code: "1-0:16.7.0" 99 | unit_of_measurement: W 100 | accuracy_decimals: 0 101 | device_class: power 102 | state_class: measurement 103 | filters: 104 | - throttle: ${throttle_time} 105 | 106 | text_sensor: 107 | - platform: sml 108 | name: "Manufacturer" 109 | sml_id: ir_sml 110 | #server_id: ${sml_server_id} 111 | obis_code: "1-0:96.50.1" 112 | format: text 113 | entity_category: diagnostic 114 | icon: mdi:factory 115 | - platform: sml 116 | name: "Device-Id" 117 | sml_id: ir_sml 118 | #server_id: ${sml_server_id} 119 | obis_code: "1-0:96.1.0" 120 | format: hex 121 | entity_category: diagnostic 122 | icon: mdi:numeric 123 | -------------------------------------------------------------------------------- /led-matrix-hub75-huidu-wf2/led-matrix-hub75-huidu-wf2.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # led-matrix-hub75-huidu-wf2.yaml -- ESPhome config for the HUIDU HD-WF2 LED matrix controller 3 | # 4 | # (C) 2023 Hajo Noerenberg 5 | # 6 | # Usage: See https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA/issues/433 7 | # 8 | # http://www.noerenberg.de/ 9 | # https://github.com/hn/esphome-configs 10 | # 11 | # 12 | # This program is free software: you can redistribute it and/or modify 13 | # it under the terms of the GNU General Public License version 3.0 as 14 | # published by the Free Software Foundation. 15 | # 16 | # This program is distributed in the hope that it will be useful, 17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | # GNU General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License along 22 | # with this program. If not, see . 23 | # 24 | 25 | esphome: 26 | name: led-matrix-hub75-huidu-wf2 27 | friendly_name: LED matrix Huidu HD-WF2 28 | platformio_options: 29 | board_build.flash_mode: dio 30 | 31 | external_components: 32 | - source: github://TillFleisch/ESPHome-HUB75-MatrixDisplayWrapper@main 33 | 34 | esp32: 35 | board: esp32-s3-devkitc-1 36 | framework: 37 | type: arduino 38 | 39 | # Enable logging 40 | logger: 41 | 42 | # Enable Home Assistant API 43 | api: 44 | encryption: 45 | key: !secret api_encryption_key 46 | 47 | ota: 48 | - platform: esphome 49 | password: !secret ota_password 50 | 51 | wifi: 52 | ssid: !secret wifi_ssid 53 | password: !secret wifi_password 54 | 55 | # Enable fallback hotspot (captive portal) in case wifi connection fails 56 | ap: 57 | ssid: "LED Matrix Huidu WF2 Fallback Hotspot" 58 | password: !secret wifi_ap_password 59 | 60 | captive_portal: 61 | 62 | i2c: 63 | sda: 41 64 | scl: 42 65 | 66 | time: 67 | - platform: pcf8563 68 | address: 0x51 69 | id: pcf8563_time 70 | - platform: homeassistant 71 | on_time_sync: 72 | then: 73 | pcf8563.write_time: 74 | 75 | font: 76 | # gfonts://family[@weight] 77 | - file: "gfonts://Roboto" 78 | id: roboto 79 | size: 12 80 | 81 | display: 82 | - platform: hub75_matrix_display 83 | id: huidu_wf2_x1 84 | width: 64 85 | height: 32 86 | chain_length: 2 87 | clock_phase: false 88 | R1_pin: 2 89 | R2_pin: 3 90 | G1_pin: 6 91 | G2_pin: 7 92 | B1_pin: 10 93 | B2_pin: 11 94 | A_pin: 39 95 | B_pin: 38 96 | C_pin: 37 97 | D_pin: 36 98 | E_pin: 21 99 | OE_pin: 35 100 | CLK_pin: 34 101 | LAT_pin: 33 102 | lambda: |- 103 | auto red = Color(255, 0, 0); 104 | auto blue = Color(0, 0, 255); 105 | auto rtc = id(pcf8563_time).now(); 106 | it.line(4, 25, 4 + 2 * rtc.second, 25, blue); 107 | it.rectangle(2, 2, 124, 28, red); 108 | it.strftime(7, 8, id(roboto), "%Y-%m-%d %H:%M:%S", rtc); 109 | //it.print(20, 10, id(roboto), "Hello World!"); 110 | 111 | switch: 112 | - platform: hub75_matrix_display 113 | matrix_id: huidu_wf2_x1 114 | restore_mode: ALWAYS_ON 115 | id: matrix_power 116 | - platform: gpio 117 | id: led_run 118 | pin: 40 119 | 120 | binary_sensor: 121 | - platform: gpio 122 | id: test_key 123 | pin: 124 | number: 17 125 | inverted: true 126 | 127 | number: 128 | - platform: hub75_matrix_display 129 | matrix_id: huidu_wf2_x1 130 | name: "Brightness" 131 | -------------------------------------------------------------------------------- /water-ph-orp-sensor-w2839/water-ph-orp-sensor-w2839.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # water-ph-orp-w2839.yaml -- ESPHome config to read W2839 Tuya PH ORP sensor 3 | # 4 | # (C) 2024 Hajo Noerenberg 5 | # 6 | # Usage: Open W2839 case and 7 | # a.) de-solder CB3S module completely - or - 8 | # b.) air-gap RX pin of the CB3S module (water-ph-orp-sensor-w2839-airgap-rx-pin.jpg) 9 | # to stop the Tuya MCU interfering. 10 | # WARNING: THE SOLDER PADS WILL TEAR OFF IF YOU PULL TOO HARD! 11 | # Then use ltchipttool to dump and write flash, see LibreTiny CB3S docs for further info. 12 | # Re-solder RX (and TX if necessary) pin. 13 | # 14 | # http://www.noerenberg.de/ 15 | # https://github.com/hn/esphome-configs 16 | # 17 | # 18 | # This program is free software: you can redistribute it and/or modify 19 | # it under the terms of the GNU General Public License version 3.0 as 20 | # published by the Free Software Foundation. 21 | # 22 | # This program is distributed in the hope that it will be useful, 23 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | # GNU General Public License for more details. 26 | # 27 | # You should have received a copy of the GNU General Public License along 28 | # with this program. If not, see . 29 | # 30 | 31 | esphome: 32 | name: water-ph-orp-w2839 33 | friendly_name: PH ORP Water Monitor 34 | 35 | bk72xx: 36 | board: cb3s 37 | 38 | logger: 39 | 40 | api: 41 | encryption: 42 | key: !secret api_encryption_key 43 | 44 | ota: 45 | - platform: esphome 46 | password: !secret ota_password 47 | 48 | wifi: 49 | ssid: !secret wifi_ssid 50 | password: !secret wifi_password 51 | 52 | # Enable fallback hotspot (captive portal) in case wifi connection fails 53 | ap: 54 | ssid: "PH ORP Sensor Fallback Hotspot" 55 | password: !secret wifi_ap_password 56 | 57 | captive_portal: 58 | 59 | tuya: 60 | 61 | # Datapoint 101: raw value (value: 01.01.00.00.00.00.01.00.00 (9)) 62 | # Datapoint 8: int value (value: 250) 63 | # Datapoint 102: int value (value: 350) 64 | # Datapoint 103: int value (value: 210) 65 | # Datapoint 106: int value (value: 1170) 66 | # Datapoint 107: int value (value: 700) 67 | # Datapoint 108: int value (value: 0) 68 | # Datapoint 111: int value (value: 0) 69 | # Datapoint 116: int value (value: 0) 70 | # Datapoint 121: int value (value: 0) 71 | # Datapoint 126: int value (value: 997) 72 | # Datapoint 131: int value (value: 60) 73 | # Datapoint 132: int value (value: 150) 74 | # Datapoint 133: int value (value: -2000) 75 | # Datapoint 136: int value (value: 0) 76 | # Datapoint 141: int value (value: 0) 77 | # Product: '{"p":"xxxxxxxxxxxxxxxx","v":"1.0.0","m":2}' 78 | 79 | uart: 80 | rx_pin: RX1 81 | tx_pin: TX1 82 | baud_rate: 9600 83 | 84 | sensor: 85 | - platform: tuya 86 | name: Temperature 87 | sensor_datapoint: 8 88 | state_class: measurement 89 | device_class: temperature 90 | unit_of_measurement: °C 91 | icon: mdi:water-thermometer 92 | accuracy_decimals: 1 93 | filters: 94 | - multiply: 0.1 95 | 96 | - platform: tuya 97 | name: pH 98 | sensor_datapoint: 106 99 | state_class: measurement 100 | icon: mdi:water-percent 101 | accuracy_decimals: 2 102 | filters: 103 | - multiply: 0.01 104 | 105 | - platform: tuya 106 | name: ORP 107 | sensor_datapoint: 131 108 | state_class: measurement 109 | device_class: voltage 110 | unit_of_measurement: mV 111 | icon: mdi:water-opacity 112 | 113 | number: 114 | - platform: tuya 115 | name: "pH max" 116 | number_datapoint: 107 117 | entity_category: config 118 | icon: mdi:water-percent 119 | min_value: 7.00 120 | max_value: 15.00 121 | multiply: 100 122 | step: 0.1 123 | mode: box 124 | 125 | - platform: tuya 126 | name: "pH min" 127 | number_datapoint: 108 128 | entity_category: config 129 | icon: mdi:water-percent 130 | min_value: 0.00 131 | max_value: 7.00 132 | multiply: 100 133 | step: 0.1 134 | mode: box 135 | 136 | - platform: tuya 137 | name: "ORP max" 138 | number_datapoint: 132 139 | entity_category: config 140 | device_class: voltage 141 | unit_of_measurement: mV 142 | icon: mdi:water-opacity 143 | min_value: -2000 144 | max_value: 2000 145 | step: 1 146 | 147 | - platform: tuya 148 | name: "ORP min" 149 | number_datapoint: 133 150 | entity_category: config 151 | device_class: voltage 152 | unit_of_measurement: mV 153 | icon: mdi:water-opacity 154 | min_value: -2000 155 | max_value: 2000 156 | step: 1 157 | 158 | -------------------------------------------------------------------------------- /rainsensor-tfa-kw-9015r/rainsensor-tfa-kw-9015r.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # rainsensor-tfa-kw-9015r.yaml -- ESPhome config to read TFA KW-9015R rain sensor via 433Mhz 3 | # 4 | # (C) 2023 Hajo Noerenberg 5 | # 6 | # Usage: Connect RXB8 433Mhz remote receiver data pin to D5 7 | # 8 | # http://www.noerenberg.de/ 9 | # https://github.com/hn/esphome-configs 10 | # 11 | # 12 | # This program is free software: you can redistribute it and/or modify 13 | # it under the terms of the GNU General Public License version 3.0 as 14 | # published by the Free Software Foundation. 15 | # 16 | # This program is distributed in the hope that it will be useful, 17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | # GNU General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License along 22 | # with this program. If not, see . 23 | # 24 | 25 | esphome: 26 | name: rainsensor-tfa-kw-9015r 27 | friendly_name: Rain sensor TFA KW-9015R 28 | 29 | esp8266: 30 | board: d1_mini 31 | 32 | # Enable logging 33 | logger: 34 | 35 | # Enable Home Assistant API 36 | api: 37 | encryption: 38 | key: !secret api_encryption_key 39 | 40 | ota: 41 | - platform: esphome 42 | password: !secret ota_password 43 | 44 | wifi: 45 | ssid: !secret wifi_ssid 46 | password: !secret wifi_password 47 | 48 | # Enable fallback hotspot (captive portal) in case wifi connection fails 49 | ap: 50 | ssid: "Rainsensor Fallback Hotspot" 51 | password: !secret wifi_ap_password 52 | 53 | captive_portal: 54 | 55 | remote_receiver: 56 | pin: D5 57 | filter: 250us 58 | idle: 8ms 59 | buffer_size: 512 # workaround for https://github.com/esphome/issues/issues/4698 60 | on_raw: 61 | then: 62 | - lambda: |- 63 | uint64_t out_code; 64 | uint8_t out_nbits; 65 | uint8_t tolerance = 20; 66 | auto protocol = new remote_base::RCSwitchBase(500, 9000, 500, 2000, 500, 4000, false); 67 | auto rrdata = new remote_base::RemoteReceiveData(x, tolerance, remote_base::TOLERANCE_MODE_PERCENTAGE); 68 | bool out_res = protocol->decode(*rrdata, &out_code, &out_nbits); 69 | delete rrdata; 70 | delete protocol; 71 | if (!out_res || out_nbits < 3) return; 72 | ESP_LOGD("rc_switch custom", "Received %d bit code 0x%llx", out_nbits, out_code); 73 | // 74 | // reverse bits, crc-check and interpret received data for TFA KW-9015R rain sensor 75 | if (out_nbits != 36) return; 76 | uint64_t value = 0; 77 | for (uint8_t i = 0; i < out_nbits; i++) { 78 | if (out_code & (1ULL << i)) value |= (1ULL << (out_nbits - 1 - i)); 79 | } 80 | uint8_t crc = 0; 81 | for (uint8_t j = 0; j < 8; j++) crc += (uint8_t)(value >> (j * 4)); 82 | if ((crc & 0b1111) != (uint8_t)(value >> 32 & 0b1111)) return; 83 | // 84 | id(kw9015r_randomid).publish_state((uint8_t)(value & 0b11001111)); 85 | id(kw9015r_channel).publish_state((uint8_t)(value >> 4 & 0b11)); 86 | id(kw9015r_battery_low).publish_state((uint8_t)(value >> 8 & 0b1)); 87 | id(kw9015r_forced_send).publish_state((uint8_t)(value >> 11 & 0b1)); 88 | id(kw9015r_precipitation).publish_state((uint8_t)(value >> 24 & 0b11111111)); 89 | int16_t temperature = value >> 12 & 0b111111111111; 90 | if (temperature & 0b100000000000) temperature |= 0b1111000000000000; 91 | id(kw9015r_temperature).publish_state(temperature); 92 | id(kw9015r_temptend).publish_state(std::to_string((uint8_t)(value >> 9 & 0b11))); 93 | return; 94 | 95 | binary_sensor: 96 | - platform: template 97 | id: kw9015r_battery_low 98 | name: Battery 99 | device_class: battery 100 | entity_category: diagnostic 101 | - platform: template 102 | id: kw9015r_forced_send 103 | name: Forced send 104 | entity_category: diagnostic 105 | icon: mdi:gesture-tap-button 106 | 107 | sensor: 108 | - platform: template 109 | id: kw9015r_temperature 110 | name: Temperature 111 | device_class: temperature 112 | state_class: measurement 113 | unit_of_measurement: °C 114 | filters: 115 | - multiply: 0.1 116 | - platform: template 117 | id: kw9015r_precipitation 118 | name: Precipitation 119 | device_class: precipitation 120 | state_class: total_increasing 121 | unit_of_measurement: mm 122 | accuracy_decimals: 2 123 | filters: 124 | - multiply: 0.45 125 | - platform: template 126 | id: kw9015r_channel 127 | name: Channel 128 | icon: mdi:alpha-c-box 129 | accuracy_decimals: 0 130 | entity_category: diagnostic 131 | - platform: template 132 | id: kw9015r_randomid 133 | name: Random boot id 134 | icon: mdi:numeric 135 | accuracy_decimals: 0 136 | entity_category: diagnostic 137 | 138 | text_sensor: 139 | - platform: template 140 | id: kw9015r_temptend 141 | name: Temperature tendency 142 | icon: mdi:thermometer-lines 143 | filters: 144 | - map: 145 | - 0 -> steady 146 | - 1 -> falling 147 | - 2 -> rising 148 | - 3 -> unknown 149 | 150 | -------------------------------------------------------------------------------- /watermeter-waterstarm/watermeter-waterstarm.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # watermeter-waterstar-cc1101.yaml -- ESPHome config to read WMBUS watermeter via CC1101 radio 868 Mhz 3 | # 4 | # WaterStarM M-ETH Q3 2,5 Water Meter, 5 | # marketed by: Brummerhoop 6 | # https://www.brummerhoop.com/media/ce/2a/62/1668505287/1081600001_2019-02-20_ba_waterstar_m_mid_de_en.pdf 7 | # manufactured by: Lorenz GmbH & Co. KG 8 | # technical support by: Engelmann Sensor GmbH 9 | # 10 | # By factory default, the M-ETH watermeter only sends data during the day from 08:00-18:00, 11 | # use https://github.com/hn/em-admin to change the settings if needed. 12 | # 13 | # (C) 2025 Hajo Noerenberg 14 | # 15 | # Usage: Connect CC1101 'green pcb' radio module to ESP32 via SPI 16 | # 17 | # garden_watermeter_id in secrets.yaml has to be prefixed with "0x" (hex number) 18 | # 19 | # http://www.noerenberg.de/ 20 | # https://github.com/hn/esphome-configs 21 | # 22 | # 23 | # This program is free software: you can redistribute it and/or modify 24 | # it under the terms of the GNU General Public License version 3.0 as 25 | # published by the Free Software Foundation. 26 | # 27 | # This program is distributed in the hope that it will be useful, 28 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 29 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 | # GNU General Public License for more details. 31 | # 32 | # You should have received a copy of the GNU General Public License along 33 | # with this program. If not, see . 34 | # 35 | 36 | esphome: 37 | name: watermeter-waterstarm 38 | friendly_name: Watermeter WaterStarM 39 | platformio_options: 40 | board_build.flash_mode: dio 41 | 42 | # https://www.sudo.is/docs/esphome/boards/esp32c3supermini/ 43 | esp32: 44 | board: esp32-c3-devkitm-1 45 | variant: ESP32C3 46 | 47 | logger: 48 | 49 | api: 50 | encryption: 51 | key: !secret api_encryption_key 52 | 53 | ota: 54 | - platform: esphome 55 | password: !secret ota_password 56 | 57 | wifi: 58 | ssid: !secret wifi_ssid 59 | password: !secret wifi_password 60 | 61 | # Enable fallback hotspot (captive portal) in case wifi connection fails 62 | ap: 63 | ssid: "CC1101 Fallback Hotspot" 64 | password: !secret wifi_ap_password 65 | 66 | captive_portal: 67 | 68 | external_components: 69 | - source: github://SzczepanLeon/esphome-components@version_4 70 | components: [ wmbus ] 71 | # refresh: 0d 72 | 73 | time: 74 | - platform: homeassistant 75 | 76 | wmbus: 77 | mosi_pin: GPIO6 78 | miso_pin: GPIO5 79 | clk_pin: GPIO4 80 | cs_pin: GPIO7 81 | gdo0_pin: GPIO10 82 | gdo2_pin: GPIO3 83 | 84 | led_pin: 85 | number: GPIO8 86 | inverted: true 87 | 88 | all_drivers: False 89 | log_all: True 90 | 91 | sensor: 92 | - platform: wmbus 93 | meter_id: !secret garden_watermeter_id 94 | type: WaterStarM 95 | key: !secret garden_watermeter_aes_key 96 | sensors: 97 | - name: "Total water consumption" 98 | field: "total" 99 | accuracy_decimals: 3 100 | unit_of_measurement: "m³" 101 | device_class: "water" 102 | state_class: "total_increasing" 103 | - id: wmbus_meter_time 104 | # name: "WMBUS Meter internal time" 105 | field: "meter" 106 | unit_of_measurement: "datetime" 107 | # device_class: "timestamp" # does not work 108 | entity_category: diagnostic 109 | on_value: 110 | then: 111 | - lambda: "id(meter_time).publish_state(x);" 112 | - platform: template 113 | name: "Meter internal time" 114 | id: meter_time 115 | device_class: "timestamp" 116 | entity_category: diagnostic 117 | accuracy_decimals: 0 118 | 119 | # To display the date in Home Assistant in absolute rather than relative format, 120 | # edit Home Assistant entities card and set 'format' attribute via code editor: 121 | # https://www.home-assistant.io/dashboards/entities/#attribute 122 | # 123 | # - entity: sensor.watermeter_waterstarm_meter_internal_time 124 | # name: Meter internal time 125 | # format: datetime 126 | 127 | text_sensor: 128 | - platform: wmbus 129 | meter_id: !secret garden_watermeter_id 130 | type: WaterStarM 131 | key: !secret garden_watermeter_aes_key 132 | sensors: 133 | - name: "Meter status" 134 | field: "status" 135 | entity_category: diagnostic 136 | icon: mdi:list-status 137 | on_value: 138 | then: 139 | - lambda: |- 140 | // main/components/wmbus/driver_waterstarm.cpp#L55 141 | bool battery_error = (x.find("BATTERY_VOLTAGE_ERROR") != std::string::npos); 142 | id(meter_battery).publish_state(battery_error); 143 | bool leakage_detected = (x.find("LEAKAGE_OR_NO_USAGE") != std::string::npos); 144 | id(leakage).publish_state(leakage_detected); 145 | bool reverse_flow_detected = (x.find("REVERSE_FLOW") != std::string::npos); 146 | id(reverse_flow).publish_state(reverse_flow_detected); 147 | 148 | binary_sensor: 149 | - platform: template 150 | id: meter_battery 151 | name: "Meter battery" 152 | device_class: battery 153 | entity_category: diagnostic 154 | - platform: template 155 | id: leakage 156 | name: "Leakage" 157 | device_class: problem 158 | entity_category: diagnostic 159 | - platform: template 160 | id: reverse_flow 161 | name: "Reverse flow" 162 | device_class: problem 163 | entity_category: diagnostic 164 | -------------------------------------------------------------------------------- /liquid-level-sensor-qdy30a/liquid-level-sensor-qdy30a.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # liquid-level-sensor-qdy30a.yaml -- ESPhome config to read QDY30A RS485 liquid level sensor 3 | # 4 | # (C) 2023 Hajo Noerenberg 5 | # 6 | # Usage: Connect RS485 adapter HW-0519 to pin D5/D6, connect QDY30A to RS485 7 | # 8 | # http://www.noerenberg.de/ 9 | # https://github.com/hn/esphome-configs 10 | # 11 | # 12 | # This program is free software: you can redistribute it and/or modify 13 | # it under the terms of the GNU General Public License version 3.0 as 14 | # published by the Free Software Foundation. 15 | # 16 | # This program is distributed in the hope that it will be useful, 17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | # GNU General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License along 22 | # with this program. If not, see . 23 | # 24 | 25 | esphome: 26 | name: liquid-level-sensor-qdy30a 27 | friendly_name: Liquid level sensor QDY30A 28 | 29 | esp8266: 30 | board: d1_mini 31 | 32 | logger: 33 | 34 | api: 35 | encryption: 36 | key: !secret api_encryption_key 37 | 38 | ota: 39 | - platform: esphome 40 | password: !secret ota_password 41 | 42 | wifi: 43 | ssid: !secret wifi_ssid 44 | password: !secret wifi_password 45 | 46 | # Enable fallback hotspot (captive portal) in case wifi connection fails 47 | ap: 48 | ssid: "Liquid Sensor Fallback Hotspot" 49 | password: !secret wifi_ap_password 50 | 51 | captive_portal: 52 | 53 | uart: 54 | id: modbus_uart 55 | tx_pin: D6 56 | rx_pin: D5 57 | baud_rate: 9600 58 | 59 | modbus: 60 | #flow_control_pin: D7 61 | send_wait_time: 300ms 62 | id: modbus_hw 63 | 64 | modbus_controller: 65 | - id: modbus_master 66 | address: 0x1 67 | modbus_id: modbus_hw 68 | setup_priority: -10 69 | update_interval: 2s 70 | 71 | sensor: 72 | - platform: template 73 | id: water_volume 74 | name: Water volume 75 | device_class: volume_storage 76 | state_class: measurement 77 | icon: mdi:water 78 | unit_of_measurement: L 79 | accuracy_decimals: 1 80 | filters: 81 | - calibrate_linear: 82 | method: exact 83 | datapoints: 84 | - 20.0 -> 0 85 | - 80.0 -> 1000 86 | - platform: modbus_controller 87 | modbus_controller_id: modbus_master 88 | id: liquid_level 89 | name: Liquid level 90 | register_type: holding 91 | value_type: S_WORD 92 | address: 0x0004 93 | force_new_range: true 94 | device_class: distance 95 | state_class: measurement 96 | icon: mdi:car-coolant-level 97 | unit_of_measurement: cm 98 | accuracy_decimals: 1 99 | filters: 100 | - multiply: 0.1 101 | - throttle_average: 20s 102 | on_value: 103 | then: 104 | - lambda: "id(water_volume).publish_state(truncf(x*10)/10);" 105 | - platform: modbus_controller 106 | modbus_controller_id: modbus_master 107 | name: Liquid level minimum 108 | register_type: holding 109 | value_type: S_WORD 110 | address: 0x0005 111 | skip_updates: 200 112 | entity_category: diagnostic 113 | device_class: distance 114 | icon: mdi:format-vertical-align-bottom 115 | unit_of_measurement: cm 116 | accuracy_decimals: 1 117 | filters: 118 | - multiply: 0.1 119 | - platform: modbus_controller 120 | modbus_controller_id: modbus_master 121 | name: Liquid level maximum 122 | register_type: holding 123 | value_type: S_WORD 124 | address: 0x0006 125 | skip_updates: 200 126 | entity_category: diagnostic 127 | device_class: distance 128 | icon: mdi:format-vertical-align-top 129 | unit_of_measurement: cm 130 | accuracy_decimals: 1 131 | filters: 132 | - multiply: 0.1 133 | 134 | number: 135 | - platform: modbus_controller 136 | name: ModBus address 137 | register_type: holding 138 | address: 0x0000 139 | entity_category: config 140 | icon: mdi:numeric 141 | skip_updates: 200 142 | mode: box 143 | min_value: 1 144 | max_value: 255 145 | write_lambda: "return {};" # disable updates, remove if needed - not tested 146 | 147 | select: 148 | - platform: modbus_controller 149 | name: Baud rate 150 | address: 0x0001 151 | entity_category: config 152 | icon: mdi:speedometer 153 | skip_updates: 200 154 | optionsmap: 155 | "1200": 0 156 | "2400": 1 157 | "4800": 2 158 | "9600": 3 159 | "19200": 4 160 | "38400": 5 161 | "57600": 6 162 | "115200": 7 163 | write_lambda: "return {};" # disable updates, remove if needed - not tested 164 | - platform: modbus_controller 165 | name: Pressure unit 166 | address: 0x0002 167 | entity_category: config 168 | icon: mdi:alpha-u-circle-outline 169 | skip_updates: 200 170 | optionsmap: 171 | "Unknown": 0 172 | "cm": 1 173 | "mm": 2 174 | "mPa": 3 175 | "Pa": 4 176 | "kPa": 5 177 | "MA": 6 178 | write_lambda: "return {};" # disable updates, remove if needed - not tested 179 | - platform: modbus_controller 180 | name: Decimal points 181 | address: 0x0003 182 | entity_category: config 183 | icon: mdi:decimal-comma-decrease 184 | skip_updates: 200 185 | optionsmap: 186 | "####": 0 187 | "###.#": 1 188 | "##.##": 2 189 | "#.###": 3 190 | write_lambda: "return {};" # disable updates, remove if needed - not tested 191 | -------------------------------------------------------------------------------- /electricitymeter-iskra-mt681/electricitymeter-iskra-mt681.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # electricitymeter-iskra-mt681.yaml -- ESPhome config to read ISKRA MT681 via IR/SML 3 | # 4 | # (C) 2023 Hajo Noerenberg 5 | # 6 | # Usage: Connect IR receiver to pin D5 7 | # 8 | # http://www.noerenberg.de/ 9 | # https://github.com/hn/esphome-configs 10 | # 11 | # 12 | # This program is free software: you can redistribute it and/or modify 13 | # it under the terms of the GNU General Public License version 3.0 as 14 | # published by the Free Software Foundation. 15 | # 16 | # This program is distributed in the hope that it will be useful, 17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | # GNU General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License along 22 | # with this program. If not, see . 23 | # 24 | 25 | esphome: 26 | name: electricitymeter-iskra-mt681 27 | friendly_name: Electricity Meter ISKRA MT681 28 | 29 | esp8266: 30 | board: d1_mini 31 | 32 | substitutions: 33 | throttle_time: "42s" 34 | sml_server_id: "123456789ABCDEF" 35 | 36 | logger: 37 | 38 | api: 39 | encryption: 40 | key: !secret api_encryption_key 41 | 42 | ota: 43 | - platform: esphome 44 | password: !secret ota_password 45 | 46 | wifi: 47 | ssid: !secret wifi_ssid 48 | password: !secret wifi_password 49 | 50 | # Enable fallback hotspot (captive portal) in case wifi connection fails 51 | ap: 52 | ssid: "Electricitymeter Fallback Hotspot" 53 | password: !secret wifi_ap_password 54 | 55 | captive_portal: 56 | 57 | uart: 58 | id: uart_bus 59 | rx_pin: D5 60 | baud_rate: 9600 61 | data_bits: 8 62 | parity: NONE 63 | stop_bits: 1 64 | 65 | sml: 66 | id: ir_sml 67 | uart_id: uart_bus 68 | 69 | sensor: 70 | - platform: sml 71 | name: "Bezug, tariflos" 72 | sml_id: ir_sml 73 | #server_id: ${sml_server_id} 74 | obis_code: "1-0:1.8.0" 75 | unit_of_measurement: Wh 76 | accuracy_decimals: 1 77 | device_class: energy 78 | state_class: total_increasing 79 | filters: 80 | - multiply: 0.1 81 | - throttle: ${throttle_time} 82 | - platform: sml 83 | name: "Bezug, Tarif 1" 84 | sml_id: ir_sml 85 | #server_id: ${sml_server_id} 86 | obis_code: "1-0:1.8.1" 87 | unit_of_measurement: Wh 88 | accuracy_decimals: 1 89 | device_class: energy 90 | state_class: total_increasing 91 | filters: 92 | - multiply: 0.1 93 | - throttle: ${throttle_time} 94 | - platform: sml 95 | name: "Bezug, Tarif 2" 96 | sml_id: ir_sml 97 | #server_id: ${sml_server_id} 98 | obis_code: "1-0:1.8.1" 99 | unit_of_measurement: Wh 100 | accuracy_decimals: 1 101 | device_class: energy 102 | state_class: total_increasing 103 | filters: 104 | - multiply: 0.1 105 | - throttle: ${throttle_time} 106 | - platform: sml 107 | name: "Einspeisung, tariflos" 108 | sml_id: ir_sml 109 | #server_id: ${sml_server_id} 110 | obis_code: "1-0:2.8.0" 111 | unit_of_measurement: Wh 112 | accuracy_decimals: 1 113 | device_class: energy 114 | state_class: total_increasing 115 | filters: 116 | - multiply: 0.1 117 | - throttle: ${throttle_time} 118 | - platform: sml 119 | name: "Einspeisung, Tarif 1" 120 | sml_id: ir_sml 121 | #server_id: ${sml_server_id} 122 | obis_code: "1-0:2.8.1" 123 | unit_of_measurement: Wh 124 | accuracy_decimals: 1 125 | device_class: energy 126 | state_class: total_increasing 127 | filters: 128 | - multiply: 0.1 129 | - throttle: ${throttle_time} 130 | - platform: sml 131 | name: "Einspeisung, Tarif 2" 132 | sml_id: ir_sml 133 | #server_id: ${sml_server_id} 134 | obis_code: "1-0:2.8.2" 135 | unit_of_measurement: Wh 136 | accuracy_decimals: 1 137 | device_class: energy 138 | state_class: total_increasing 139 | filters: 140 | - multiply: 0.1 141 | - throttle: ${throttle_time} 142 | - platform: sml 143 | name: "Wirkleistung gesamt" 144 | sml_id: ir_sml 145 | #server_id: ${sml_server_id} 146 | obis_code: "1-0:16.7.0" 147 | unit_of_measurement: W 148 | accuracy_decimals: 0 149 | device_class: power 150 | state_class: measurement 151 | filters: 152 | - throttle: ${throttle_time} 153 | - platform: sml 154 | name: "Wirkleistung L1" 155 | sml_id: ir_sml 156 | #server_id: ${sml_server_id} 157 | obis_code: "1-0:36.7.0" 158 | unit_of_measurement: W 159 | accuracy_decimals: 0 160 | device_class: power 161 | state_class: measurement 162 | filters: 163 | - throttle: ${throttle_time} 164 | - platform: sml 165 | name: "Wirkleistung L2" 166 | sml_id: ir_sml 167 | #server_id: ${sml_server_id} 168 | obis_code: "1-0:56.7.0" 169 | unit_of_measurement: W 170 | accuracy_decimals: 0 171 | device_class: power 172 | state_class: measurement 173 | filters: 174 | - throttle: ${throttle_time} 175 | - platform: sml 176 | name: "Wirkleistung L3" 177 | sml_id: ir_sml 178 | #server_id: ${sml_server_id} 179 | obis_code: "1-0:76.7.0" 180 | unit_of_measurement: W 181 | accuracy_decimals: 0 182 | device_class: power 183 | state_class: measurement 184 | filters: 185 | - throttle: ${throttle_time} 186 | 187 | text_sensor: 188 | - platform: sml 189 | name: "Manufacturer" 190 | sml_id: ir_sml 191 | #server_id: ${sml_server_id} 192 | obis_code: "129-129:199.130.3" 193 | format: text 194 | entity_category: diagnostic 195 | icon: mdi:factory 196 | - platform: sml 197 | name: "Public Key" 198 | sml_id: ir_sml 199 | #server_id: ${sml_server_id} 200 | obis_code: "129-129:199.130.5" 201 | format: text 202 | entity_category: diagnostic 203 | icon: mdi:numeric 204 | filters: 205 | - lambda: |- 206 | std::string hexstr = format_hex_pretty((uint8_t *) x.c_str(), x.size()); 207 | replace(hexstr.begin(), hexstr.end(), '.', ' '); 208 | return hexstr; 209 | -------------------------------------------------------------------------------- /garden-monitor-hama-gm-300/garden-monitor-hama-gm-300.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # garden-monitor-hama-gm-300.yaml -- ESPhome config to read HAMA GM-300 garden monitor via 433Mhz 3 | # 4 | # (C) 2023 Hajo Noerenberg 5 | # 6 | # Usage: Connect RXB8 433Mhz remote receiver data pin to D5 7 | # 8 | # http://www.noerenberg.de/ 9 | # https://github.com/hn/esphome-configs 10 | # 11 | # 12 | # This program is free software: you can redistribute it and/or modify 13 | # it under the terms of the GNU General Public License version 3.0 as 14 | # published by the Free Software Foundation. 15 | # 16 | # This program is distributed in the hope that it will be useful, 17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | # GNU General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License along 22 | # with this program. If not, see . 23 | # 24 | 25 | esphome: 26 | name: garden-monitor-hama-gm-300 27 | friendly_name: Garden monitor HAMA GM-300 28 | 29 | esp8266: 30 | board: d1_mini 31 | 32 | # Enable logging 33 | logger: 34 | 35 | # Enable Home Assistant API 36 | api: 37 | encryption: 38 | key: !secret api_encryption_key 39 | 40 | ota: 41 | - platform: esphome 42 | password: !secret ota_password 43 | 44 | wifi: 45 | ssid: !secret wifi_ssid 46 | password: !secret wifi_password 47 | 48 | # Enable fallback hotspot (captive portal) in case wifi connection fails 49 | ap: 50 | ssid: "Garden-Monitor Fallback Hotspot" 51 | password: !secret wifi_ap_password 52 | 53 | captive_portal: 54 | 55 | packages: 56 | c1_sensor: !include 57 | file: common/garden-monitor-hama-gm-300-sensor.yaml 58 | vars: 59 | channel: 1 60 | desc: Pink orchid 61 | c2_sensor: !include 62 | file: common/garden-monitor-hama-gm-300-sensor.yaml 63 | vars: 64 | channel: 2 65 | desc: Lime tree 66 | c3_sensor: !include 67 | file: common/garden-monitor-hama-gm-300-sensor.yaml 68 | vars: 69 | channel: 3 70 | desc: Calla flower 71 | c4_sensor: !include 72 | file: common/garden-monitor-hama-gm-300-sensor.yaml 73 | vars: 74 | channel: 4 75 | desc: Amaryllis 76 | c5_sensor: !include 77 | file: common/garden-monitor-hama-gm-300-sensor.yaml 78 | vars: 79 | channel: 5 80 | desc: Sunflower 81 | 82 | # Connect RXB8 433Mhz remote receiver data pin to D5 83 | remote_receiver: 84 | pin: D5 85 | filter: 250us 86 | idle: 5ms 87 | buffer_size: 512 # workaround for https://github.com/esphome/issues/issues/4698 88 | on_raw: 89 | then: 90 | - lambda: |- 91 | uint64_t out_code; 92 | uint8_t out_nbits; 93 | uint8_t tolerance = 20; 94 | auto protocol = new remote_base::RCSwitchBase(500, 6000, 500, 1000, 500, 2000, false); 95 | auto rrdata = new remote_base::RemoteReceiveData(x, tolerance, remote_base::TOLERANCE_MODE_PERCENTAGE); 96 | bool out_res = protocol->decode(*rrdata, &out_code, &out_nbits); 97 | delete rrdata; 98 | delete protocol; 99 | if (!out_res || out_nbits < 3) return; 100 | ESP_LOGD("rc_switch custom", "Received %d bit code 0x%llx", out_nbits, out_code); 101 | // 102 | // crc-check, reverse bits and interpret received data for HAMA HAMA GM-300 garden monitor 103 | if (out_nbits != 64) return; 104 | uint8_t crc = 0xff; 105 | for (uint8_t i = 8 * 7; i; i -= 8) { 106 | crc ^= out_code >> i; 107 | for (uint8_t j = 0; j < 8; j++) { 108 | crc = crc & 0x80 ? (crc << 1) ^ 0x31 : crc << 1; 109 | } 110 | } 111 | if (crc != (uint8_t) out_code) return; 112 | uint64_t value = 0; 113 | for (uint8_t i = 0; i < out_nbits; i++) { 114 | if (out_code & (1ULL << i)) value |= (1ULL << (out_nbits - 1 - i)); 115 | } 116 | // 117 | uint16_t randomid = value & 0b111111111111; 118 | bool forced_send = value >> 15 & 0b1; 119 | bool battery_low = value >> 16 & 0b1; 120 | uint8_t moisture = value >> 17 & 0b11; 121 | int16_t soil_temperature = value >> 20 & 0b111111111111; 122 | if (soil_temperature & 0b100000000000) soil_temperature |= 0b1111000000000000; 123 | int16_t air_temperature = value >> 32 & 0b111111111111; 124 | if (air_temperature & 0b100000000000) air_temperature |= 0b1111000000000000; 125 | // 126 | // uuhhh, oohhh, this is ugly ... 127 | switch(1 + (uint8_t)(value >> 12 & 0b111)) { 128 | case 1: 129 | id(gm300_c1_randomid).publish_state(randomid); 130 | id(gm300_c1_forced_send).publish_state(forced_send); 131 | id(gm300_c1_battery_low).publish_state(battery_low); 132 | id(gm300_c1_moisture).publish_state(moisture); 133 | id(gm300_c1_soil_temperature).publish_state(soil_temperature); 134 | id(gm300_c1_air_temperature).publish_state(air_temperature); 135 | break; 136 | case 2: 137 | id(gm300_c2_randomid).publish_state(randomid); 138 | id(gm300_c2_forced_send).publish_state(forced_send); 139 | id(gm300_c2_battery_low).publish_state(battery_low); 140 | id(gm300_c2_moisture).publish_state(moisture); 141 | id(gm300_c2_soil_temperature).publish_state(soil_temperature); 142 | id(gm300_c2_air_temperature).publish_state(air_temperature); 143 | break; 144 | case 3: 145 | id(gm300_c3_randomid).publish_state(randomid); 146 | id(gm300_c3_forced_send).publish_state(forced_send); 147 | id(gm300_c3_battery_low).publish_state(battery_low); 148 | id(gm300_c3_moisture).publish_state(moisture); 149 | id(gm300_c3_soil_temperature).publish_state(soil_temperature); 150 | id(gm300_c3_air_temperature).publish_state(air_temperature); 151 | break; 152 | case 4: 153 | id(gm300_c4_randomid).publish_state(randomid); 154 | id(gm300_c4_forced_send).publish_state(forced_send); 155 | id(gm300_c4_battery_low).publish_state(battery_low); 156 | id(gm300_c4_moisture).publish_state(moisture); 157 | id(gm300_c4_soil_temperature).publish_state(soil_temperature); 158 | id(gm300_c4_air_temperature).publish_state(air_temperature); 159 | break; 160 | case 5: 161 | id(gm300_c5_randomid).publish_state(randomid); 162 | id(gm300_c5_forced_send).publish_state(forced_send); 163 | id(gm300_c5_battery_low).publish_state(battery_low); 164 | id(gm300_c5_moisture).publish_state(moisture); 165 | id(gm300_c5_soil_temperature).publish_state(soil_temperature); 166 | id(gm300_c5_air_temperature).publish_state(air_temperature); 167 | break; 168 | } 169 | 170 | return; 171 | -------------------------------------------------------------------------------- /air-quality-zn-mt29/air-quality-zn-mt29.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # air-quality-zn-mt29.yaml -- ESPHome config to read ZN-MT29 Tuya Air Quality Sensor 3 | # 4 | # (C) 2025 Hajo Noerenberg 5 | # 6 | # Usage: Open ZN-MT29 case (air-quality-zn-mt29-open-case.jpg) and 7 | # 1a.) de-solder CBU module completely - or - 8 | # 1b.) temporarily remove SMD resistor R18 from PCB 9 | # to stop the Tuya MCU interfering. 10 | # 2.) Connect GND/3v3/RX/TX to CBU MCU (air-quality-zn-mt29-rx-tx.jpg). 11 | # 3.) Use ltchipttool to dump and write flash, see LibreTiny CBU docs for further info. 12 | # 4.) Remove cables, re-solder CBU module or R18. 13 | # 14 | # http://www.noerenberg.de/ 15 | # https://github.com/hn/esphome-configs 16 | # 17 | # 18 | # This program is free software: you can redistribute it and/or modify 19 | # it under the terms of the GNU General Public License version 3.0 as 20 | # published by the Free Software Foundation. 21 | # 22 | # This program is distributed in the hope that it will be useful, 23 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 24 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 | # GNU General Public License for more details. 26 | # 27 | # You should have received a copy of the GNU General Public License along 28 | # with this program. If not, see . 29 | # 30 | 31 | esphome: 32 | name: air-quality-zn-mt29 33 | friendly_name: Air Quality Monitor ZN-MT29 34 | platformio_options: 35 | platform_packages: 36 | - framework-arduino-api @ https://github.com/hn/ArduinoCore-API#RingBufferSize512 37 | 38 | bk72xx: 39 | board: cbu 40 | 41 | logger: 42 | 43 | api: 44 | encryption: 45 | key: !secret api_encryption_key 46 | 47 | ota: 48 | - platform: esphome 49 | password: !secret ota_password 50 | 51 | wifi: 52 | ssid: !secret wifi_ssid 53 | password: !secret wifi_password 54 | 55 | # Enable fallback hotspot (captive portal) in case wifi connection fails 56 | ap: 57 | ssid: "Air Quality Sensor Hotspot" 58 | password: !secret wifi_ap_password 59 | 60 | captive_portal: 61 | 62 | time: 63 | - platform: homeassistant 64 | id: network_time 65 | 66 | uart: 67 | rx_pin: RX1 68 | tx_pin: TX1 69 | baud_rate: 115200 70 | 71 | tuya: 72 | time_id: network_time 73 | on_datapoint_update: 74 | - sensor_datapoint: 1 75 | datapoint_type: enum 76 | then: 77 | - text_sensor.template.publish: 78 | id: tuya_air_quality_index 79 | state: !lambda "return std::to_string(x);" 80 | 81 | text_sensor: 82 | - platform: template 83 | id: tuya_air_quality_index 84 | name: Air Quality Index 85 | icon: mdi:air-filter 86 | filters: 87 | - map: 88 | - 0 -> Good 89 | - 1 -> Moderate 90 | - 2 -> Unhealthy 91 | 92 | text: 93 | - platform: template 94 | id: alarm1_text 95 | name: Alarm Time 1 96 | icon: mdi:alarm 97 | min_length: 5 98 | max_length: 5 99 | mode: text 100 | set_action: 101 | - number.set: 102 | id: alarm1 103 | value: !lambda |- 104 | unsigned int h, m; 105 | if (sscanf(x.c_str(), "%d:%d", &h, &m) == 2) 106 | return h * 60 + m; 107 | return 0; 108 | - platform: template 109 | id: alarm2_text 110 | name: Alarm Time 2 111 | icon: mdi:alarm 112 | min_length: 5 113 | max_length: 5 114 | mode: text 115 | set_action: 116 | - number.set: 117 | id: alarm2 118 | value: !lambda |- 119 | unsigned int h, m; 120 | if (sscanf(x.c_str(), "%d:%d", &h, &m) == 2) 121 | return h * 60 + m; 122 | return 0; 123 | - platform: template 124 | id: alarm3_text 125 | name: Alarm Time 3 126 | icon: mdi:alarm 127 | min_length: 5 128 | max_length: 5 129 | mode: text 130 | set_action: 131 | - number.set: 132 | id: alarm3 133 | value: !lambda |- 134 | unsigned int h, m; 135 | if (sscanf(x.c_str(), "%d:%d", &h, &m) == 2) 136 | return h * 60 + m; 137 | return 0; 138 | 139 | sensor: 140 | - platform: tuya 141 | sensor_datapoint: 2 142 | name: Temperature 143 | device_class: temperature 144 | unit_of_measurement: "°C" 145 | - platform: tuya 146 | sensor_datapoint: 3 147 | name: Humidity 148 | device_class: humidity 149 | unit_of_measurement: "%" 150 | - platform: tuya 151 | sensor_datapoint: 4 152 | id: co2 153 | name: Carbon Dioxide (CO2) 154 | device_class: carbon_dioxide 155 | unit_of_measurement: ppm 156 | - platform: tuya 157 | sensor_datapoint: 5 158 | id: hcho 159 | name: Formaldehyde (HCHO) 160 | unit_of_measurement: mg/m³ 161 | icon: mdi:flask 162 | accuracy_decimals: 3 163 | filters: 164 | - multiply: 0.001 165 | - platform: tuya 166 | sensor_datapoint: 7 167 | id: pm25 168 | name: Particulate Matter 2.5µm (PM2.5) 169 | device_class: pm25 170 | unit_of_measurement: µg/m³ 171 | - platform: tuya 172 | sensor_datapoint: 8 173 | id: pm1 174 | name: Particulate Matter 1.0µm (PM1.0) 175 | device_class: pm1 176 | unit_of_measurement: µg/m³ 177 | - platform: tuya 178 | sensor_datapoint: 9 179 | id: pm10 180 | name: Particulate Matter 10µm (PM10) 181 | device_class: pm10 182 | unit_of_measurement: µg/m³ 183 | - platform: tuya 184 | sensor_datapoint: 22 185 | name: Battery Remaining 186 | device_class: battery 187 | entity_category: diagnostic 188 | unit_of_measurement: "%" 189 | - platform: tuya 190 | sensor_datapoint: 101 191 | id: tvoc 192 | name: Volatile Organic Compounds (TVOC) 193 | device_class: volatile_organic_compounds 194 | unit_of_measurement: mg/m³ 195 | icon: mdi:chemical-weapon 196 | accuracy_decimals: 3 197 | filters: 198 | - multiply: 0.001 199 | - platform: tuya 200 | sensor_datapoint: 102 201 | name: Carbon Monoxide (CO) 202 | device_class: carbon_monoxide 203 | unit_of_measurement: ppm 204 | - platform: tuya 205 | sensor_datapoint: 107 206 | id: pm03 207 | name: Particulate Matter 0.3µm (PM0.3) 208 | device_class: pm1 # workaround as there is no pm03 class 209 | unit_of_measurement: µg/m³ 210 | 211 | binary_sensor: 212 | - platform: tuya 213 | sensor_datapoint: 23 214 | name: Battery Charging 215 | device_class: battery_charging 216 | entity_category: diagnostic 217 | 218 | select: 219 | # - platform: tuya 220 | # enum_datapoint: 28 221 | # name: Alarm Volume 222 | # entity_category: config 223 | # icon: mdi:volume-high 224 | # optimistic: true 225 | # options: 226 | # 1: Middle 227 | # - platform: tuya 228 | # enum_datapoint: 103 229 | # name: Backlight Level 230 | # entity_category: config 231 | # icon: mdi:television-ambient-light 232 | # optimistic: true 233 | # options: 234 | # 100: "Level 100" 235 | - platform: tuya 236 | enum_datapoint: 112 237 | name: Temperature Unit 238 | entity_category: config 239 | icon: mdi:thermometer-lines 240 | optimistic: true 241 | options: 242 | 0: °C 243 | 1: °F 244 | 245 | number: 246 | - platform: tuya 247 | number_datapoint: 104 248 | name: Alarm Carbon Dioxide (CO2) 249 | device_class: carbon_dioxide 250 | unit_of_measurement: ppm 251 | entity_category: config 252 | mode: box 253 | min_value: 500 254 | max_value: 3000 255 | step: 100 256 | - platform: tuya 257 | number_datapoint: 105 258 | name: Screensaver 259 | unit_of_measurement: min 260 | entity_category: config 261 | icon: mdi:monitor-off 262 | mode: box 263 | min_value: 0 264 | max_value: 100 265 | step: 1 266 | - platform: tuya 267 | number_datapoint: 109 268 | id: alarm1 269 | min_value: 0 270 | max_value: 1440 271 | step: 1 272 | on_value: 273 | then: 274 | - lambda: |- 275 | char buf[5 + 1]; 276 | sprintf(buf, "%02d:%02d", (int) x / 60, (int) x % 60); 277 | id(alarm1_text).publish_state(std::string(buf)); 278 | - platform: tuya 279 | number_datapoint: 110 280 | id: alarm2 281 | min_value: 0 282 | max_value: 1440 283 | step: 1 284 | on_value: 285 | then: 286 | - lambda: |- 287 | char buf[5 + 1]; 288 | sprintf(buf, "%02d:%02d", (int) x / 60, (int) x % 60); 289 | id(alarm2_text).publish_state(std::string(buf)); 290 | - platform: tuya 291 | number_datapoint: 111 292 | id: alarm3 293 | min_value: 0 294 | max_value: 1440 295 | step: 1 296 | on_value: 297 | then: 298 | - lambda: |- 299 | char buf[5 + 1]; 300 | sprintf(buf, "%02d:%02d", (int) x / 60, (int) x % 60); 301 | id(alarm3_text).publish_state(std::string(buf)); 302 | - platform: tuya 303 | number_datapoint: 113 304 | name: Alarm Carbon Monoxide (CO) 305 | device_class: carbon_monoxide 306 | unit_of_measurement: ppm 307 | entity_category: config 308 | mode: box 309 | min_value: 10 310 | max_value: 500 311 | step: 10 312 | - platform: tuya 313 | number_datapoint: 114 314 | name: Alarm Particulate Matter 2.5µm (PM2.5) 315 | device_class: pm25 316 | unit_of_measurement: µg/m³ 317 | entity_category: config 318 | mode: box 319 | min_value: 50 320 | max_value: 300 321 | step: 10 322 | - platform: tuya 323 | number_datapoint: 115 324 | name: Alarm Formaldehyde (HCHO) 325 | unit_of_measurement: mg/m³ 326 | icon: mdi:flask 327 | entity_category: config 328 | mode: box 329 | min_value: 8 330 | max_value: 199 331 | step: 1 332 | multiply: 1000 333 | 334 | switch: 335 | - platform: tuya 336 | switch_datapoint: 106 337 | name: Acoustic Alarms 338 | icon: mdi:volume-high 339 | - platform: tuya 340 | switch_datapoint: 116 341 | name: Alarm 1 Enable 342 | icon: mdi:alarm-multiple 343 | - platform: tuya 344 | switch_datapoint: 117 345 | name: Alarm 2 Enable 346 | icon: mdi:alarm-multiple 347 | - platform: tuya 348 | switch_datapoint: 118 349 | name: Alarm 3 Enable 350 | icon: mdi:alarm-multiple 351 | 352 | --------------------------------------------------------------------------------