{{ :supportukraine.gif|}}
====== Home Assistant: Water consumption monitoring with gPlugD-E and Ensor eRS801 via P1-DSMR interface in ESPHome ======
{{en:tux.png |Hey, my name is "Tux"!}} Hey, my name is "Tux" and this tutorial will show you how to set up water consumption monitoring in [[https://www.home-assistant.io/|Home Assistant]] with [[https://esphome.io/|ESPHome]], a [[https://gplug.ch/produkte/gplugd-e/|gPlugD-E]] adapter, connected to the //P1-DSMR// interface of an [[https://www.ensor.com/produkte|Ensor]] eRS801 smart meter.
----
\\
===== Preparation =====
First of all, if you want to catch any data of an //Ensor eRS801// its //P1-DSMR// customer interface, you have to make sure the customer interface is being unlocked. In my case, the electrician hired by the municipality from the village I live, which installed the //Ensor eRS801//, took care on this for me. I also asked him to set down the //Ensor eRS801// its internal request interval to the physical water meter (which is an [[https://ch.integra-metering.com/product/aquastream-m-bus-pulses/|Integra aquastream Type AQS-MB]] in my case) to an interval of 60 seconds instead of default 3600 seconds. This way I could monitor at least consumed liters per minute, which is sufficient for my needs.
He also had to tell me on which //M-Bus// channel the water metering communication is being transferred, which is channel #4 in my case. If the channel number differs in your case, please just adjust the number accordingly on the YAML code provided later in this tutorial.
In addition, in case you need it, because I was not able to find anything documented officially and therefore had to trial and error, here's on how to bring the //gPlugD-E// adapter into flashing mode:
Press and hold the ''R''-button (1), then press and hold the ''A''-button (2), then release the ''R''-button (1) and finally release the ''A''-button (2). Now you can flash your custom ''.bin'' firmware file via [[https://web.esphome.io/|web.esphome.io]] web interface. Be aware, that after successful flashing, you need to press the ''R''-button at least once again to reset the //gPlugD-E// adapter to make the uploaded program start running. It was somehow not sufficient in my case to press the virtual device reset button on the //web.esphome.io// web interface.
[{{:homeassistantgplugde01.png?400|gPlugD-E physical buttons}}]
\\
===== First thoughts & tutorial =====
While searching for a way to track my water usage in //Home Assistant// after the municipality had ruined my original, well-functioning solution with their new installation, I came across [[https://github.com/haribert/gplug-esphome|this]] alternative. Should be an easy task, right? Using the main YAML code from the linked tutorial, replacing the power monitoring code part with my own water monitoring part, flashing it via //ESPHome// to the //gPlugD-E// adapter and I will be ready to go... \\
But wait: The problem I stumbled across was that the //gPlugE// adapter from the linked tutorial is not available anymore and has being replaced with its successor, the //gPlugD-E// adapter. The underlying hardware is not the same anymore and internal microcontroller pin connections to the physical ethernet interface have changed. So I had to determine the new board its layout by myself.
I contacted the //gPlugD-E// support but they were not willing to help me out with this so I flashed back the [[http://ota.gplug.ch/Tasmota/gPlugDE/firmware.factory.bin|gPlugD-E its original Tasmota firmware]], opened its web console and tried to determine the according pin layout by executing the following command:
Template
Which gave me the following output:
''{"NAME":"IoT-Adapter","GPIO":[736,672,5536,704,0,0,0,0,5600,0,5568,0,0,0,0,0,0,0,0,0,0,0]}''
Seems like an array of GPIO mapping values, which I could use to compare against the [[https://tasmota.github.io/docs/GPIO-Conversion/|official Tasmota GPIO conversion table]], right?
Unfortunately not. I was not able to find those array values within the conversion table, so the logic behind it must be different. My bad, I guess.
So I asked [[https://claude.ai|claude.ai]] to help me and it told me to execute the following command on the //Tasmota// console:
gpio all
...and voilà:
''17:47:27.464 RSL: RESULT = {"GPIO0":{"SPI CLK1":736},"GPIO1":{"SPI MISO1":672},"GPIO2":{"ETH POWER":5536},"GPIO3":{"SPI MOSI1":704},"GPIO4":{"None":0},"GPIO5":{"None":0},"GPIO6":{"None":0},"GPIO7":{"None":0},"GPIO8":{"ETH MDIO":5600},"GPIO9":{"None":0},"GPIO10":{"ETH MDC":5568},"GPIO11":{"None":0},"GPIO12":{"None":0},"GPIO13":{"None":0},"GPIO18":{"None":0},"GPIO19":{"None":0},"GPIO20":{"None":0},"GPIO21":{"None":0}}''
All the required pin mappings are there. Now I got everything I needed to configure the ethernet port via YAML code accordingly, which worked perfectly. Yay!
Now the //ESPHome// YAML code to read out data via DSMR protocol standard was indeed simple and minimal.
But the next problem was right around the corner: Data was being transmitted successfully, but the default [[https://esphome.io/components/sensor/dsmr/|DSMR library]] from //ESPHome// was not able to parse the data output accordingly, it mostly had something to do with missing or false timestamp format, but I cannot tell for sure as I never analyzed the whole raw data stream.
No worries. In the end I had to prompt //Claude// again to help me out with this and it gave me the following perfectly working code solution:
# Ethernet:
ethernet:
type: W5500
clk_pin: GPIO0
mosi_pin: GPIO3
miso_pin: GPIO1
cs_pin: GPIO10
interrupt_pin: GPIO8
reset_pin: GPIO2
# Globals:
globals:
# Globals for water consumption calculation
- id: water_m3
type: float
restore_value: true
initial_value: '0.0'
- id: tbuf
type: std::string
initial_value: '""'
- id: tactive
type: bool
initial_value: 'false'
# Sensors:
sensor:
# Water consumption
- platform: template
id: water_sensor
name: "Water consumption"
unit_of_measurement: "m³"
accuracy_decimals: 3
device_class: water
state_class: total_increasing
icon: "mdi:water"
lambda: return id(water_m3);
update_interval: 5s
# UART:
uart:
id: uart_bus
rx_pin: GPIO4
baud_rate: 115200
rx_buffer_size: 2048
# Interval-driven data parsing
interval:
# Check for incoming data over serial every 100ms
- interval: 100ms
then:
- lambda: |-
while (id(uart_bus).available() > 0) {
uint8_t b;
id(uart_bus).read_byte(&b);
char c = (char) b;
if (c == '/') {
id(tbuf) = "";
id(tactive) = true;
}
if (!id(tactive)) continue;
id(tbuf) += c;
if (id(tbuf).size() > 2000) {
id(tbuf) = "";
id(tactive) = false;
continue;
}
if (c == '!') {
const std::string pfx = "0-4:24.2.1(";
size_t p = id(tbuf).find(pfx);
size_t s = id(tbuf).find('*', p);
if (p != std::string::npos && s != std::string::npos) {
p += pfx.size();
float v = atof(id(tbuf).substr(p, s - p).c_str());
if (v > 0.0f) id(water_m3) = v;
}
id(tbuf) = "";
id(tactive) = false;
}
}
Now I adapted the //gPlugD-E// adapter into //Home Assistant// and the ''Water consumption" sensor was available as expected:
[{{:homeassistantgplugde02.png?600|ESPHome "Water consumption" sensor}}]
I now was able to use this sensor for adding water consumption monitoring on the //Home Assistant Energy Dashboard//.
\\
===== End of tutorial =====
\\
\\
Appreciate my work? \\ [[https://www.buymeacoffee.com/fabioU|Buy me a coffee]] {{:buymeacoffee.png|}} or [[https://www.paypal.com/donate/?hosted_button_id=TH8Q3NTJCAJBA|PayPal]] {{:paypal.png|}}
\\
\\
**Source(s):**
\\
[[https://bitaranto.ch | Bitaranto.ch: IT-tutorials & technics]]
\\
{{htmlmetatags>metatag-robots=()}}