├── .gitignore
├── docs
├── Elster-IN-Z61.jpg
├── Gas-Verbrauch.png
├── Gasverbrauch-heute.png
├── esp32-gaszaehler.jpg
├── ESP32-Z61-Gaszaehler.jpg
├── Sensor-Gasverbrauch.png
├── Dashboard-Gasverbrauch.png
├── Gasverbrauch-pro-Stunde.png
└── Gasverbrauch-letze-Woche.png
├── README.md
├── common
├── base_webserver.yaml
├── secrets.yaml
├── base.yaml
└── base_global.yaml
├── LICENSE
├── _static
├── webserver-v1.min.js
├── webserver-v1.js
├── webserver-v1.min.css
└── webserver-v1.css
├── gasmeter.yaml
└── wasserundgas.yaml
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .DS_Store
3 |
--------------------------------------------------------------------------------
/docs/Elster-IN-Z61.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zibous/ha-gasmeter/HEAD/docs/Elster-IN-Z61.jpg
--------------------------------------------------------------------------------
/docs/Gas-Verbrauch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zibous/ha-gasmeter/HEAD/docs/Gas-Verbrauch.png
--------------------------------------------------------------------------------
/docs/Gasverbrauch-heute.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zibous/ha-gasmeter/HEAD/docs/Gasverbrauch-heute.png
--------------------------------------------------------------------------------
/docs/esp32-gaszaehler.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zibous/ha-gasmeter/HEAD/docs/esp32-gaszaehler.jpg
--------------------------------------------------------------------------------
/docs/ESP32-Z61-Gaszaehler.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zibous/ha-gasmeter/HEAD/docs/ESP32-Z61-Gaszaehler.jpg
--------------------------------------------------------------------------------
/docs/Sensor-Gasverbrauch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zibous/ha-gasmeter/HEAD/docs/Sensor-Gasverbrauch.png
--------------------------------------------------------------------------------
/docs/Dashboard-Gasverbrauch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zibous/ha-gasmeter/HEAD/docs/Dashboard-Gasverbrauch.png
--------------------------------------------------------------------------------
/docs/Gasverbrauch-pro-Stunde.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zibous/ha-gasmeter/HEAD/docs/Gasverbrauch-pro-Stunde.png
--------------------------------------------------------------------------------
/docs/Gasverbrauch-letze-Woche.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zibous/ha-gasmeter/HEAD/docs/Gasverbrauch-letze-Woche.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ha-gasmeter
2 | Reads gasmeter
3 |
4 |
5 |
6 |
7 |
8 | 
9 |
10 |
11 |
12 | ## NODEMCU Modul
13 |
14 | 
15 |
16 |
--------------------------------------------------------------------------------
/common/base_webserver.yaml:
--------------------------------------------------------------------------------
1 | ## ---------------------------------------------------
2 | ## WEBSERVER Settings
3 | ## ---------------------------------------------------
4 | web_server:
5 | port: 80
6 | css_include: "_static/webserver-v1.min.css"
7 | css_url: ""
8 | js_include: "_static/webserver-v1.min.js"
9 | js_url: ""
--------------------------------------------------------------------------------
/common/secrets.yaml:
--------------------------------------------------------------------------------
1 | ## Example of the settings, before creating the
2 | ## application adjust it for your environment.
3 |
4 | ssid1_pswd: "UpdJyFeHQUrwmM8bbs"
5 | ssid1_name: "Wlanrouter1"
6 |
7 | ssid2_pswd: "fxRGjE2aiL6PCd9caK"
8 | ssid2_name: "Wlanrouter2"
9 |
10 | domain: ".lab.home"
11 |
12 | app_pswd: "pzW8z8jE9XSXyDo9Ng"
13 | ota_pswd: "7wnRTacNf9jm5DNKWC"
14 | ha_pswd: "7wnRTacNf9jm5DNKWC"
15 |
16 | mqtt_broker: mqtt_broker.local
17 | mqtt_username: webservice
18 | mqtt_password: hxt3Xw5jYJZuUvscLi
19 |
20 | home_latitude: 47.4581049
21 | home_longitude: 9.6371659
22 | home_elevation: 403
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Peter Siebler
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/_static/webserver-v1.min.js:
--------------------------------------------------------------------------------
1 | const source=new EventSource("/events");source.addEventListener('log',function(e){const log=document.getElementById("log");let klass='';if(e.data.startsWith("[1;31m")){klass='e';}else if(e.data.startsWith("[0;33m")){klass='w';}else if(e.data.startsWith("[0;32m")){klass='i';}else if(e.data.startsWith("[0;35m")){klass='c';}else if(e.data.startsWith("[0;36m")){klass='d';}else if(e.data.startsWith("[0;37m")){klass='v';}else{log.innerHTML+=e.data+'\n';}
2 | log.innerHTML+=''+e.data.substr(7,e.data.length-10)+"\n";});source.addEventListener('state',function(e){const data=JSON.parse(e.data);document.getElementById(data.id).children[1].innerText=data.state;});const states=document.getElementById("states");let i=0,row;for(;row=states.rows[i];i++){if(!row.children[2].children.length){continue;}
3 | if(row.classList.contains("switch")){(function(id){row.children[2].children[0].addEventListener('click',function(){const xhr=new XMLHttpRequest();xhr.open("POST",'/switch/'+id.substr(7)+'/toggle',true);xhr.send();});})(row.id);}
4 | if(row.classList.contains("fan")){(function(id){row.children[2].children[0].addEventListener('click',function(){const xhr=new XMLHttpRequest();xhr.open("POST",'/fan/'+id.substr(4)+'/toggle',true);xhr.send();});})(row.id);}
5 | if(row.classList.contains("light")){(function(id){row.children[2].children[0].addEventListener('click',function(){const xhr=new XMLHttpRequest();xhr.open("POST",'/light/'+id.substr(6)+'/toggle',true);xhr.send();});})(row.id);}
6 | if(row.classList.contains("cover")){(function(id){row.children[2].children[0].addEventListener('click',function(){const xhr=new XMLHttpRequest();xhr.open("POST",'/cover/'+id.substr(6)+'/open',true);xhr.send();});row.children[2].children[1].addEventListener('click',function(){const xhr=new XMLHttpRequest();xhr.open("POST",'/cover/'+id.substr(6)+'/close',true);xhr.send();});})(row.id);}
7 | if(row.classList.contains("select")){(function(id){row.children[2].children[0].addEventListener('change',function(){const xhr=new XMLHttpRequest();xhr.open("POST",'/select/'+id.substr(7)+'/set?option='+encodeURIComponent(this.value),true);xhr.send();});})(row.id);}}
--------------------------------------------------------------------------------
/_static/webserver-v1.js:
--------------------------------------------------------------------------------
1 | const source = new EventSource("/events");
2 |
3 | source.addEventListener('log', function (e) {
4 | const log = document.getElementById("log");
5 | let klass = '';
6 | if (e.data.startsWith("[1;31m")) {
7 | klass = 'e';
8 | } else if (e.data.startsWith("[0;33m")) {
9 | klass = 'w';
10 | } else if (e.data.startsWith("[0;32m")) {
11 | klass = 'i';
12 | } else if (e.data.startsWith("[0;35m")) {
13 | klass = 'c';
14 | } else if (e.data.startsWith("[0;36m")) {
15 | klass = 'd';
16 | } else if (e.data.startsWith("[0;37m")) {
17 | klass = 'v';
18 | } else {
19 | log.innerHTML += e.data + '\n';
20 | }
21 | log.innerHTML += '' + e.data.substr(7, e.data.length - 10) + "\n";
22 | });
23 |
24 | source.addEventListener('state', function (e) {
25 | const data = JSON.parse(e.data);
26 | document.getElementById(data.id).children[1].innerText = data.state;
27 | });
28 |
29 | const states = document.getElementById("states");
30 | let i = 0, row;
31 | for (; row = states.rows[i]; i++) {
32 | if (!row.children[2].children.length) {
33 | continue;
34 | }
35 |
36 | if (row.classList.contains("switch")) {
37 | (function(id) {
38 | row.children[2].children[0].addEventListener('click', function () {
39 | const xhr = new XMLHttpRequest();
40 | xhr.open("POST", '/switch/' + id.substr(7) + '/toggle', true);
41 | xhr.send();
42 | });
43 | })(row.id);
44 | }
45 | if (row.classList.contains("fan")) {
46 | (function(id) {
47 | row.children[2].children[0].addEventListener('click', function () {
48 | const xhr = new XMLHttpRequest();
49 | xhr.open("POST", '/fan/' + id.substr(4) + '/toggle', true);
50 | xhr.send();
51 | });
52 | })(row.id);
53 | }
54 | if (row.classList.contains("light")) {
55 | (function(id) {
56 | row.children[2].children[0].addEventListener('click', function () {
57 | const xhr = new XMLHttpRequest();
58 | xhr.open("POST", '/light/' + id.substr(6) + '/toggle', true);
59 | xhr.send();
60 | });
61 | })(row.id);
62 | }
63 | if (row.classList.contains("cover")) {
64 | (function(id) {
65 | row.children[2].children[0].addEventListener('click', function () {
66 | const xhr = new XMLHttpRequest();
67 | xhr.open("POST", '/cover/' + id.substr(6) + '/open', true);
68 | xhr.send();
69 | });
70 | row.children[2].children[1].addEventListener('click', function () {
71 | const xhr = new XMLHttpRequest();
72 | xhr.open("POST", '/cover/' + id.substr(6) + '/close', true);
73 | xhr.send();
74 | });
75 | })(row.id);
76 | }
77 | if (row.classList.contains("select")) {
78 | (function(id) {
79 | row.children[2].children[0].addEventListener('change', function () {
80 | const xhr = new XMLHttpRequest();
81 | xhr.open("POST", '/select/' + id.substr(7) + '/set?option=' + encodeURIComponent(this.value), true);
82 | xhr.send();
83 | });
84 | })(row.id);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/common/base.yaml:
--------------------------------------------------------------------------------
1 | # Base Configuration the selected device
2 | # Valid for esp32 and esp8266 w/o BLE SCANNER
3 | #
4 | # Used substitutions:
5 | #
6 | # - device_name_short: Hostname for the device
7 | # - platform: used platform
8 | # - board: used board
9 | # - node_name: name of the device
10 | # - secret file for all private settings
11 | #
12 | # Setup for:
13 | #
14 | # - WIFI
15 | # - WEBSERVER
16 | # - LOGGER
17 | # - OTA
18 | # - Time server
19 | # - API Homeassistant
20 | # - BLE TRACKER
21 | # - Globals for bootcounter, daily value
22 | #
23 | # Sensors:
24 | # - binary_sensor status
25 | # - switch restart
26 | # - switch reset boot counter
27 | # - sensor Boot counter
28 | # - sensor uptime
29 | # - sensor wifi_signal
30 | # - text_sensor version
31 | # - text_sensor Online seit
32 | # - text_sensor IP address
33 | # - text_sensor SSID Name
34 | # - text_sensor BSSID
35 | # - text_sensor Current Timestamp
36 |
37 |
38 | # substitutions:
39 | # update_interval: 60s
40 |
41 | esphome:
42 | name: ${device_name_short}
43 | build_path: ./build/${device_name_short}
44 | on_boot:
45 | then:
46 | - logger.log:
47 | level: info
48 | format: "BOOTMESSAGE:${device_name_short} API is connected, Device ready!"
49 | - globals.set:
50 | id: boot_counter
51 | value: !lambda "return id(boot_counter)+=1;"
52 | on_shutdown:
53 | then:
54 | - logger.log: ${device_name_short} is down!
55 |
56 | ## ---------------------------------------------------
57 | ## WIFI Settings
58 | ## ---------------------------------------------------
59 | wifi:
60 | use_address: ${device_name_short}.local
61 | networks:
62 | - ssid: !secret ssid1_name
63 | password: !secret ssid1_pswd
64 | - ssid: !secret ssid2_name
65 | password: !secret ssid2_pswd
66 |
67 | ## ---------------------------------------------------
68 | ## WEBSERVER Settings
69 | ## ---------------------------------------------------
70 | web_server:
71 | port: 80
72 | css_include: "_static/webserver-v1.min.css"
73 | css_url: ""
74 | js_include: "_static/webserver-v1.min.js"
75 | js_url: ""
76 |
77 | ## ---------------------------------------------------
78 | ## Enable logging
79 | ## ---------------------------------------------------
80 | logger:
81 |
82 | ## ---------------------------------------------------
83 | ## OTA Settings
84 | ## ---------------------------------------------------
85 | ota:
86 | password: !secret ota_pswd
87 | on_error:
88 | then:
89 | - logger.log:
90 | format: "OTA update error %d"
91 | args: ["x"]
92 |
93 | # ----------------------------------------------------------------
94 | # Native API Component
95 | # ----------------------------------------------------------------
96 | api:
97 | id: espapi
98 | port: 6053
99 | reboot_timeout: 5min
100 |
101 | ## ---------------------------------------------------
102 | ## SNTP Time server
103 | ## ---------------------------------------------------
104 | time:
105 | - platform: sntp
106 | id: sntp_time
107 | timezone: Europe/Berlin
108 | servers:
109 | - 0.at.pool.ntp.org
110 | - 0.pool.ntp.org
111 | - 1.pool.ntp.org
112 | on_time:
113 | - seconds: 0
114 | minutes: 0
115 | hours: 0
116 | then:
117 | - lambda: |-
118 | if(id(daily_value)){
119 | id(daily_value)=0.00;
120 | }
121 | - seconds: 0
122 | minutes: 0
123 | then:
124 | - lambda: |-
125 | if(id(hour_value)){
126 | id(hour_value)=0.00;
127 | }
128 | on_time_sync:
129 | then:
130 | - logger.log: "Synchronized sntp clock"
131 |
132 |
--------------------------------------------------------------------------------
/common/base_global.yaml:
--------------------------------------------------------------------------------
1 |
2 | # ----------------------------------------------------------------
3 | # Global variables
4 | # ----------------------------------------------------------------
5 | globals:
6 | - id: boot_counter
7 | type: int
8 | restore_value: yes
9 | initial_value: "0"
10 | - id: daily_value
11 | type: float
12 | restore_value: yes
13 | initial_value: "0.0"
14 | - id: hour_value
15 | type: float
16 | restore_value: yes
17 | initial_value: "0.0"
18 |
19 | ## ---------------------------------------------------
20 | ## binary sensors
21 | ## ---------------------------------------------------
22 | binary_sensor:
23 | - platform: status
24 | name: ${friendly_name} Status
25 |
26 | ## ---------------------------------------------------
27 | ## switches
28 | ## ---------------------------------------------------
29 | switch:
30 | - platform: restart
31 | id: restart_device
32 | name: ${friendly_name} restart
33 | - platform: template
34 | name: ${friendly_name} reset boot counter
35 | turn_on_action:
36 | then:
37 | - lambda: |-
38 | id(boot_counter) = 0;
39 | id(bootcounter).update();
40 | - logger.log: ${device_name_short} reset boot counter o.k!
41 |
42 | ## ---------------------------------------------------
43 | ## all default sensors
44 | ## ---------------------------------------------------
45 | sensor:
46 |
47 | - platform: template
48 | name: ${friendly_name} Boot counter
49 | id: bootcounter
50 | accuracy_decimals: 0
51 | lambda: |-
52 | return (id(boot_counter));
53 |
54 | - platform: uptime
55 | name: ${friendly_name} Uptime Sensor
56 | id: uptime_sensor
57 | update_interval: ${update_interval}
58 | on_raw_value:
59 | then:
60 | - text_sensor.template.publish:
61 | id: uptime_human
62 | state: !lambda |-
63 | int seconds = round(id(uptime_sensor).raw_state);
64 | int days = seconds / (24 * 3600);
65 | seconds = seconds % (24 * 3600);
66 | int hours = seconds / 3600;
67 | seconds = seconds % 3600;
68 | int minutes = seconds / 60;
69 | seconds = seconds % 60;
70 | return (
71 | (days ? String(days) + "d " : "") +
72 | (hours ? String(hours) + "h " : "") +
73 | (minutes ? String(minutes) + "m " : "") +
74 | (String(seconds) + "s")
75 | ).c_str();
76 |
77 | - platform: wifi_signal
78 | id: wifisignal
79 | name: ${friendly_name} WiFi Signal
80 | update_interval: 60s
81 |
82 | - platform: template
83 | id: sensor_wifi_signal_percentage
84 | name: "${friendly_name} WiFi Signal Percentage"
85 | icon: "mdi:wifi"
86 | unit_of_measurement: "%"
87 | update_interval: 60s
88 | lambda: |-
89 | if (id(wifisignal).state) {
90 | if (id(wifisignal).state <= -100 ) {
91 | return 0;
92 | } else if (id(wifisignal).state >= -50) {
93 | return 100;
94 | } else {
95 | return 2 * (id(wifisignal).state + 100);
96 | }
97 | } else {
98 | return NAN;
99 | }
100 |
101 |
102 | ## ---------------------------------------------------
103 | ## all text sensors
104 | ## ---------------------------------------------------
105 | text_sensor:
106 | - platform: version
107 | name: ${friendly_name} Version
108 | id: appver
109 |
110 | - platform: template
111 | name: ${friendly_name} Online seit
112 | id: uptime_human
113 | icon: mdi:clock-start
114 |
115 | - platform: wifi_info
116 | ip_address:
117 | name: ${friendly_name} IP
118 | id: wifiip
119 | icon: mdi:ip-network
120 |
121 | ssid:
122 | name: ${friendly_name} SSID
123 | id: wifiip_ssid
124 | icon: mdi:wifi
125 |
126 | bssid:
127 | name: ${friendly_name} BSSID
128 | id: wifiip_bssid
129 | icon: mdi:wifi
130 |
131 | mac_address:
132 | name: ${friendly_name} Mac Wifi Address
133 | id: wifimac_address
134 | icon: mdi:wifi
135 |
136 | - platform: template
137 | name: ${friendly_name} Timestamp
138 | id: systime
139 | lambda: char str[20];
140 | time_t currTime = id(sntp_time).now().timestamp;
141 | strftime(str, sizeof(str), "%Y-%m-%dT%H:%M:%S", localtime(&currTime));
142 | return (std::string) str;
143 |
--------------------------------------------------------------------------------
/_static/webserver-v1.min.css:
--------------------------------------------------------------------------------
1 | /* Based off of https://github.com/sindresorhus/github-markdown-css */
2 | .markdown-body{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;line-height:1.5;color:#24292e;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:16px;line-height:1.5;word-wrap:break-word}.markdown-body a{background-color:transparent}.markdown-body a:active,.markdown-body a:hover{outline-width:0}.markdown-body strong{font-weight:bolder}.markdown-body h1{font-size:2em;margin:0.67em 0}.markdown-body img{border-style:none}.markdown-body pre{font-family:monospace,monospace;font-size:1em}.markdown-body hr{box-sizing:content-box;height:0;overflow:visible}.markdown-body input{font:inherit;margin:0}.markdown-body input{overflow:visible}.markdown-body [type="checkbox"]{box-sizing:border-box;padding:0}.markdown-body *{box-sizing:border-box}.markdown-body input{font-family:inherit;font-size:inherit;line-height:inherit}.markdown-body a{color:#0366d6;text-decoration:none}.markdown-body a:hover{text-decoration:underline}.markdown-body strong{font-weight:600}.markdown-body hr{height:0;margin:15px 0;overflow:hidden;background:transparent;border:0;border-bottom:1px solid #dfe2e5}.markdown-body hr::before{display:table;content:""}.markdown-body hr::after{display:table;clear:both;content:""}.markdown-body table{border-spacing:0;border-collapse:collapse}.markdown-body td,.markdown-body th{padding:0}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:0;margin-bottom:0}.markdown-body h1{font-size:32px;font-weight:600}.markdown-body h2{font-size:24px;font-weight:600}.markdown-body h3{font-size:20px;font-weight:600}.markdown-body h4{font-size:16px;font-weight:600}.markdown-body h5{font-size:14px;font-weight:600}.markdown-body h6{font-size:12px;font-weight:600}.markdown-body p{margin-top:0;margin-bottom:10px}.markdown-body blockquote{margin:0}.markdown-body ul,.markdown-body ol{padding-left:0;margin-top:0;margin-bottom:0}.markdown-body ol ol,.markdown-body ul ol{list-style-type:lower-roman}.markdown-body ul ul ol,.markdown-body ul ol ol,.markdown-body ol ul ol,.markdown-body ol ol ol{list-style-type:lower-alpha}.markdown-body dd{margin-left:0}.markdown-body pre{margin-top:0;margin-bottom:0;font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:12px}.markdown-body::before{display:table;content:""}.markdown-body::after{display:table;clear:both;content:""}.markdown-body>*:first-child{margin-top:0!important}.markdown-body>*:last-child{margin-bottom:0!important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body p,.markdown-body blockquote,.markdown-body ul,.markdown-body ol,.markdown-body dl,.markdown-body table,.markdown-body pre{margin-top:0;margin-bottom:16px}.markdown-body hr{height:0.25em;padding:0;margin:24px 0;background-color:#e1e4e8;border:0}.markdown-body blockquote{padding:0 1em;color:#6a737d;border-left:0.25em solid #dfe2e5}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.markdown-body h1{padding-bottom:0.3em;font-size:2em;border-bottom:1px solid #eaecef}.markdown-body h2{padding-bottom:0.3em;font-size:1.5em;border-bottom:1px solid #eaecef}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:0.875em}.markdown-body h6{font-size:0.85em;color:#6a737d}.markdown-body ul,.markdown-body ol{padding-left:2em}.markdown-body ul ul,.markdown-body ul ol,.markdown-body ol ol,.markdown-body ol ul{margin-top:0;margin-bottom:0}.markdown-body li{word-wrap:break-all}.markdown-body li>p{margin-top:16px}.markdown-body li+li{margin-top:0.25em}.markdown-body dl{padding:0}.markdown-body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:600}.markdown-body dl dd{padding:0 16px;margin-bottom:16px}.markdown-body table{display:block;width:100%;overflow:auto}.markdown-body table th{font-weight:600}.markdown-body table th,.markdown-body table td{padding:6px 13px;border:1px solid #dfe2e5}.markdown-body table tr{background-color:#fff;border-top:1px solid #c6cbd1}.markdown-body table tr:nth-child(2n){background-color:#f6f8fa}.markdown-body img{max-width:100%;box-sizing:content-box;background-color:#fff}.markdown-body img[align=right]{padding-left:20px}.markdown-body img[align=left]{padding-right:20px}.markdown-body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f6f8fa;border-radius:3px;word-wrap:normal}.markdown-body:checked+.radio-label{position:relative;z-index:1;border-color:#0366d6}.markdown-body hr{border-bottom-color:#eee}#log .v{color:#888}#log .d{color:#0DD}#log .c{color:magenta}#log .i{color:limegreen}#log .w{color:yellow}#log .e{color:red;font-weight:bold}#log{background-color:#1c1c1c}
--------------------------------------------------------------------------------
/_static/webserver-v1.css:
--------------------------------------------------------------------------------
1 | /* Based off of https://github.com/sindresorhus/github-markdown-css */
2 |
3 | .markdown-body {
4 | -ms-text-size-adjust: 100%;
5 | -webkit-text-size-adjust: 100%;
6 | line-height: 1.5;
7 | color: #24292e;
8 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
9 | font-size: 16px;
10 | word-wrap: break-word;
11 | }
12 |
13 | .markdown-body a {
14 | background-color: transparent;
15 | }
16 |
17 | .markdown-body a:active,
18 | .markdown-body a:hover {
19 | outline-width: 0;
20 | }
21 |
22 | .markdown-body strong {
23 | font-weight: bolder;
24 | }
25 |
26 | .markdown-body h1 {
27 | font-size: 2em;
28 | margin: 0.67em 0;
29 | }
30 |
31 | .markdown-body img {
32 | border-style: none;
33 | }
34 |
35 | .markdown-body pre {
36 | font-family: monospace, monospace;
37 | font-size: 1em;
38 | }
39 |
40 | .markdown-body hr {
41 | box-sizing: content-box;
42 | height: 0;
43 | overflow: visible;
44 | }
45 |
46 | .markdown-body input {
47 | font: inherit;
48 | margin: 0;
49 | }
50 |
51 | .markdown-body input {
52 | overflow: visible;
53 | }
54 |
55 | .markdown-body [type="checkbox"] {
56 | box-sizing: border-box;
57 | padding: 0;
58 | }
59 |
60 | .markdown-body * {
61 | box-sizing: border-box;
62 | }
63 |
64 | .markdown-body input {
65 | font-family: inherit;
66 | font-size: inherit;
67 | line-height: inherit;
68 | }
69 |
70 | .markdown-body a {
71 | color: #0366d6;
72 | text-decoration: none;
73 | }
74 |
75 | .markdown-body a:hover {
76 | text-decoration: underline;
77 | }
78 |
79 | .markdown-body strong {
80 | font-weight: 600;
81 | }
82 |
83 | .markdown-body hr {
84 | height: 0;
85 | margin: 15px 0;
86 | overflow: hidden;
87 | background: transparent;
88 | border: 0;
89 | border-bottom: 1px solid #dfe2e5;
90 | }
91 |
92 | .markdown-body hr::before {
93 | display: table;
94 | content: "";
95 | }
96 |
97 | .markdown-body hr::after {
98 | display: table;
99 | clear: both;
100 | content: "";
101 | }
102 |
103 | .markdown-body table {
104 | border-spacing: 0;
105 | border-collapse: collapse;
106 | }
107 |
108 | .markdown-body td,
109 | .markdown-body th {
110 | padding: 0;
111 | }
112 |
113 | .markdown-body h1,
114 | .markdown-body h2,
115 | .markdown-body h3,
116 | .markdown-body h4,
117 | .markdown-body h5,
118 | .markdown-body h6 {
119 | margin-top: 0;
120 | margin-bottom: 0;
121 | }
122 |
123 | .markdown-body h1 {
124 | font-size: 32px;
125 | font-weight: 600;
126 | }
127 |
128 | .markdown-body h2 {
129 | font-size: 24px;
130 | font-weight: 600;
131 | }
132 |
133 | .markdown-body h3 {
134 | font-size: 20px;
135 | font-weight: 600;
136 | }
137 |
138 | .markdown-body h4 {
139 | font-size: 16px;
140 | font-weight: 600;
141 | }
142 |
143 | .markdown-body h5 {
144 | font-size: 14px;
145 | font-weight: 600;
146 | }
147 |
148 | .markdown-body h6 {
149 | font-size: 12px;
150 | font-weight: 600;
151 | }
152 |
153 | .markdown-body p {
154 | margin-top: 0;
155 | margin-bottom: 10px;
156 | }
157 |
158 | .markdown-body blockquote {
159 | margin: 0;
160 | }
161 |
162 | .markdown-body ul,
163 | .markdown-body ol {
164 | padding-left: 0;
165 | margin-top: 0;
166 | margin-bottom: 0;
167 | }
168 |
169 | .markdown-body ol ol,
170 | .markdown-body ul ol {
171 | list-style-type: lower-roman;
172 | }
173 |
174 | .markdown-body ul ul ol,
175 | .markdown-body ul ol ol,
176 | .markdown-body ol ul ol,
177 | .markdown-body ol ol ol {
178 | list-style-type: lower-alpha;
179 | }
180 |
181 | .markdown-body dd {
182 | margin-left: 0;
183 | }
184 |
185 | .markdown-body pre {
186 | margin-top: 0;
187 | margin-bottom: 0;
188 | font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
189 | font-size: 12px;
190 | }
191 | .markdown-body::before {
192 | display: table;
193 | content: "";
194 | }
195 |
196 | .markdown-body::after {
197 | display: table;
198 | clear: both;
199 | content: "";
200 | }
201 |
202 | .markdown-body>*:first-child {
203 | margin-top: 0 !important;
204 | }
205 |
206 | .markdown-body>*:last-child {
207 | margin-bottom: 0 !important;
208 | }
209 |
210 | .markdown-body a:not([href]) {
211 | color: inherit;
212 | text-decoration: none;
213 | }
214 |
215 | .markdown-body p,
216 | .markdown-body blockquote,
217 | .markdown-body ul,
218 | .markdown-body ol,
219 | .markdown-body dl,
220 | .markdown-body table,
221 | .markdown-body pre {
222 | margin-top: 0;
223 | margin-bottom: 16px;
224 | }
225 |
226 | .markdown-body hr {
227 | height: 0.25em;
228 | padding: 0;
229 | margin: 24px 0;
230 | background-color: #e1e4e8;
231 | border: 0;
232 | }
233 |
234 | .markdown-body blockquote {
235 | padding: 0 1em;
236 | color: #6a737d;
237 | border-left: 0.25em solid #dfe2e5;
238 | }
239 |
240 | .markdown-body blockquote>:first-child {
241 | margin-top: 0;
242 | }
243 |
244 | .markdown-body blockquote>:last-child {
245 | margin-bottom: 0;
246 | }
247 |
248 | .markdown-body h1,
249 | .markdown-body h2,
250 | .markdown-body h3,
251 | .markdown-body h4,
252 | .markdown-body h5,
253 | .markdown-body h6 {
254 | margin-top: 24px;
255 | margin-bottom: 16px;
256 | font-weight: 600;
257 | line-height: 1.25;
258 | }
259 |
260 | .markdown-body h1 {
261 | padding-bottom: 0.3em;
262 | font-size: 2em;
263 | border-bottom: 1px solid #eaecef;
264 | }
265 |
266 | .markdown-body h2 {
267 | padding-bottom: 0.3em;
268 | font-size: 1.5em;
269 | border-bottom: 1px solid #eaecef;
270 | }
271 |
272 | .markdown-body h3 {
273 | font-size: 1.25em;
274 | }
275 |
276 | .markdown-body h4 {
277 | font-size: 1em;
278 | }
279 |
280 | .markdown-body h5 {
281 | font-size: 0.875em;
282 | }
283 |
284 | .markdown-body h6 {
285 | font-size: 0.85em;
286 | color: #6a737d;
287 | }
288 |
289 | .markdown-body ul,
290 | .markdown-body ol {
291 | padding-left: 2em;
292 | }
293 |
294 | .markdown-body ul ul,
295 | .markdown-body ul ol,
296 | .markdown-body ol ol,
297 | .markdown-body ol ul {
298 | margin-top: 0;
299 | margin-bottom: 0;
300 | }
301 |
302 | .markdown-body li {
303 | word-wrap: break-all;
304 | }
305 |
306 | .markdown-body li>p {
307 | margin-top: 16px;
308 | }
309 |
310 | .markdown-body li+li {
311 | margin-top: 0.25em;
312 | }
313 |
314 | .markdown-body dl {
315 | padding: 0;
316 | }
317 |
318 | .markdown-body dl dt {
319 | padding: 0;
320 | margin-top: 16px;
321 | font-size: 1em;
322 | font-style: italic;
323 | font-weight: 600;
324 | }
325 |
326 | .markdown-body dl dd {
327 | padding: 0 16px;
328 | margin-bottom: 16px;
329 | }
330 |
331 | .markdown-body table {
332 | display: block;
333 | width: 100%;
334 | overflow: auto;
335 | }
336 |
337 | .markdown-body table th {
338 | font-weight: 600;
339 | }
340 |
341 | .markdown-body table th,
342 | .markdown-body table td {
343 | padding: 6px 13px;
344 | border: 1px solid #dfe2e5;
345 | }
346 |
347 | .markdown-body table tr {
348 | background-color: #fff;
349 | border-top: 1px solid #c6cbd1;
350 | }
351 |
352 | .markdown-body table tr:nth-child(2n) {
353 | background-color: #f6f8fa;
354 | }
355 |
356 | .markdown-body img {
357 | max-width: 100%;
358 | box-sizing: content-box;
359 | background-color: #fff;
360 | }
361 |
362 | .markdown-body img[align=right] {
363 | padding-left: 20px;
364 | }
365 |
366 | .markdown-body img[align=left] {
367 | padding-right: 20px;
368 | }
369 |
370 | .markdown-body pre {
371 | padding: 16px;
372 | overflow: auto;
373 | font-size: 85%;
374 | line-height: 1.45;
375 | background-color: #f6f8fa;
376 | border-radius: 3px;
377 | word-wrap: normal;
378 | }
379 | .markdown-body :checked+.radio-label {
380 | position: relative;
381 | z-index: 1;
382 | border-color: #0366d6;
383 | }
384 |
385 | .markdown-body hr {
386 | border-bottom-color: #eee;
387 | }
388 |
389 | #log .v {
390 | color: #888888;
391 | }
392 |
393 | #log .d {
394 | color: #00DDDD;
395 | }
396 |
397 | #log .c {
398 | color: magenta;
399 | }
400 |
401 | #log .i {
402 | color: limegreen;
403 | }
404 |
405 | #log .w {
406 | color: yellow;
407 | }
408 |
409 | #log .e {
410 | color: red;
411 | font-weight: bold;
412 | }
413 |
414 | #log {
415 | background-color: #1c1c1c;
416 | }
417 |
--------------------------------------------------------------------------------
/gasmeter.yaml:
--------------------------------------------------------------------------------
1 | ## ################################################################
2 | ## ESP32 DEV - GAS & WASSER 2021 - SENSOREN
3 | ## ESP32 NodeMCU Module WLAN WiFi Development Board mit CP2102
4 | ## - GPIO19: Pulscounter Gaszähler
5 | ## ################################################################
6 | esp32:
7 | board: esp32dev
8 | framework:
9 | type: arduino
10 | version: recommended
11 |
12 | substitutions:
13 | platform: ESP32
14 | board: esp32dev
15 | device_name_short: "gasmeter" # used by esp-home config
16 | friendly_name: "GM2021"
17 | device_description: "Gasmeter"
18 | update_interval: 60s
19 | impulsfactor: "0.100"
20 | appversion: "1.1.7"
21 |
22 | esphome:
23 | project:
24 | name: "gasmeter.esp32WUG"
25 | version: ${appversion}
26 |
27 | # ----------------------------------------------------------------
28 | # Global variables
29 | # ----------------------------------------------------------------
30 | globals:
31 | - id: z61count
32 | type: int
33 | restore_value: yes
34 | initial_value: "0"
35 | - id: z61counter
36 | type: float
37 | restore_value: yes
38 | initial_value: "0.0"
39 | - id: m3kw
40 | type: float
41 | restore_value: yes
42 | initial_value: "10.94"
43 | - id: gas_meter_displayinital
44 | type: float
45 | restore_value: yes
46 | initial_value: "29060.654"
47 | - id: gas_meter_displayvalue
48 | type: float
49 | restore_value: yes
50 | initial_value: "29246.433"
51 | - id: gas_meter_totalm3
52 | type: float
53 | restore_value: yes
54 | initial_value: "0.0"
55 |
56 | # ---------------------------------------
57 | # Base packages wifi, timeserver...
58 | # ---------------------------------------
59 | packages:
60 | base: !include common/base.yaml
61 | base_webserver: !include common/base_webserver.yaml
62 | base_global: !include common/base_global.yaml
63 |
64 | # ----------------------------------------------------------------
65 | # Native API Component
66 | # ----------------------------------------------------------------
67 | api:
68 | id: espapi
69 | port: 6053
70 | reboot_timeout: 5min
71 | services:
72 | - service: set_gasmeterdisplay
73 | variables:
74 | my_newdisplayvalue: float
75 | then:
76 | - logger.log:
77 | format: "Setting Gasmeter Display value: %.1f"
78 | args: [my_newdisplayvalue]
79 | - globals.set:
80 | id: gas_meter_displayvalue
81 | value: !lambda "return (my_newdisplayvalue);"
82 | - globals.set:
83 | id: z61counter
84 | value: !lambda "return (my_newdisplayvalue);"
85 | - globals.set:
86 | id: gas_meter_totalm3
87 | value: !lambda "return ((my_newdisplayvalue) - id(gas_meter_displayinital));"
88 | - globals.set:
89 | id: z61count
90 | value: !lambda "return ( ((my_newdisplayvalue) - id(gas_meter_displayinital))/${impulsfactor} );"
91 | - logger.log:
92 | format: "Gasmeter Display value: %.1f"
93 | args: [id(gas_meter_displayvalue)]
94 |
95 | # ----------------------------------------------------------------
96 | # Switch to restart, reset all, reset bootcounter
97 | # ----------------------------------------------------------------
98 | switch:
99 | - platform: template
100 | name: ${friendly_name} reset all
101 | turn_on_action:
102 | then:
103 | - lambda: |-
104 | id(boot_counter) = 0;
105 | id(z61counter) = 0.0;
106 | id(z61count) = 0;
107 | id(gas_meter_totalm3)= 0.0;
108 | id(gas_meter_displayvalue)= 0.0;
109 | id(daily_value)= 0.0;
110 | id(hour_value)= 0.0;
111 | id(bootcounter).update();
112 | id(gas_meter_display).update();
113 | id(gas_meter_total_m3).update();
114 | id(gas_meter_total_kw).update();
115 | id(gas_meter_total_kw_day).update();
116 | - logger.log: ${device_name_short} all values reset!
117 |
118 | # ----------------------------------------------------------------
119 | # GASCOUNTER ZI-61 REED CONTACT
120 | # GPIO19 <-- o-RC-o <--- GND
121 | # o-10k ----> +5V
122 | # +++++++++++++++++++++++++++++++
123 | # Gasmeter: Krom Schröder BK-G,25
124 | # ++++++++++++++++++++++++++++++++
125 | # Q_max: 4 m³/h
126 | # Q_min: 0.025 m³/h
127 | # V: 1.2 dm³
128 | # p_max: 0.5 bar
129 | # 1 imp = 0.1 m³
130 | # ----------------------------------------------------------------
131 | binary_sensor:
132 | - platform: gpio
133 | pin:
134 | number: GPIO19
135 | mode: INPUT_PULLUP ## set ESP32 pin to input pull-up mode
136 | inverted: false
137 | name: ${friendly_name} Gaszähler Z-61 Impuls
138 | id: gassensor_state
139 | device_class: window
140 | filters:
141 | - delayed_off: 10ms
142 | ## This automation will be triggered when a button press ends,
143 | ## or in other words on the falling edge of the signal.
144 | on_release:
145 | then:
146 | - lambda: |-
147 | ESP_LOGI("main", " ------- Z-61 SET NEW VALUES !!!!!");
148 | id(z61count) += 1;
149 | id(z61counter) += ${impulsfactor};
150 | id(gas_meter_displayvalue) += ${impulsfactor};
151 | id(gas_meter_totalm3) += ${impulsfactor};
152 | id(daily_value) += ${impulsfactor};
153 | id(hour_value) += ${impulsfactor};
154 | id(gas_meter_display).update();
155 | id(gas_meter_total_m3).update();
156 | id(gas_meter_total_kw).update();
157 | id(gas_meter_total_kw_day).update();
158 | id(gas_meter_m3_today).publish_state(${impulsfactor});
159 |
160 | # ----------------------------------------------------------------
161 | # ALL SENSORS
162 | # ----------------------------------------------------------------
163 | sensor:
164 | - platform: template
165 | name: ${friendly_name} Gasmeter Display
166 | id: gas_meter_display
167 | accuracy_decimals: 1
168 | unit_of_measurement: "m³"
169 | icon: "mdi:counter"
170 | device_class: gas
171 | lambda: |-
172 | return id(gas_meter_displayvalue);
173 |
174 | - platform: template
175 | name: ${friendly_name} Gasmeter current
176 | id: gas_meter_m3_today
177 | state_class: measurement
178 | device_class: gas
179 | unit_of_measurement: "m³"
180 | accuracy_decimals: 2
181 |
182 | - platform: template
183 | name: ${friendly_name} Gasmeter Impulse
184 | id: gas_meter_impulse_count
185 | state_class: measurement
186 | accuracy_decimals: 0
187 | lambda: |-
188 | return (id(z61count));
189 |
190 | - platform: template
191 | name: ${friendly_name} Gas total
192 | id: gas_meter_total_m3
193 | accuracy_decimals: 1
194 | unit_of_measurement: "m³"
195 | device_class: gas
196 | state_class: total_increasing
197 | lambda: |-
198 | return id(gas_meter_totalm3);
199 |
200 | - platform: template
201 | name: ${friendly_name} Gas per today
202 | id: gas_meter_total_m3_day
203 | unit_of_measurement: "m³"
204 | state_class: total_increasing
205 | accuracy_decimals: 1
206 | icon: mdi:gauge
207 | lambda: |-
208 | return (id(daily_value));
209 |
210 | - platform: template
211 | name: ${friendly_name} Gas per hour
212 | id: gas_meter_total_m3_hour
213 | unit_of_measurement: "m³"
214 | state_class: total_increasing
215 | accuracy_decimals: 1
216 | icon: mdi:gauge
217 | lambda: |-
218 | return (id(hour_value));
219 |
220 | - platform: template
221 | name: ${friendly_name} Kilowattstunde Gas total
222 | id: gas_meter_total_kw
223 | accuracy_decimals: 2
224 | device_class: energy
225 | state_class: measurement
226 | unit_of_measurement: "kWh"
227 | lambda: |-
228 | return (id(gas_meter_totalm3) * id(m3kw));
229 |
230 | - platform: template
231 | name: ${friendly_name} Kilowattstunde Gas today
232 | id: gas_meter_total_kw_day
233 | unit_of_measurement: "kWh"
234 | state_class: measurement
235 | device_class: energy
236 | accuracy_decimals: 2
237 | lambda: |-
238 | return (id(daily_value) * id(m3kw));
239 |
240 | - platform: template
241 | name: ${friendly_name} Kilowattstunde Gas per hour
242 | id: gas_meter_total_kw_hour
243 | unit_of_measurement: "kWh"
244 | state_class: measurement
245 | device_class: energy
246 | accuracy_decimals: 2
247 | lambda: |-
248 | return (id(hour_value) * id(m3kw));
249 |
250 | logger:
251 | level: NONE
252 | # baud_rate: 9600
253 | baud_rate: 0
254 |
--------------------------------------------------------------------------------
/wasserundgas.yaml:
--------------------------------------------------------------------------------
1 | ## ################################################################
2 | ## ESP32 DEV - GAS & WASSER 2021 - SENSOREN
3 | ## - GPIO12: Pulscounter Gaszähler
4 | ## - GPIO34: Druck Kaltwasser
5 | ## - GPIO17: Kaltwasser Temperatur
6 | ## ################################################################
7 | substitutions:
8 | device_id: "wasserundgas"
9 | device_name: "wasserundgas"
10 | device_name_short: "wasserundgas"
11 | device_name_upper: "GWS"
12 | update_interval: 60s
13 | impulsfactor: "0.100"
14 | platform: ESP32
15 | board: esp32dev
16 | attribution: "Data provided by Peter Siebler"
17 | appversion: "1.0.4"
18 | topic_prefix: "tele/wasserundgas"
19 | topic_data: "tele/wasserundgas/data"
20 | device_description: "Gaszähler Kaltwassertemperatur, Kaltwasserdruck"
21 |
22 | esphome:
23 | name: $device_name
24 | comment: ${device_description}
25 | platform: ${platform}
26 | board: ${board}
27 | arduino_version: recommended
28 | project:
29 | name: "ips.home"
30 | version: ${appversion}
31 | on_boot:
32 | priority: -10
33 | then:
34 | - logger.log: "API is connected, Device ready!"
35 |
36 | # ----------------------------------------------------------------
37 | # Global variables
38 | # ----------------------------------------------------------------
39 | globals:
40 | - id: z61count
41 | type: int
42 | restore_value: yes
43 | initial_value: "0"
44 | - id: z61counter
45 | type: float
46 | restore_value: yes
47 | initial_value: "0.000"
48 | - id: m3kw
49 | type: float
50 | restore_value: yes
51 | initial_value: "10.94"
52 | - id: gas_meter_displayvalue
53 | type: float
54 | restore_value: yes
55 | initial_value: "29121.057"
56 | - id: gas_meter_totalm3
57 | type: float
58 | restore_value: yes
59 | initial_value: "0.000"
60 | - id: daily_value
61 | type: float
62 | restore_value: yes
63 | initial_value: "0.000"
64 |
65 | # ----------------------------------------------------------------
66 | # MQTT Client Component
67 | # ----------------------------------------------------------------
68 | # see: https://esphome.io/components/mqtt.html?highlight=mqtt
69 | # inlude mqtt broker and wifi settings w/o api
70 | # sets wifi, ap, domain, default logger, ota password, webserver
71 | # time sntp, mqtt brocker.
72 | <<: !include common/mqttonly.yaml
73 |
74 | # ----------------------------------------------------------------
75 | # Logger settings
76 | # ----------------------------------------------------------------
77 | logger:
78 | level: INFO
79 | logs:
80 | mqtt.component: ERROR
81 | mqtt.client: ERROR
82 |
83 | # ----------------------------------------------------------------
84 | # GPIO02: used for temperatur sensors data wired
85 | # ----------------------------------------------------------------
86 | dallas:
87 | pin: GPIO17
88 | update_interval: ${update_interval}
89 |
90 | switch:
91 | # Switch to restart
92 | - platform: restart
93 | name: ${device_name_upper} restart
94 |
95 | # ----------------------------------------------------------------
96 | # GASCOUNTER ZI-61 REED CONTACT
97 | # ----------------------------------------------------------------
98 | binary_sensor:
99 | - platform: gpio
100 | pin:
101 | number: GPIO12
102 | mode: INPUT_PULLUP
103 | inverted: false
104 | name: ${device_name_upper} Gaszähler Z-61 Impuls
105 | id: gassensor_state
106 | device_class: window
107 | filters:
108 | - delayed_off: 10ms
109 | on_release:
110 | then:
111 | - lambda: |-
112 | id(z61counter) += ${impulsfactor};
113 | id(z61count) += 1;
114 | id(gas_meter_totalm3) += ${impulsfactor};
115 | id(gas_meter_displayvalue) += ${impulsfactor};
116 | id(daily_value) += ${impulsfactor};
117 | id(gas_meter_display).update();
118 | id(gas_meter_total_m3).update();
119 | id(gas_meter_total_kw).update();
120 | id(gas_meter_total_kw_day).update();
121 |
122 | # ----------------------------------------------------------------
123 | # ALL SENSORS
124 | # ----------------------------------------------------------------
125 | sensor:
126 | - platform: template
127 | name: ${device_name_upper} Gaszähler Anzeige
128 | id: gas_meter_display
129 | accuracy_decimals: 3
130 | unit_of_measurement: "m³"
131 | icon: "mdi:counter"
132 | state_topic: ${topic_prefix}/gas_meter_displayvalue
133 | lambda: |-
134 | return id(gas_meter_displayvalue);
135 |
136 | - platform: template
137 | name: ${device_name_upper} Gasverbrauch
138 | id: gas_meter_total_m3
139 | accuracy_decimals: 3
140 | unit_of_measurement: "m³"
141 | state_topic: ${topic_prefix}/gas_total_m3
142 | lambda: |-
143 | return id(gas_meter_totalm3);
144 |
145 | - platform: template
146 | name: ${device_name_upper} Gasverbrauch kW
147 | id: gas_meter_total_kw
148 | accuracy_decimals: 3
149 | unit_of_measurement: "kW"
150 | state_topic: ${topic_prefix}/gas_total_kw
151 | lambda: |-
152 | return (id(gas_meter_totalm3) * id(m3kw));
153 |
154 | - platform: template
155 | name: ${device_name_upper} Gasverbrauch heute
156 | id: gas_meter_total_kw_day
157 | unit_of_measurement: "kW"
158 | lambda: |-
159 | return (id(daily_value) * id(m3kw));
160 |
161 | # -----------------------------------------------------
162 | # DFRobot SEN0257 water pressure sensor 1 GPIO 34
163 | # -----------------------------------------------------
164 | - platform: adc
165 | name: ${device_name_upper} Kaltwasser Wasserdruck
166 | pin: GPIO34
167 | id: coldwater_pressure
168 | update_interval: 10s
169 | unit_of_measurement: "bar"
170 | accuracy_decimals: 2
171 | attenuation: 11db
172 | state_topic: ${topic_prefix}/coldwater_pressure
173 | filters:
174 | - lambda: |-
175 | if(x-0.41<0) return 0.00;
176 | return ((x) * 2.00) - 0.82;
177 |
178 | # ------------------------------------------------------------------------------
179 | # PIN GIPO17: DS18B20 Digital temperature sensor 1
180 | # For this, connect a resistor of about 4.7KΩ (values around that like 1KΩ will,
181 | # if you don’t have massively long wires, work fine in most cases)
182 | # between 3.3V and the data pin.
183 | # Unique ID: 'dallas-7900000C8579C728'
184 | # ------------------------------------------------------------------------------
185 | - platform: dallas
186 | # index: 0
187 | address: 0x7900000C8579C728
188 | accuracy_decimals: 2
189 | unit_of_measurement: "°C"
190 | name: ${device_name_upper} Kaltwasser Temperatur
191 | id: coldwater_temperature
192 | icon: mdi:thermometer-lines
193 | state_topic: ${topic_prefix}/coldwater_temperature
194 |
195 | - platform: wifi_signal
196 | id: wifisignal
197 | name: ${device_name_upper} WiFi Signal
198 | update_interval: 60s
199 |
200 | # -----------------------------------------------
201 | # additional sensors
202 | # -----------------------------------------------
203 | - platform: uptime
204 | name: ${device_name_upper} Uptime Sensor
205 | id: uptime_sensor
206 | update_interval: ${update_interval}
207 | on_raw_value:
208 | then:
209 | - text_sensor.template.publish:
210 | id: uptime_human
211 | state: !lambda |-
212 | int seconds = round(id(uptime_sensor).raw_state);
213 | int days = seconds / (24 * 3600);
214 | seconds = seconds % (24 * 3600);
215 | int hours = seconds / 3600;
216 | seconds = seconds % 3600;
217 | int minutes = seconds / 60;
218 | seconds = seconds % 60;
219 | return (
220 | (days ? String(days) + "d " : "") +
221 | (hours ? String(hours) + "h " : "") +
222 | (minutes ? String(minutes) + "m " : "") +
223 | (String(seconds) + "s")
224 | ).c_str();
225 | on_value:
226 | - mqtt.publish_json:
227 | topic: "tele/wasserundgas/data"
228 | payload: !lambda |-
229 | root["name_pretty"] = "${device_name_upper}";
230 | root["gas_meter_sensor"] = id(gassensor_state).state;
231 | root["gas_display"] = id(gas_meter_display).state;
232 | root["gas_meter_total_m3"] = id(gas_meter_total_m3).state;
233 | root["gas_meter_total_kw"] = id(gas_meter_total_kw).state;
234 | root["z61counter"] = id(z61counter);
235 | root["z61count"] = id(z61count);
236 | root["coldwater_pressure"] = isnan(id(coldwater_pressure).state)?0:id(coldwater_pressure).state;
237 | root["coldwater_temperature"] = isnan(id(coldwater_temperature).state)?0:id(coldwater_temperature).state;
238 | root["wifi_signal"] = id(wifisignal).state;
239 | root["wif_iip"] = id(wifiip).state;
240 | root["wifi_ssid"] = id(wifissid).state;
241 | root["wifi_bssid"] = id(wifibssid).state;
242 | root["version"] = id(appver).state;
243 | root["timestamp"] = id(systime).state;
244 | root["uptime"] = id(uptime_sensor).state;
245 | root["uptime_human"] = id(uptime_human).state;
246 | root["appversion"] = "${appversion}";
247 | root["attribution"] = "${attribution}";
248 |
249 | ## -----------------------------------------------------------
250 | ## additional sensor data
251 | ## -----------------------------------------------------------
252 | text_sensor:
253 | - platform: version
254 | name: ${device_name_upper} Version
255 | id: appver
256 |
257 | - platform: template
258 | name: ${device_name_upper} Online seit
259 | id: uptime_human
260 | icon: mdi:clock-start
261 |
262 | - platform: wifi_info
263 | ip_address:
264 | name: ${device_name_upper} IP
265 | id: wifiip
266 | icon: mdi:ip-network
267 |
268 | ssid:
269 | name: ${device_name_upper} SSID
270 | id: wifissid
271 |
272 | bssid:
273 | id: wifibssid
274 | name: ${device_name_upper} BSSID
275 |
276 | - platform: template
277 | name: ${device_name_upper} Timestamp
278 | id: systime
279 | lambda: char str[20];
280 | time_t currTime = id(sntp_time).now().timestamp;
281 | strftime(str, sizeof(str), "%Y-%m-%dT%H:%M:%S", localtime(&currTime));
282 | return (std::string) str;
283 |
--------------------------------------------------------------------------------