Skip to content

Commit d9dab7f

Browse files
Refactor the loop. (#1)
Improve the maintainability.
1 parent ff73501 commit d9dab7f

File tree

1 file changed

+82
-80
lines changed

1 file changed

+82
-80
lines changed

smartMeterReader-esp32.ino

Lines changed: 82 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
66
and pushes these telegrams to websocket clients connected on '/raw'.
77
8-
There is also a websocket '/current' pushing the current wattage to connected clients.
8+
There is also a websocket '/current' pushing the current usage stats to connected clients.
9+
10+
Finally there is a webserver at port 80 with an index page that connects to websocket '/current' and shows energy use info.
911
1012
How to connect to a p1 port see: https://github.com/matthijskooijman/arduino-dsmr#connecting-the-p1-port
1113
*/
@@ -30,6 +32,7 @@
3032
#define I2C_SDA_PIN (5)
3133
#define I2C_SCL_PIN (4)
3234

35+
/* settings for ntp time sync */
3336
const char* NTP_POOL = "pool.ntp.org";
3437
const char* TIMEZONE = "CET-1CEST,M3.5.0/2,M10.5.0/3"; /* Central European Time - see http://www.remotemonitoringsystems.ca/time-zone-abbreviations.php */
3538

@@ -41,19 +44,16 @@ const IPAddress SUBNET(255, 255, 255, 0); /* Usually 255,255,255,
4144
const IPAddress PRIMARY_DNS(192, 168, 0, 30); /* Check in your router */
4245
const IPAddress SECONDARY_DNS(192, 168, 0, 50); /* Check in your router */
4346

44-
AsyncWebServer server(80);
45-
AsyncWebSocket ws_raw("/raw");
46-
AsyncWebSocket ws_current("/current");
47-
HardwareSerial smartMeter(UART_NR);
48-
SSD1306 oled(OLED_ADDRESS, I2C_SDA_PIN, I2C_SCL_PIN);
49-
bool oledFound{false};
50-
uint8_t currentDay;
47+
const char* WS_RAW_URL{"/raw"};
48+
const char* WS_CURRENT_URL{"/current"};
5149

52-
struct {
53-
int t1Start{0};
54-
int t2Start{0};
55-
int gasStart{0};
56-
} today;
50+
AsyncWebServer server(80);
51+
AsyncWebSocket ws_raw(WS_RAW_URL);
52+
AsyncWebSocket ws_current(WS_CURRENT_URL);
53+
HardwareSerial smartMeter(UART_NR);
54+
SSD1306 oled(OLED_ADDRESS, I2C_SDA_PIN, I2C_SCL_PIN);
55+
bool oledFound{false};
56+
uint8_t currentMonthDay;
5757

5858
void setup() {
5959
Serial.begin(115200);
@@ -99,7 +99,7 @@ void setup() {
9999

100100
while (!getLocalTime(&timeinfo, 0))
101101
delay(10);
102-
currentDay = timeinfo.tm_mday;
102+
currentMonthDay = timeinfo.tm_mday;
103103

104104
/* websocket setup */
105105
ws_raw.onEvent(onEvent);
@@ -127,89 +127,28 @@ void setup() {
127127
Serial.printf("Listening on HardwareSerial(%i) with RXD_PIN=%i\n", UART_NR, RXD_PIN);
128128
}
129129

130-
bool coldBoot{true};
131-
char currentUseString[200];
132-
133130
void loop() {
134131
static String telegram{""};
135132

136133
ws_raw.cleanupClients();
137134
ws_current.cleanupClients();
138135

139136
while (smartMeter.available()) {
140-
141137
const char incomingChar = smartMeter.read();
142-
143-
if (incomingChar != '!')
144-
telegram.concat(incomingChar);
145-
else {
146-
telegram.concat(incomingChar);
147-
148-
/* checksum reached, wait for and read 6 more bytes then the telegram is received completely - see DSMR 5.0.2 ¶ 6.2 */
149-
while (smartMeter.available() < 6) delay(1);
150-
151-
while (smartMeter.available()) telegram.concat((char)smartMeter.read());
152-
153-
ws_raw.textAll(telegram);
154-
155-
currentUseData data;
156-
const ParseResult<void> res = P1Parser::parse(&data, telegram.c_str(), telegram.length());
157-
158-
if (res.err)
159-
ESP_LOGE(TAG, "%s", res.fullError(telegram.c_str(), telegram.c_str() + telegram.length()));
160-
else
161-
{
162-
if (coldBoot) {
163-
today.t1Start = data.energy_delivered_tariff1.int_val();
164-
today.t2Start = data.energy_delivered_tariff2.int_val();
165-
today.gasStart = data.gas_delivered.int_val();
166-
coldBoot = false;
167-
};
168-
169-
snprintf(currentUseString, sizeof(currentUseString), "%i\n%i\n%i\n%i\n%i\n%i\n%i\n%s",
170-
data.power_delivered.int_val(),
171-
data.energy_delivered_tariff1.int_val(),
172-
data.energy_delivered_tariff2.int_val(),
173-
data.gas_delivered.int_val(),
174-
data.energy_delivered_tariff1.int_val() - today.t1Start,
175-
data.energy_delivered_tariff2.int_val() - today.t2Start,
176-
data.gas_delivered.int_val() - today.gasStart,
177-
(data.electricity_tariff.equals("0001")) ? "laag" : "hoog"
178-
);
179-
180-
ws_current.textAll(currentUseString);
181-
182-
if (oledFound) {
183-
oled.clear();
184-
oled.setFont(ArialMT_Plain_16);
185-
oled.drawString(oled.width() >> 1, 0, WiFi.localIP().toString());
186-
oled.setFont(ArialMT_Plain_24);
187-
oled.drawString(oled.width() >> 1, 18, String(data.power_delivered.int_val()) + "W");
188-
oled.display();
189-
}
190-
191-
/* check if we changed day and update starter values if so */
192-
struct tm timeinfo = {0};
193-
getLocalTime(&timeinfo);
194-
if (currentDay != timeinfo.tm_mday) {
195-
today.t1Start = data.energy_delivered_tariff1.int_val();
196-
today.t2Start = data.energy_delivered_tariff2.int_val();
197-
today.gasStart = data.gas_delivered.int_val();
198-
currentDay = timeinfo.tm_mday;
199-
}
200-
}
201-
telegram = "";
202-
}
138+
telegram.concat(incomingChar);
139+
if ('!' == incomingChar) parseAndSend(telegram);
203140
}
204141
delay(1);
205142
}
206143

144+
char currentUseString[200];
145+
207146
void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len) {
208147
switch (type) {
209148

210149
case WS_EVT_CONNECT :
211150
ESP_LOGI(TAG, "[%s][%u] connect", server->url(), client->id());
212-
if (0 == strcmp("/current", server->url()))
151+
if (0 == strcmp(WS_CURRENT_URL, server->url()))
213152
client->text(currentUseString);
214153
break;
215154

@@ -236,3 +175,66 @@ void onEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
236175
default : ESP_LOGE(TAG, "unhandled ws event type");
237176
}
238177
}
178+
179+
void parseAndSend(String& telegram) {
180+
/* checksum reached, wait for and read 6 more bytes then the telegram is received completely - see DSMR 5.0.2 ¶ 6.2 */
181+
while (smartMeter.available() < 6) delay(1);
182+
183+
while (smartMeter.available()) telegram.concat((char)smartMeter.read());
184+
185+
ws_raw.textAll(telegram);
186+
187+
currentUseData data;
188+
const ParseResult<void> res = P1Parser::parse(&data, telegram.c_str(), telegram.length());
189+
190+
if (res.err) {
191+
ESP_LOGE(TAG, "%s", res.fullError(telegram.c_str(), telegram.c_str() + telegram.length()));
192+
telegram = "";
193+
return;
194+
}
195+
telegram = "";
196+
197+
static struct {
198+
uint32_t t1Start{0};
199+
uint32_t t2Start{0};
200+
uint32_t gasStart{0};
201+
} today;
202+
203+
if (!today.t1Start) {
204+
today.t1Start = data.energy_delivered_tariff1.int_val();
205+
today.t2Start = data.energy_delivered_tariff2.int_val();
206+
today.gasStart = data.gas_delivered.int_val();
207+
};
208+
209+
snprintf(currentUseString, sizeof(currentUseString), "%i\n%i\n%i\n%i\n%i\n%i\n%i\n%s",
210+
data.power_delivered.int_val(),
211+
data.energy_delivered_tariff1.int_val(),
212+
data.energy_delivered_tariff2.int_val(),
213+
data.gas_delivered.int_val(),
214+
data.energy_delivered_tariff1.int_val() - today.t1Start,
215+
data.energy_delivered_tariff2.int_val() - today.t2Start,
216+
data.gas_delivered.int_val() - today.gasStart,
217+
(data.electricity_tariff.equals("0001")) ? "laag" : "hoog"
218+
);
219+
220+
ws_current.textAll(currentUseString);
221+
222+
if (oledFound) {
223+
oled.clear();
224+
oled.setFont(ArialMT_Plain_16);
225+
oled.drawString(oled.width() >> 1, 0, WiFi.localIP().toString());
226+
oled.setFont(ArialMT_Plain_24);
227+
oled.drawString(oled.width() >> 1, 18, String(data.power_delivered.int_val()) + "W");
228+
oled.display();
229+
}
230+
231+
/* check if we changed day and update starter values if so */
232+
struct tm timeinfo = {0};
233+
getLocalTime(&timeinfo);
234+
if (currentMonthDay != timeinfo.tm_mday) {
235+
today.t1Start = data.energy_delivered_tariff1.int_val();
236+
today.t2Start = data.energy_delivered_tariff2.int_val();
237+
today.gasStart = data.gas_delivered.int_val();
238+
currentMonthDay = timeinfo.tm_mday;
239+
}
240+
}

0 commit comments

Comments
 (0)