eigger
(eigger)
February 7, 2025, 1:59am
1
ESPHome UART External Component
An external component for ESPHome that allows easy parsing of UART data, enabling users to extract relevant information and efficiently build custom components.
Usage Example
Below is an example YAML configuration:
uart:
baud_rate: 9600
data_bits: 8
parity: NONE
stop_bits: 1
rx_pin: GPIO22
tx_pin: GPIO19
external_components:
- source: github://eigger/espcomponents/releases/latest
components: [ uartex ]
refresh: always
uartex:
rx_timeout: 10ms
tx_delay: 50ms
tx_timeout: 500ms
tx_retry_cnt: 3
rx_header: [0x02, 0x01]
rx_footer: [0x0D, 0x0A]
tx_header: [0x02, 0x01]
tx_footer: [0x0D, 0x0A]
rx_checksum: add
tx_checksum: add
version:
disabled: False
error:
disabled: False
log:
disabled: False
#packet on) 0x02 0x01 0x02 0x03 0x01 (add)checksum 0x0D 0x0A
# offset) head head 0 1 2
#packet off) 0x02 0x01 0x02 0x03 0x00 (add)checksum 0x0D 0x0A
binary_sensor:
- platform: uartex
name: Binary_Sensor1
state: [0x02, 0x03]
state_on:
offset: 2
data: [0x01]
state_off:
offset: 2
data: [0x00]
#packet on) 0x02 0x01 0x02 0x03 0x01 (add)checksum 0x0D 0x0A
# offset) head head 0 1 2
#packet on ack) 0x02 0x01 0x02 0x13 0x01 (add)checksum 0x0D 0x0A
#packet off) 0x02 0x01 0x02 0x03 0x00 (add)checksum 0x0D 0x0A
#packet off ack) 0x02 0x01 0x02 0x03 0x00 (add)checksum 0x0D 0x0A
switch:
- platform: uartex
name: "Switch1"
state:
data: [0x02, 0x03]
mask: [0xff, 0x0f]
state_on:
offset: 2
data: [0x01]
state_off:
offset: 2
data: [0x00]
command_on:
data: [0x02, 0x03, 0x01]
ack: [0x02, 0x13, 0x01]
command_off: !lambda |-
return {{0x02, 0x03, 0x00}, {0x02, 0x13, 0x00}};
Detailed Example
For more detailed examples,
3 Likes
s1godfrey
(S1godfrey)
February 22, 2025, 5:28pm
2
Can this be used to replace a ‘Custom’ component based UART Text Sensor:
- platform: custom
lambda: |-
auto my_custom_sensor = new UartReadLineSensor(id(uart_bus));
App.register_component(my_custom_sensor);
return {my_custom_sensor};
text_sensors:
id: uart_readline
name: "Detected"
on_value:
- lambda: if (x == "name1") id(timer1).execute(); if (x == "name2") id(timer2).execute();
If so, could you please help me to understand how to convert my now depreciated UartReadLineSensor into your Custom Sensor?
I’m sorry but someone helped me set this up years ago and until the latest ESPHome update I have never had to make any changes to this setup.
I’m sort of assuming all I need to use from the detailed examples link is:
text_sensor:
- platform: uartex
name: "Text Sensor"
state: [0x02, 0x03]
But, would the value (x) still be applicable in this:
on_value:
- lambda: if (x == "name1") id(timer1).execute(); if (x == "name2") id(timer2).execute();
eigger
(eigger)
February 23, 2025, 12:08pm
3
You can try like this.
text_sensor:
- platform: uartex
name: "Text Sensor"
state: "name"
lambda: |-
if (data[4] == '1') id(timer1).execute();
if (data[4] == '2') id(timer2).execute();
return "OK";
or
text_sensor:
- platform: uartex
name: "Text Sensor"
state: "name1"
lambda: |-
id(timer1).execute();
return "name1 OK";
- platform: uartex
name: "Text Sensor"
state: "name2"
lambda: |-
id(timer2).execute();
return "name2 OK";
Any examples with a number: or sensor: component? I really could have used this on my pellet stove project. I had to do it the hard way…
eigger
(eigger)
February 24, 2025, 5:31am
5
If you specify the exact packet you want, I can provide more examples. Below, I’ve created an example based on my estimation. Let me know if there are any additional packets you’d like to include.
uartex:
rx_timeout: 10ms
tx_delay: 50ms
tx_timeout: 500ms
tx_retry_cnt: 3
rx_header: [0xAA]
rx_footer: [0xCC, 0x33]
tx_header: [0xAA]
tx_footer: [0xCC, 0x33]
version:
disabled: False
error:
disabled: False
log:
disabled: False
#0xAA 0x01 0x48 0x80 0xCC 0x33
sensor:
- platform: uartex
name: ECO Value
state: [0x01, 0x48]
state_number:
offset: 2
length: 1
precision: 0
Fascinating. Nice work. When I get around to updating my code on these pellet stoves I’ll be sure to test this out! Having this before would have literally saved me days of head banging. Obviously I got there in the end but it’s not pretty.
eigger
(eigger)
February 24, 2025, 5:56am
7
Yeah, ESPHome is great, but parsing UART isn’t easy without external components. Let me know if you run into any issues during testing.
1 Like
Hey, nice looking components.
I have this config, but I doesn’t work.
Have you any hints.
# RS-232 Übertragungsprotokoll
# Verbindungskabel
# Der Computer wird über das RS-232-Verbindungskabel mit dem ZEWA Wasserstop
# verbunden.
# Schnittstellenparameter
# Bits pro Sekunde: 9600
# Datenbits: 8
# Parität: keine
# Stoppbits: 1
# Verbindungsaufbau
# - ZEWA wartet auf Kennung von Computer
# - Computer sendet Kennungsbyte AAh
# - Computer sendet Aktionsbyte "01h" (Abruf Betriebsdaten)
# Reaktion von ZEWA
# Der ZEWA antwortet auf das Aktionsbyte bzw. führt Befehl aus:
# Aktionsbyte "01h" (Abruf Betriebsdaten)
# Nachdem das Aktionsbyte 01h an den ZEWA gesendet wurde, sendet der ZEWA
# folgende Bytes an den Computer zurück:
# 1. Byte Kennung EEh
# 2. Byte Anzahl der Datenbytes inkl. Checksummenbyte
# 3. Byte Statusbyte 0
# Bit0 Kugelventil 0 – offen 1 – geschlossen
# Bit1 Wassermenge 0 – keine Überschreitung 1 – Überschreitung
# Bit2 Durchfluss 0 – keine Überschreitung 1 – Überschreitung
# Bit3 Entnahmedauer 0 – keine Überschreitung 1 – Überschreitung
# Bit4 Urlaubsmodus 0 – nicht aktiv 1 – aktiv
# Bit5 Standby-Modus 0 – nicht aktiv 1 – aktiv
# Bit6 Störung 0 – keine Störung 1 – Störung
# Bit7 KV-Motor 0 – ausgeschaltet 1 – eingeschaltet
# Seite 3 von 5 1701936 · 2014/084. Byte Statusbyte 1
# Bit0 Spannungsvers. 0 – Netzversorgung 1 – Batterieversorgung
# Bit1 Batteriezustand 0 – Batterie i. O. 1 – Batterie leer
# Bit2 Datenverbindung 0 – Datenverbindung i. O. 1 – keine Datenverbindung
# Bit3 Leckagesensor 0 – keine Abschaltung 1 – Abschaltung
# Bit4 ext. I/O 0 – kein Eingangssignal 1 – Eingangssignal
# Bit5 Rel 1 ext. auf /zu 0 – KV geöffnet 1 – KV geschlossen
# Bit6 Rel 2 Störung 0 – Störung, keine Span. 1 – Betrieb
# Bit7 Rel 3 100 L Imp. 0 – kein Impuls 1 – Impuls nach 100 l
# 5. Byte Batteriespannung (in Volt) = Byte5 * 0.07906
# 6. Byte Ausgangspannung des Notstrommoduls (in Volt)= Byte6 * 0.1556
# 7. Byte gespeicherte Abschaltungen Wassermenge Einstellung1
# 8. Byte gespeicherte Abschaltungen Wassermenge Einstellung2
# 9. Byte gespeicherte Abschaltungen Wassermenge Einstellung3
# 10. Byte gespeicherte Abschaltungen Wassermenge Einstellung4
# 11. Byte gespeicherte Abschaltungen Wassermenge Einstellung5
# 12. Byte gespeicherte Abschaltungen Wassermenge Einstellung6
# 13. Byte gespeicherte Abschaltungen Durchfluss Einstellung1
# 14. Byte gespeicherte Abschaltungen Durchfluss Einstellung2
# 15. Byte gespeicherte Abschaltungen Durchfluss Einstellung3
# 16. Byte gespeicherte Abschaltungen Durchfluss Einstellung4
# 17. Byte gespeicherte Abschaltungen Durchfluss Einstellung5
# 18. Byte gespeicherte Abschaltungen Durchfluss Einstellung6
# 19. Byte gespeicherte Abschaltungen Entnahmezeit Einstellung1
# 20. Byte gespeicherte Abschaltungen Entnahmezeit Einstellung2
# 21. Byte gespeicherte Abschaltungen Entnahmezeit Einstellung3
# 22. Byte gespeicherte Abschaltungen Entnahmezeit Einstellung4
# 23. Byte gespeicherte Abschaltungen Entnahmezeit Einstellung5
# 24. Byte gespeicherte Abschaltungen Entnahmezeit Einstellung6
# 25 Byte Anzahl Abschaltungen im Urlaubsmodus
# 26. Byte Anzahl der Abschaltungen durch Leckagesensor
# 27. Byte Anzahl Störmeldungen Fehler2 (Motor oder Nockenschalter defekt)
# 28. Byte Anzahl Störmeldungen Fehler3 (Verbindungsfehler Notstrom-ZEWA)
# 29. u. 30. Byte aktuelle Einstellung Grenzwert max. Wassermenge [l]
# 31. u. 32. Byte aktuelle Einstellung Grenzwert max. Durchfluss [l/h]
# 33. u. 34. Byte aktuelle Einstellung Grenzwert max. Entnahmezeit [0,5 s]
# 35. u. 36. Byte aktueller Messwert Wassermenge
# 37. u. 38. Byte aktueller Messwert Durchfluss
# 39. u. 40. Byte aktueller Messwert Entnahmezeit
# 41., 42., 43. u. 44. Byte Gesamtwassermenge:
# = (Byte41 + Byte42 * 256 + Byte43 * 2562 + Byte44 * 2563) * 100 Liter
# 45. bis 47. Byte interne Verwendung
# 48. Byte Checksumme
# Aktionsbyte "02h" (Befehl Öffnen / Schließen)
# Nachdem das Aktionsbyte 02h vom Computer an den ZEWA gesendet wurde, antwortet
# der ZEWA mit:
# 1. Byte Kennung EEh
# 2. Byte Quittierung 99h
# Anschließend führt der ZEWA den Befehl zum Öffnen / Schließen aus.
# Berechnung der Checksumme:
# Summe von Byte2 bis Byte47. Das niederwertige Byte der Summe ist die Check
esphome:
name: esp32-wasserstopgateway
friendly_name: ESP32-WasserStopGateway
esp32:
board: esp32dev
framework:
type: arduino
logger:
level: VERBOSE
baud_rate: 0
logs:
display: NONE
api:
encryption:
key:="
ota:
- platform: esphome
password: ""
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
static_ip: 192.168.178.111
gateway: 192.168.178.1
subnet: 255.255.255.0
ap:
ssid: "Wasserstopgateway"
password: "hEArICVbDKss"
captive_portal:
web_server:
port: 80
uart:
id: uart_bus
tx_pin: GPIO17 # Adjust as needed!
rx_pin: GPIO16
baud_rate: 9600
data_bits: 8
parity: NONE
stop_bits: 1
external_components:
- source: github://eigger/espcomponents/releases/latest
components: [ uartex ]
refresh: always
uartex:
id: zewa_uartex
uart_id: uart_bus
rx_timeout: 10ms
tx_delay: 50ms
tx_timeout: 500ms
tx_retry_cnt: 3
rx_header: [0xEE]
rx_footer: []
tx_header: [0xAA]
tx_footer: []
rx_checksum: add
tx_checksum: add
#################################################################
# Binary Sensors – Statusbits from Statusbyte 0 (Byte 2, i.e. data[1])
#################################################################
binary_sensor:
- platform: uartex
name: "Kugelventil"
state:
data: [0x02] # Read Statusbyte 0
mask: [0x01] # Bit0: 0 = Offen, 1 = Geschlossen
state_on:
offset: 0
data: [0x01]
state_off:
offset: 0
data: [0x00]
- platform: uartex
name: "Wassermenge Überschreitung"
state:
data: [0x02]
mask: [0x02] # Bit1: 1 = Überschreitung
state_on:
offset: 0
data: [0x02]
state_off:
offset: 0
data: [0x00]
- platform: uartex
name: "Durchfluss Überschreitung"
state:
data: [0x02]
mask: [0x04] # Bit2: 1 = Überschreitung
state_on:
offset: 0
data: [0x04]
state_off:
offset: 0
data: [0x00]
- platform: uartex
name: "Entnahmedauer Überschreitung"
state:
data: [0x02]
mask: [0x08] # Bit3: 1 = Überschreitung
state_on:
offset: 0
data: [0x08]
state_off:
offset: 0
data: [0x00]
- platform: uartex
name: "Urlaubsmodus aktiv"
state:
data: [0x02]
mask: [0x10] # Bit4: 1 = Aktiv
state_on:
offset: 0
data: [0x10]
state_off:
offset: 0
data: [0x00]
- platform: uartex
name: "Standby aktiv"
state:
data: [0x02]
mask: [0x20] # Bit5: 1 = Aktiv
state_on:
offset: 0
data: [0x20]
state_off:
offset: 0
data: [0x00]
- platform: uartex
name: "Störung"
state:
data: [0x02]
mask: [0x40] # Bit6: 1 = Störung
state_on:
offset: 0
data: [0x40]
state_off:
offset: 0
data: [0x00]
- platform: uartex
name: "KV-Motor"
state:
data: [0x02]
mask: [0x80] # Bit7: 1 = Ein, 0 = Aus
state_on:
offset: 0
data: [0x80]
state_off:
offset: 0
data: [0x00]
#################################################################
# Binary Sensors – Statusbits from Statusbyte 1 (Byte 3, i.e. data[2])
#################################################################
- platform: uartex
name: "Spannungsversorgung Batteriebetrieb"
state:
data: [0x03] # Read Statusbyte 1
mask: [0x01] # Bit0: 1 = Batterieversorgung, 0 = Netz
state_on:
offset: 0
data: [0x01]
state_off:
offset: 0
data: [0x00]
- platform: uartex
name: "Batteriezustand leer"
state:
data: [0x03]
mask: [0x02] # Bit1: 1 = Leer, 0 = OK
state_on:
offset: 0
data: [0x02]
state_off:
offset: 0
data: [0x00]
- platform: uartex
name: "Datenverbindung Fehler"
state:
data: [0x03]
mask: [0x04] # Bit2: 1 = Fehler, 0 = OK
state_on:
offset: 0
data: [0x04]
state_off:
offset: 0
data: [0x00]
- platform: uartex
name: "Leckagesensor Abschaltung"
state:
data: [0x03]
mask: [0x08] # Bit3: 1 = Abschaltung, 0 = OK
state_on:
offset: 0
data: [0x08]
state_off:
offset: 0
data: [0x00]
- platform: uartex
name: "Externer I/O Signal"
state:
data: [0x03]
mask: [0x10] # Bit4: 1 = Signal, 0 = Kein Signal
state_on:
offset: 0
data: [0x10]
state_off:
offset: 0
data: [0x00]
- platform: uartex
name: "Relais 1 geschlossen"
state:
data: [0x03]
mask: [0x20] # Bit5: 1 = Geschlossen
state_on:
offset: 0
data: [0x20]
state_off:
offset: 0
data: [0x00]
- platform: uartex
name: "Relais 2 Betrieb"
state:
data: [0x03]
mask: [0x40] # Bit6: 1 = Betrieb, 0 = Störung
state_on:
offset: 0
data: [0x40]
state_off:
offset: 0
data: [0x00]
- platform: uartex
name: "Relais 3 Impuls"
state:
data: [0x03]
mask: [0x80] # Bit7: 1 = Impuls, 0 = Kein Impuls
state_on:
offset: 0
data: [0x80]
state_off:
offset: 0
data: [0x00]
#################################################################
# Numeric Sensors – Measurements and Counters
#################################################################
sensor:
# Batteriespannung (Byte 5 * 0,07906 V)
- platform: uartex
name: "Batteriespannung (Messwert)"
unit_of_measurement: "V"
state:
data: [0x05]
lambda: |-
return data[4] * 0.07906;
# Notstrom-Spannung (Byte 6 * 0,1556 V)
- platform: uartex
name: "Notstrom-Spannung (Messwert)"
unit_of_measurement: "V"
state:
data: [0x06]
lambda: |-
return data[5] * 0.1556;
# Urlaubsmodus Abschaltungen (Byte 28 -> data[27])
- platform: uartex
name: "Urlaubsmodus Abschaltungen"
unit_of_measurement: "count"
state:
data: [0x1C]
state_number:
offset: 27
length: 1
precision: 0
# Fehlermeldungen Fehler2 (Byte 29 -> data[28])
- platform: uartex
name: "Fehlermeldungen Fehler2"
unit_of_measurement: "count"
state:
data: [0x1D]
state_number:
offset: 28
length: 1
precision: 0
# Fehlermeldungen Fehler3 (Byte 30 -> data[29])
- platform: uartex
name: "Fehlermeldungen Fehler3"
unit_of_measurement: "count"
state:
data: [0x1E]
state_number:
offset: 29
length: 1
precision: 0
# Grenzwert max. Wassermenge (Bytes 31-32 -> data[30] and data[31])
- platform: uartex
name: "Grenzwert max. Wassermenge"
unit_of_measurement: "L"
state:
data: [0x1F, 0x20]
state_number:
offset: 30
length: 2
precision: 0
# Grenzwert max. Durchfluss (Bytes 33-34 -> data[32] and data[33])
- platform: uartex
name: "Grenzwert max. Durchfluss"
unit_of_measurement: "L/h"
state:
data: [0x21, 0x22]
state_number:
offset: 32
length: 2
precision: 0
# Grenzwert max. Entnahmezeit (Bytes 35-36 -> data[34] and data[35]), umgerechnet: * 0,5 s
- platform: uartex
name: "Grenzwert max. Entnahmezeit"
unit_of_measurement: "s"
state:
data: [0x23, 0x24]
lambda: |-
return ( (data[34] + (data[35] << 8)) * 0.5 );
# Aktuelle Wassermenge (Bytes 37-38 -> data[36] and data[37])
- platform: uartex
name: "Aktuelle Wassermenge"
unit_of_measurement: "L"
state:
data: [0x25, 0x26]
state_number:
offset: 36
length: 2
precision: 0
# Aktueller Durchfluss (Bytes 39-40 -> data[38] and data[39])
- platform: uartex
name: "Aktueller Durchfluss"
unit_of_measurement: "L/h"
state:
data: [0x27, 0x28]
state_number:
offset: 38
length: 2
precision: 0
# Aktuelle Entnahmezeit (Bytes 41-42 -> data[40] and data[41]), umgerechnet: * 0,5 s
- platform: uartex
name: "Aktuelle Entnahmezeit"
unit_of_measurement: "s"
state:
data: [0x29, 0x2A]
lambda: |-
return ( (data[40] + (data[41] << 8)) * 0.5 );
# Gesamtwassermenge (Bytes 43-46 -> data[42] to data[45]), umgerechnet in Liter (Multipliziert mit 100)
- platform: uartex
name: "Gesamtwassermenge"
unit_of_measurement: "L"
state:
data: [0x2B, 0x2C, 0x2D, 0x2E]
lambda: |-
return (data[42] + (data[43] << 8) + (data[44] << 16) + (data[45] << 24)) * 100;
# Totaler Wasserverbrauch (in m³) unter Berücksichtigung eines Offsets (Bytes 43-46 -> data[42] to data[45])
- platform: uartex
name: "Totaler Wasserverbrauch"
unit_of_measurement: "m³"
state:
data: [0x2B, 0x2C, 0x2D, 0x2E]
lambda: |-
float measured_total = (data[42] + (data[43] << 8) + (data[44] << 16) + (data[45] << 24)) / 1000.0;
return measured_total + id(total_water_consumption_offset).state;
# Globaler Offset für den Totalen Wasserverbrauch
- platform: template
name: "Totaler Wasserverbrauch Offset"
id: total_water_consumption_offset
unit_of_measurement: "m³"
accuracy_decimals: 2
lambda: |-
return 0.0;
interval:
- interval: 1s
then:
- uart.write: [0xAA, 0x01]
time:
- platform: sntp
id: sntp_time
timezone: Europe/Berlin
servers:
- 0.pool.ntp.org
- 1.pool.ntp.org
- 2.pool.ntp.org
font:
- file: "gfonts://Roboto"
id: font_small
size: 10
i2c:
scan: true
id: bus_a
eigger
(eigger)
February 26, 2025, 11:39am
9
If you provide me with the full packet information, I will create an example for you.
Thank you:
The big comment block describes the rs-232.
Here is the official documentation:
Judo Zewa RS-232
Is this enough?
eigger
(eigger)
February 26, 2025, 11:56am
11
Okay, I will check the document.
1 Like
eigger
(eigger)
February 26, 2025, 12:56pm
12
I have attached a few examples. Would you like to test them?
uartex:
rx_timeout: 10ms
tx_delay: 50ms
tx_timeout: 500ms
tx_retry_cnt: 3
rx_header: [0xEE]
tx_header: [0xAA]
# The add checksum option includes the header.
# So I redefined it using a lambda.
rx_checksum: !lambda |-
uint8_t crc = 0;
for (int i = 0; i < len; i++)
{
crc += data[i];
}
return crc;
#################################################################
# Binary Sensors – Statusbits from Statusbyte 0 (Byte 2, i.e. data[1])
#################################################################
#Offset starts from 0, excluding the header.
#packet 0xEE 0x00 0x00 0x00 0x00 ...
#offset 0 1 2 3
binary_sensor:
- platform: uartex
name: "Kugelventil"
state:
data: [0x00] # Read All
mask: [0x00]
state_on:
offset: 1
data: [0x01]
mask: [0x01] # Bit0: 0 = Offen, 1 = Geschlossen
state_off:
offset: 1
data: [0x00]
mask: [0x01] # Bit0: 0 = Offen, 1 = Geschlossen
update_interval: 1s
# The header is automatically included."
# Does the sent data not include a checksum or an end character?
# 0xAA 0x01
command_update:
data: [0x01]
- platform: uartex
name: "Wassermenge Überschreitung"
state:
data: [0x00] # Read All
mask: [0x00]
state_on:
offset: 1
data: [0x02]
mask: [0x02] # Bit1: 1 = Überschreitung
state_off:
offset: 1
data: [0x00]
mask: [0x02] # Bit1: 1 = Überschreitung
#################################################################
# Binary Sensors – Statusbits from Statusbyte 1 (Byte 3, i.e. data[2])
#################################################################
- platform: uartex
name: "Spannungsversorgung Batteriebetrieb"
state:
data: [0x00] # Read All
mask: [0x00]
state_on:
offset: 2
data: [0x01]
mask: [0x01] # Bit0: 1 = Batterieversorgung, 0 = Netz
state_off:
offset: 2
data: [0x00]
mask: [0x01] # Bit0: 1 = Batterieversorgung, 0 = Netz
#################################################################
# Numeric Sensors – Measurements and Counters
#################################################################
sensor:
# Batteriespannung (Byte 5 * 0,07906 V)
- platform: uartex
name: "Batteriespannung (Messwert)"
unit_of_measurement: "V"
state:
data: [0x00] # Read All
mask: [0x00]
lambda: |-
return data[3] * 0.07906;
# Urlaubsmodus Abschaltungen
- platform: uartex
name: "Urlaubsmodus Abschaltungen"
unit_of_measurement: "count"
state:
data: [0x00] # Read All
mask: [0x00]
state_number:
offset: 24
length: 1
precision: 0
Thank you. I will test it.
i have tested it with the Batteriespannung sensor: HA says unknown e.g. no value. The log from esp32 says
[21:02:27][W][uartex:318]: [Read] Size error: EE(1)
a workin esp8266 sketch as standalone app
My Board: ESP32-Wroom-32, i will try a esp8266 tomorrow
My yaml:
# RS-232 Übertragungsprotokoll
# Verbindungskabel
# Der Computer wird über das RS-232-Verbindungskabel mit dem ZEWA Wasserstop
# verbunden.
# Schnittstellenparameter
# Bits pro Sekunde: 9600
# Datenbits: 8
# Parität: keine
# Stoppbits: 1
# Verbindungsaufbau
# - ZEWA wartet auf Kennung von Computer
# - Computer sendet Kennungsbyte AAh
# - Computer sendet Aktionsbyte "01h" (Abruf Betriebsdaten)
# Reaktion von ZEWA
# Der ZEWA antwortet auf das Aktionsbyte bzw. führt Befehl aus:
# Aktionsbyte "01h" (Abruf Betriebsdaten)
# Nachdem das Aktionsbyte 01h an den ZEWA gesendet wurde, sendet der ZEWA
# folgende Bytes an den Computer zurück:
# 1. Byte Kennung EEh
# 2. Byte Anzahl der Datenbytes inkl. Checksummenbyte
# 3. Byte Statusbyte 0
# Bit0 Kugelventil 0 – offen 1 – geschlossen
# Bit1 Wassermenge 0 – keine Überschreitung 1 – Überschreitung
# Bit2 Durchfluss 0 – keine Überschreitung 1 – Überschreitung
# Bit3 Entnahmedauer 0 – keine Überschreitung 1 – Überschreitung
# Bit4 Urlaubsmodus 0 – nicht aktiv 1 – aktiv
# Bit5 Standby-Modus 0 – nicht aktiv 1 – aktiv
# Bit6 Störung 0 – keine Störung 1 – Störung
# Bit7 KV-Motor 0 – ausgeschaltet 1 – eingeschaltet
# Seite 3 von 5 1701936 · 2014/084. Byte Statusbyte 1
# Bit0 Spannungsvers. 0 – Netzversorgung 1 – Batterieversorgung
# Bit1 Batteriezustand 0 – Batterie i. O. 1 – Batterie leer
# Bit2 Datenverbindung 0 – Datenverbindung i. O. 1 – keine Datenverbindung
# Bit3 Leckagesensor 0 – keine Abschaltung 1 – Abschaltung
# Bit4 ext. I/O 0 – kein Eingangssignal 1 – Eingangssignal
# Bit5 Rel 1 ext. auf /zu 0 – KV geöffnet 1 – KV geschlossen
# Bit6 Rel 2 Störung 0 – Störung, keine Span. 1 – Betrieb
# Bit7 Rel 3 100 L Imp. 0 – kein Impuls 1 – Impuls nach 100 l
# 5. Byte Batteriespannung (in Volt) = Byte5 * 0.07906
# 6. Byte Ausgangspannung des Notstrommoduls (in Volt)= Byte6 * 0.1556
# 7. Byte gespeicherte Abschaltungen Wassermenge Einstellung1
# 8. Byte gespeicherte Abschaltungen Wassermenge Einstellung2
# 9. Byte gespeicherte Abschaltungen Wassermenge Einstellung3
# 10. Byte gespeicherte Abschaltungen Wassermenge Einstellung4
# 11. Byte gespeicherte Abschaltungen Wassermenge Einstellung5
# 12. Byte gespeicherte Abschaltungen Wassermenge Einstellung6
# 13. Byte gespeicherte Abschaltungen Durchfluss Einstellung1
# 14. Byte gespeicherte Abschaltungen Durchfluss Einstellung2
# 15. Byte gespeicherte Abschaltungen Durchfluss Einstellung3
# 16. Byte gespeicherte Abschaltungen Durchfluss Einstellung4
# 17. Byte gespeicherte Abschaltungen Durchfluss Einstellung5
# 18. Byte gespeicherte Abschaltungen Durchfluss Einstellung6
# 19. Byte gespeicherte Abschaltungen Entnahmezeit Einstellung1
# 20. Byte gespeicherte Abschaltungen Entnahmezeit Einstellung2
# 21. Byte gespeicherte Abschaltungen Entnahmezeit Einstellung3
# 22. Byte gespeicherte Abschaltungen Entnahmezeit Einstellung4
# 23. Byte gespeicherte Abschaltungen Entnahmezeit Einstellung5
# 24. Byte gespeicherte Abschaltungen Entnahmezeit Einstellung6
# 25 Byte Anzahl Abschaltungen im Urlaubsmodus
# 26. Byte Anzahl der Abschaltungen durch Leckagesensor
# 27. Byte Anzahl Störmeldungen Fehler2 (Motor oder Nockenschalter defekt)
# 28. Byte Anzahl Störmeldungen Fehler3 (Verbindungsfehler Notstrom-ZEWA)
# 29. u. 30. Byte aktuelle Einstellung Grenzwert max. Wassermenge [l]
# 31. u. 32. Byte aktuelle Einstellung Grenzwert max. Durchfluss [l/h]
# 33. u. 34. Byte aktuelle Einstellung Grenzwert max. Entnahmezeit [0,5 s]
# 35. u. 36. Byte aktueller Messwert Wassermenge
# 37. u. 38. Byte aktueller Messwert Durchfluss
# 39. u. 40. Byte aktueller Messwert Entnahmezeit
# 41., 42., 43. u. 44. Byte Gesamtwassermenge:
# = (Byte41 + Byte42 * 256 + Byte43 * 2562 + Byte44 * 2563) * 100 Liter
# 45. bis 47. Byte interne Verwendung
# 48. Byte Checksumme
# Aktionsbyte "02h" (Befehl Öffnen / Schließen)
# Nachdem das Aktionsbyte 02h vom Computer an den ZEWA gesendet wurde, antwortet
# der ZEWA mit:
# 1. Byte Kennung EEh
# 2. Byte Quittierung 99h
# Anschließend führt der ZEWA den Befehl zum Öffnen / Schließen aus.
# Berechnung der Checksumme:
# Summe von Byte2 bis Byte47. Das niederwertige Byte der Summe ist die Check
esphome:
name: esp32-wasserstopgateway
friendly_name: ESP32-WasserStopGateway
esp32:
board: esp32dev
framework:
type: arduino
logger:
level: DEBUG
baud_rate: 0
logs:
display: NONE
api:
encryption:
key: "="
ota:
- platform: esphome
password: ""
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
static_ip: 192.168.178.111
gateway: 192.168.178.1
subnet: 255.255.255.0
ap:
ssid: "Wasserstopgateway"
password: "hEArICVbDKss"
captive_portal:
web_server:
port: 80
uart:
id: uart_bus
tx_pin: GPIO17 # Adjust as needed!
rx_pin: GPIO16
baud_rate: 9600
data_bits: 8
parity: NONE
stop_bits: 1
external_components:
- source: github://eigger/espcomponents/releases/latest
components: [ uartex ]
refresh: always
uartex:
rx_timeout: 30ms
tx_delay: 50ms
tx_timeout: 500ms
tx_retry_cnt: 3
rx_header: [0xEE]
tx_header: [0xAA]
# The add checksum option includes the header.
# So I redefined it using a lambda.
rx_checksum: !lambda |-
uint8_t crc = 0;
for (int i = 0; i < len; i++)
{
crc += data[i];
}
return crc;
#################################################################
# Numeric Sensors – Measurements and Counters
#################################################################
sensor:
# Batteriespannung (Byte 5 * 0,07906 V)
- platform: uartex
name: "Batteriespannung (Messwert)"
unit_of_measurement: "V"
state:
data: [0x00] # Read All
mask: [0x00]
lambda: |-
return data[3] * 0.07906;
interval:
- interval: 1s
then:
- uart.write: [0xAA, 0x01]
time:
- platform: sntp
id: sntp_time
timezone: Europe/Berlin
servers:
- 0.pool.ntp.org
- 1.pool.ntp.org
- 2.pool.ntp.org
font:
- file: "gfonts://Roboto"
id: font_small
size: 10
i2c:
scan: true
id: bus_a
eigger
(eigger)
February 26, 2025, 10:19pm
15
Could you check the UART logs by adding the debug option?
I want to check whether the data is not being received or not being parsed.
uart:
id: uart_bus
tx_pin: GPIO17 # Adjust as needed!
rx_pin: GPIO16
baud_rate: 9600
data_bits: 8
parity: NONE
stop_bits: 1
debug:
or edit logger
logger:
level: DEBUG
#baud_rate: 0
#logs:
# display: NONE
Here is a Log Snippet, i revice the Data.
[08:47:51][D][uart_debug:114]: >>> AA:01
[08:47:51][W][uartex:318]: [Read] Size error: EE(1)
[08:47:51][W][component:237]: Component uartex took a long time for an operation (60 ms).
[08:47:51][W][component:238]: Components should block for at most 30 ms.
[08:47:51][D][uart_debug:114]: <<< EE:2E:00:40:DE:DE:00:0A:00:00:00:00:00:00:03:00:00:00:00:00:00:04:00:00:02:00:00:00:E8:03:D0:07:10:0E:00:00:00:00:00:00:E4:13:00:00:00:00:00:14
eigger
(eigger)
February 27, 2025, 9:02am
17
Try testing it without the checksum for now. I will review the checksum method
uartex:
rx_timeout: 50ms
tx_delay: 50ms
tx_timeout: 500ms
tx_retry_cnt: 3
rx_header: [0xEE]
tx_header: [0xAA]
# The add checksum option includes the header.
# So I redefined it using a lambda.
#rx_checksum: !lambda |-
# uint8_t crc = 0;
# for (int i = 0; i < len; i++)
# {
# crc += data[i];
# }
# return crc;
now i have the first Value it reported 18V, it is possible to change it to 18,00 V?
Now i will test one other Sensor:
EDIT:
It was a one time success. -.-
eigger
(eigger)
February 27, 2025, 10:31am
19
can you like to test it again? I don’t quite understand your situation.
size error doesn’t seem to be related to the checksum.
I tried modifying another part.
uartex:
rx_timeout: 100ms
tx_delay: 50ms
tx_timeout: 500ms
tx_retry_cnt: 3
rx_header: [0xEE]
rx_checksum: !lambda |-
uint8_t crc = 0;
for (int i = 0; i < len; i++)
{
crc += data[i];
}
return crc;
interval:
- interval: 1s
then:
- uartex.write: [0xAA, 0x01]
logger:
level: DEBUG
Sure. Now i get a Value.
I have tried
binary_sensor:
- platform: uartex
name: "Kugelventil"
state:
data: [0x00] # Read All
mask: [0x00]
state_on:
offset: 1
data: [0x01]
mask: [0x01] # Bit0: 0 = Offen, 1 = Geschlossen
state_off:
offset: 1
data: [0x00]
mask: [0x01] # Bit0: 0 = Offen, 1 = Geschlossen
this code. Here i have a value, too. But it says false (Aus) but i think it should be true, because i know i can use the Water in my House
I dont understand the data and mask thing and how i chose the right position in the data array in the lambda