Subversion Repositories ESP32_P1_Meter

Rev

Rev 5 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5 Rev 6
Line 1... Line 1...
1
////////////////////////////////  Include libraries  /////////////////////////////////////////
1
////////////////////////////////  Include libraries  /////////////////////////////////////////
2
#include <Arduino.h>
2
#include <Arduino.h>
3
#include <ArduinoOTA.h>
3
#include <ArduinoOTA.h>
4
#include <EEPROM.h>
4
#include <EEPROM.h>
5
#include <Ticker.h>
-
 
6
#include <FS.h>
5
#include <FS.h>
7
#include <LittleFS.h>
6
#include <LittleFS.h>
8
#include <ezButton.h>
7
#include <ezButton.h>
9
#include <PubSubClient.h>              // https://github.com/knolleary/pubsubclient/
8
#include <PubSubClient.h>              // https://github.com/knolleary/pubsubclient/
10
#include <AsyncFsWebServer.h>          //https://github.com/cotestatnt/async-esp-fs-webserver
9
#include <AsyncFsWebServer.h>          //https://github.com/cotestatnt/async-esp-fs-webserver
-
 
10
#include <HardwareSerial.h>
11
 
11
 
12
////////////////////////////////  Include settings  /////////////////////////////////////////
12
////////////////////////////////  Include settings  /////////////////////////////////////////
13
#include "settings.h"
13
#include "settings.h"
14
 
14
 
15
////////////////////////////////  Define constants  /////////////////////////////////////////
15
////////////////////////////////  Define constants  /////////////////////////////////////////
Line 31... Line 31...
31
#define MQTT_CLIENT_LABEL "MQTT Client"
31
#define MQTT_CLIENT_LABEL "MQTT Client"
32
#define MQTT_SERVER_LABEL "MQTT Server"
32
#define MQTT_SERVER_LABEL "MQTT Server"
33
#define MQTT_PORT_LABEL "MQTT Server Port"
33
#define MQTT_PORT_LABEL "MQTT Server Port"
34
#define MQTT_USER_LABEL "MQTT User"
34
#define MQTT_USER_LABEL "MQTT User"
35
#define MQTT_PASSWORD_LABEL "MQTT Password"
35
#define MQTT_PASSWORD_LABEL "MQTT Password"
36
#define MQTT_TOPIC_LABEL "MQTT Topic"
36
#define MQTT_PREFIX_LABEL "MQTT Prefix"
37
 
37
 
38
#define SHORT_PRESS_TIME_MIN 1000 // 1 second
38
#define SHORT_PRESS_TIME_MIN 1000 // 1 second
39
#define SHORT_PRESS_TIME_MAX 2500 // 2.5 seconds
39
#define SHORT_PRESS_TIME_MAX 2500 // 2.5 seconds
40
#define LONG_PRESS_TIME  10000 // 10 seconds
40
#define LONG_PRESS_TIME  10000 // 10 seconds
41
 
41
 
Line 43... Line 43...
43
  0x89, 0x50, 0x4E, 0x47, /* ... */
43
  0x89, 0x50, 0x4E, 0x47, /* ... */
44
};
44
};
45
 
45
 
46
////////////////////////////////  Create Objects  /////////////////////////////////////////
46
////////////////////////////////  Create Objects  /////////////////////////////////////////
47
struct tm Time;
47
struct tm Time;
-
 
48
 
48
Ticker ticker;
49
HardwareSerial mySerial(0); // UART0 (Serial0)
-
 
50
 
49
AsyncFsWebServer server(FILESYSTEM, 80, "P1_Meter");
51
AsyncFsWebServer server(FILESYSTEM, 80, "P1_Meter");
50
ezButton button(9); // create ezButton object that attach to pin GPIO9
52
ezButton button(9); // create ezButton object that attach to pin GPIO9
51
 
53
 
-
 
54
WiFiClient espClient;
-
 
55
PubSubClient mqttClient(espClient);
52
 
56
 
53
// * Define variables
57
////////////////////////////////  Define variables  /////////////////////////////////////////
54
bool captiveRun = false;
58
bool captiveRun = false;
55
// Setup Settings
59
// Setup Settings
56
String Username = "admin";
60
String Username = "admin";
57
String Password = "admin";
61
String Password = "admin";
58
bool External_Antenna = true;
62
bool External_Antenna = true;
-
 
63
 
59
// MQTT Settings
64
// MQTT Settings
60
bool MQTT_Enabled = false;
65
bool MQTT_Enabled = false;
61
String MQTT_Client = "ESP32_P1_Meter";
66
String MQTT_Client = "ESP32_P1_Meter";
62
String MQTT_Server = "";
67
String MQTT_Server = "";
63
//uint16_t MQTT_Port = Default_MQTT_Port;
-
 
64
String MQTT_Port = Default_MQTT_Port;
68
String MQTT_Port = Default_MQTT_Port;
65
String MQTT_User = "";
69
String MQTT_User = "";
66
String MQTT_Password = "";
70
String MQTT_Password = "";
67
String MQTT_Topic = "P1_Meter";
71
String MQTT_Prefix = "P1_Meter";
68
int LEDSpeed = 0;
72
int LEDSpeed = 0;
69
 
73
 
70
bool isPressing = false;
74
bool isPressing = false;
71
unsigned long pressedTime  = 0;
75
unsigned long pressedTime  = 0;
72
unsigned long releasedTime = 0;
76
unsigned long releasedTime = 0;
73
 
77
 
-
 
78
char clientId[16];
-
 
79
char inTopic[24];
-
 
80
char outTopic[24];
-
 
81
 
74
////////////////////////////////  Filesystem  /////////////////////////////////////////
82
////////////////////////////////  Filesystem  /////////////////////////////////////////
75
bool startFilesystem() {
83
bool startFilesystem() {
76
  if (FILESYSTEM.begin()){
84
  if (FILESYSTEM.begin()){
77
    server.printFileList(FILESYSTEM, "/", 2), Serial;
85
    server.printFileList(FILESYSTEM, "/", 2), Serial;
78
    return true;
86
    return true;
Line 94... Line 102...
94
	fsInfo->totalBytes = LittleFS.totalBytes();
102
	fsInfo->totalBytes = LittleFS.totalBytes();
95
	fsInfo->usedBytes = LittleFS.usedBytes();
103
	fsInfo->usedBytes = LittleFS.usedBytes();
96
}
104
}
97
#endif
105
#endif
98
 
106
 
-
 
107
// * Send a message to a broker topic
-
 
108
void send_mqtt_message(const char *topic, char *payload)
-
 
109
{
-
 
110
    Serial.printf("MQTT Outgoing on %s: ", topic);
-
 
111
    Serial.println(payload);
-
 
112
    if (MQTT_Enabled) {
-
 
113
 
-
 
114
      bool result = mqttClient.publish(topic, payload, false);
-
 
115
 
-
 
116
      if (!result)
-
 
117
      {
-
 
118
          Serial.printf("MQTT publish to topic %s failed\n", topic);
-
 
119
      }
-
 
120
    }
-
 
121
}
-
 
122
 
-
 
123
///////////////////////////  MQTT callback function  ///////////////////////////////////
-
 
124
void mqttCallback(char* topic, byte* payload, unsigned int length) {
-
 
125
  Serial.printf("Message arrived [%s] ", topic);
-
 
126
  for (int i = 0; i < length; i++) {
-
 
127
    Serial.print((char)payload[i]);
-
 
128
  }
-
 
129
  Serial.println();
-
 
130
}
-
 
131
 
-
 
132
///////////////////////////  MQTT reconnect function  ///////////////////////////////////
-
 
133
void mqttReconnect() {
-
 
134
 
-
 
135
  if (WiFi.status() != WL_CONNECTED)  // Check connection
-
 
136
    return;
-
 
137
 
-
 
138
  static uint32_t lastConnectionTime = 5000;
-
 
139
  if (millis() - lastConnectionTime < 5000)  // Wait 5 seconds before retrying
-
 
140
    return;
-
 
141
  lastConnectionTime = millis();
-
 
142
 
-
 
143
  if (MQTT_Enabled) {
-
 
144
    Serial.print("Attempting MQTT connection...");
-
 
145
    if (mqttClient.connect(MQTT_Client.c_str(), MQTT_User.c_str(), MQTT_Password.c_str())) {  // Attempt to connect
-
 
146
      Serial.println("connected to MQTT server.");
-
 
147
 
-
 
148
      String payload = "Hello World from ";
-
 
149
      payload += clientId;
-
 
150
      mqttClient.publish(outTopic, payload.c_str());  // Once connected, publish an announcement...
-
 
151
      mqttClient.subscribe(inTopic);
-
 
152
                      // ... and resubscribe
-
 
153
    } else {
-
 
154
      Serial.printf("failed, rc=%d, try again in 5 seconds\n", mqttClient.state());
-
 
155
    }
-
 
156
  }
-
 
157
}
-
 
158
 
99
////////////////////////////////   WebSocket Handler  /////////////////////////////
159
////////////////////////////////   WebSocket Handler  /////////////////////////////
100
void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){
160
void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){
101
  switch (type) {
161
  switch (type) {
102
    case WS_EVT_DISCONNECT:
162
    case WS_EVT_DISCONNECT:
103
      Serial.print("WebSocket client disconnected!\n");
163
      Serial.print("WebSocket client disconnected!\n");
Line 137... Line 197...
137
    server.getOptionValue(MQTT_CLIENT_LABEL, MQTT_Client);
197
    server.getOptionValue(MQTT_CLIENT_LABEL, MQTT_Client);
138
    server.getOptionValue(MQTT_SERVER_LABEL, MQTT_Server);
198
    server.getOptionValue(MQTT_SERVER_LABEL, MQTT_Server);
139
    server.getOptionValue(MQTT_PORT_LABEL, MQTT_Port);
199
    server.getOptionValue(MQTT_PORT_LABEL, MQTT_Port);
140
    server.getOptionValue(MQTT_USER_LABEL, MQTT_User);
200
    server.getOptionValue(MQTT_USER_LABEL, MQTT_User);
141
    server.getOptionValue(MQTT_PASSWORD_LABEL, MQTT_Password);
201
    server.getOptionValue(MQTT_PASSWORD_LABEL, MQTT_Password);
142
    server.getOptionValue(MQTT_TOPIC_LABEL, MQTT_Topic);
202
    server.getOptionValue(MQTT_PREFIX_LABEL, MQTT_Prefix);
143
 
203
 
144
    Serial.println("\nThis are the current values stored: \n");
204
    Serial.println("\nThis are the current values stored: \n");
145
    Serial.printf("MQTT Enabled: %s\n", MQTT_Enabled ? "true" : "false");
205
    Serial.printf("MQTT Enabled: %s\n", MQTT_Enabled ? "true" : "false");
146
    Serial.printf("MQTT Client: %s\n", MQTT_Client.c_str());
206
    Serial.printf("MQTT Client: %s\n", MQTT_Client.c_str());
147
    Serial.printf("MQTT Server: %s\n", MQTT_Server.c_str());
207
    Serial.printf("MQTT Server: %s\n", MQTT_Server.c_str());
148
//    Serial.printf("MQTT Server Port: %d\n", MQTT_Port);
-
 
149
    Serial.printf("MQTT Server Port: %s\n", MQTT_Port.c_str());
208
    Serial.printf("MQTT Server Port: %s\n", MQTT_Port.c_str());
150
    Serial.printf("MQTT User: %s\n", MQTT_User.c_str());
209
    Serial.printf("MQTT User: %s\n", MQTT_User.c_str());
151
    Serial.printf("MQTT password: %s\n", MQTT_Password.c_str());
210
    Serial.printf("MQTT password: %s\n", MQTT_Password.c_str());
152
    Serial.printf("MQTT Topic: %s\n", MQTT_Topic.c_str());
211
    Serial.printf("MQTT Prefix: %s\n", MQTT_Prefix.c_str());
153
    return true;
212
    return true;
154
  }
213
  }
155
  else
214
  else
156
    Serial.println(F("Config file not exist"));
215
    Serial.println(F("Config file not exist"));
157
  return false;
216
  return false;
158
}
217
}
159
 
218
 
160
bool _was_connected = false;
-
 
161
void saveOptions() {
-
 
162
   server.saveOptionValue(USER_LABEL, Username);
-
 
163
   server.saveOptionValue(PASSWORD_LABEL, Password);
-
 
164
   server.saveOptionValue(EXTERNAL_ANTENNA_LABEL, External_Antenna);
-
 
165
 
-
 
166
   server.saveOptionValue(MQTT_ENABLED_LABEL, MQTT_Enabled);
-
 
167
   server.saveOptionValue(MQTT_CLIENT_LABEL, MQTT_Client);
-
 
168
   server.saveOptionValue(MQTT_SERVER_LABEL, MQTT_Server);
-
 
169
   server.saveOptionValue(MQTT_PORT_LABEL, MQTT_Port);
-
 
170
   server.saveOptionValue(MQTT_USER_LABEL, MQTT_User);
-
 
171
   server.saveOptionValue(MQTT_PASSWORD_LABEL, MQTT_Password);
-
 
172
   server.saveOptionValue(MQTT_TOPIC_LABEL, MQTT_Topic);
-
 
173
  Serial.println(F("Application options saved."));
-
 
174
}
-
 
175
 
-
 
176
////////////////////////////  HTTP Request Handlers  ////////////////////////////////////
219
////////////////////////////  HTTP Request Handlers  ////////////////////////////////////
177
void handleLoadOptions(AsyncWebServerRequest *request) {
220
void handleLoadOptions(AsyncWebServerRequest *request) {
178
  request->send(200, "text/plain", "Options loaded");
221
  request->send(200, "text/plain", "Options loaded");
179
  loadOptions();
222
  loadOptions();
180
  Serial.println("Application option loaded after web request");
223
  Serial.println("Application option loaded after web request");
181
}
224
}
182
 
225
 
-
 
226
////////////////////////////  Send data to MQTT  ////////////////////////////////////
-
 
227
void send_metric(String name, long metric)
-
 
228
{
-
 
229
//    Serial.print(F("Sending metric to broker: "));
-
 
230
    Serial.print(name);
-
 
231
    Serial.print(F("="));
-
 
232
    Serial.println(metric);
-
 
233
 
-
 
234
    char output[10];
-
 
235
    ltoa(metric, output, sizeof(output));
-
 
236
 
-
 
237
    String topic = String(MQTT_Prefix) + "/" + name;
-
 
238
    send_mqtt_message(topic.c_str(), output);
-
 
239
}
-
 
240
 
-
 
241
////////////////////////////  Set data for MQTT  ////////////////////////////////////
-
 
242
void send_data_to_broker()
-
 
243
{
-
 
244
    send_metric("consumption_low_tarif", CONSUMPTION_LOW_TARIF);
-
 
245
    send_metric("consumption_high_tarif", CONSUMPTION_HIGH_TARIF);
-
 
246
    send_metric("returndelivery_low_tarif", RETURNDELIVERY_LOW_TARIF);
-
 
247
    send_metric("returndelivery_high_tarif", RETURNDELIVERY_HIGH_TARIF);
-
 
248
    send_metric("actual_consumption", ACTUAL_CONSUMPTION);
-
 
249
    send_metric("actual_returndelivery", ACTUAL_RETURNDELIVERY);
-
 
250
 
-
 
251
    send_metric("l1_instant_power_usage", L1_INSTANT_POWER_USAGE);
-
 
252
    send_metric("l2_instant_power_usage", L2_INSTANT_POWER_USAGE);
-
 
253
    send_metric("l3_instant_power_usage", L3_INSTANT_POWER_USAGE);
-
 
254
    send_metric("l1_instant_power_current", L1_INSTANT_POWER_CURRENT);
-
 
255
    send_metric("l2_instant_power_current", L2_INSTANT_POWER_CURRENT);
-
 
256
    send_metric("l3_instant_power_current", L3_INSTANT_POWER_CURRENT);
-
 
257
    send_metric("l1_voltage", L1_VOLTAGE);
-
 
258
    send_metric("l2_voltage", L2_VOLTAGE);
-
 
259
    send_metric("l3_voltage", L3_VOLTAGE);
-
 
260
    
-
 
261
    send_metric("gas_meter_m3", GAS_METER_M3);
-
 
262
 
-
 
263
    send_metric("actual_tarif_group", ACTUAL_TARIF);
-
 
264
    send_metric("short_power_outages", SHORT_POWER_OUTAGES);
-
 
265
    send_metric("long_power_outages", LONG_POWER_OUTAGES);
-
 
266
    send_metric("short_power_drops", SHORT_POWER_DROPS);
-
 
267
    send_metric("short_power_peaks", SHORT_POWER_PEAKS);
-
 
268
}
-
 
269
 
-
 
270
////////////////////////////  CRC16 Check  ////////////////////////////////////
-
 
271
unsigned int CRC16(unsigned int crc, unsigned char *buf, int len)
-
 
272
{
-
 
273
	for (int pos = 0; pos < len; pos++)
-
 
274
    {
-
 
275
		crc ^= (unsigned int)buf[pos];    // * XOR byte into least sig. byte of crc
-
 
276
                                          // * Loop over each bit
-
 
277
        for (int i = 8; i != 0; i--)
-
 
278
        {
-
 
279
            // * If the LSB is set
-
 
280
            if ((crc & 0x0001) != 0)
-
 
281
            {
-
 
282
                // * Shift right and XOR 0xA001
-
 
283
                crc >>= 1;
-
 
284
				crc ^= 0xA001;
-
 
285
			}
-
 
286
            // * Else LSB is not set
-
 
287
            else
-
 
288
                // * Just shift right
-
 
289
                crc >>= 1;
-
 
290
		}
-
 
291
	}
-
 
292
	return crc;
-
 
293
}
-
 
294
 
-
 
295
////////////////////////////  Check if data is Number  ////////////////////////////////////
-
 
296
bool isNumber(char *res, int len)
-
 
297
{
-
 
298
    for (int i = 0; i < len; i++)
-
 
299
    {
-
 
300
        if (((res[i] < '0') || (res[i] > '9')) && (res[i] != '.' && res[i] != 0))
-
 
301
            return false;
-
 
302
    }
-
 
303
    return true;
-
 
304
}
-
 
305
 
-
 
306
////////////////////////////  Char search in Array  ////////////////////////////////////
-
 
307
int FindCharInArrayRev(char array[], char c, int len)
-
 
308
{
-
 
309
    for (int i = len - 1; i >= 0; i--)
-
 
310
    {
-
 
311
        if (array[i] == c)
-
 
312
            return i;
-
 
313
    }
-
 
314
    return -1;
-
 
315
}
-
 
316
 
-
 
317
////////////////////////////  Get the value from the Telegram  ////////////////////////////////////
-
 
318
long getValue(char *buffer, int maxlen, char startchar, char endchar)
-
 
319
{
-
 
320
    int s = FindCharInArrayRev(buffer, startchar, maxlen - 2);
-
 
321
    int l = FindCharInArrayRev(buffer, endchar, maxlen - 2) - s - 1;
-
 
322
 
-
 
323
    char res[16];
-
 
324
    memset(res, 0, sizeof(res));
-
 
325
 
-
 
326
    if (strncpy(res, buffer + s + 1, l))
-
 
327
    {
-
 
328
        if (endchar == '*')
-
 
329
        {
-
 
330
            if (isNumber(res, l))
-
 
331
                // * Lazy convert float to long
-
 
332
                return (1000 * atof(res));
-
 
333
        }
-
 
334
        else if (endchar == ')')
-
 
335
        {
-
 
336
            if (isNumber(res, l))
-
 
337
                return atof(res);
-
 
338
        }
-
 
339
    }
-
 
340
    return 0;
-
 
341
}
-
 
342
 
-
 
343
////////////////////////////  Decode Telegram  ////////////////////////////////////
-
 
344
bool decode_telegram(int len)
-
 
345
{
-
 
346
    int startChar = FindCharInArrayRev(telegram, '/', len);
-
 
347
    int endChar = FindCharInArrayRev(telegram, '!', len);
-
 
348
//    bool validCRCFound = false;
-
 
349
    bool validCRCFound = true;
-
 
350
 
-
 
351
    for (int cnt = 0; cnt < len; cnt++) {
-
 
352
        Serial.print(telegram[cnt]);
-
 
353
    }
-
 
354
//    Serial.print("\n");
-
 
355
 
-
 
356
    if (startChar >= 0)
-
 
357
    {
-
 
358
        // * Start found. Reset CRC calculation
-
 
359
        currentCRC = CRC16(0x0000,(unsigned char *) telegram+startChar, len-startChar);
-
 
360
    }
-
 
361
    else if (endChar >= 0)
-
 
362
    {
-
 
363
        // * Add to crc calc
-
 
364
        currentCRC = CRC16(currentCRC,(unsigned char*)telegram+endChar, 1);
-
 
365
 
-
 
366
        char messageCRC[5];
-
 
367
        strncpy(messageCRC, telegram + endChar + 1, 4);
-
 
368
 
-
 
369
        messageCRC[4] = 0;   // * Thanks to HarmOtten (issue 5)
-
 
370
//        validCRCFound = (strtol(messageCRC, NULL, 16) == currentCRC);
-
 
371
 
-
 
372
        if (validCRCFound)
-
 
373
            Serial.println(F("CRC Valid!"));
-
 
374
        else
-
 
375
            Serial.println(F("CRC Invalid!"));
-
 
376
 
-
 
377
        currentCRC = 0;
-
 
378
    }
-
 
379
    else
-
 
380
    {
-
 
381
        currentCRC = CRC16(currentCRC, (unsigned char*) telegram, len);
-
 
382
    }
-
 
383
 
-
 
384
    // 1-0:1.8.1(000992.992*kWh)
-
 
385
    // 1-0:1.8.1 = Elektra verbruik laag tarief (DSMR v4.0)
-
 
386
    if (strncmp(telegram, "1-0:1.8.1", strlen("1-0:1.8.1")) == 0)
-
 
387
    {
-
 
388
        CONSUMPTION_LOW_TARIF = getValue(telegram, len, '(', '*');
-
 
389
    }
-
 
390
 
-
 
391
    // 1-0:1.8.2(000560.157*kWh)
-
 
392
    // 1-0:1.8.2 = Elektra verbruik hoog tarief (DSMR v4.0)
-
 
393
    if (strncmp(telegram, "1-0:1.8.2", strlen("1-0:1.8.2")) == 0)
-
 
394
    {
-
 
395
        CONSUMPTION_HIGH_TARIF = getValue(telegram, len, '(', '*');
-
 
396
    }
-
 
397
	
-
 
398
    // 1-0:2.8.1(000560.157*kWh)
-
 
399
    // 1-0:2.8.1 = Elektra teruglevering laag tarief (DSMR v4.0)
-
 
400
    if (strncmp(telegram, "1-0:2.8.1", strlen("1-0:2.8.1")) == 0)
-
 
401
    {
-
 
402
        RETURNDELIVERY_LOW_TARIF = getValue(telegram, len, '(', '*');
-
 
403
    }
-
 
404
 
-
 
405
    // 1-0:2.8.2(000560.157*kWh)
-
 
406
    // 1-0:2.8.2 = Elektra teruglevering hoog tarief (DSMR v4.0)
-
 
407
    if (strncmp(telegram, "1-0:2.8.2", strlen("1-0:2.8.2")) == 0)
-
 
408
    {
-
 
409
        RETURNDELIVERY_HIGH_TARIF = getValue(telegram, len, '(', '*');
-
 
410
    }
183
 
411
 
-
 
412
    // 1-0:1.7.0(00.424*kW) Actueel verbruik
-
 
413
    // 1-0:1.7.x = Electricity consumption actual usage (DSMR v4.0)
-
 
414
    if (strncmp(telegram, "1-0:1.7.0", strlen("1-0:1.7.0")) == 0)
-
 
415
    {
-
 
416
        ACTUAL_CONSUMPTION = getValue(telegram, len, '(', '*');
-
 
417
    }
184
 
418
 
-
 
419
    // 1-0:2.7.0(00.000*kW) Actuele teruglevering (-P) in 1 Watt resolution
-
 
420
    if (strncmp(telegram, "1-0:2.7.0", strlen("1-0:2.7.0")) == 0)
-
 
421
    {
-
 
422
        ACTUAL_RETURNDELIVERY = getValue(telegram, len, '(', '*');
-
 
423
    }
185
 
424
 
186
// * ==========================================================================================
425
    // 1-0:21.7.0(00.378*kW)
187
// * = HIERONDER NOG NETJES MAKEN == HIERONDER NOG NETJES MAKEN == HIERONDER NOG NETJES MAKEN =
426
    // 1-0:21.7.0 = Instantaan vermogen Elektriciteit levering L1
188
// * ==========================================================================================
427
    if (strncmp(telegram, "1-0:21.7.0", strlen("1-0:21.7.0")) == 0)
189
 
428
    {
190
//MQTT_Port_String = String(MQTT_Port);
-
 
191
//sprintf(MQTT_Port_String, "%u", MQTT_Port);
-
 
192
//MQTTRemote _mqtt_remote(MQTT_Client.c_str(), MQTT_Server.c_str(), MQTT_Port, MQTT_User.c_str(), MQTT_Password.c_str(),
-
 
193
//                        {.rx_buffer_size = 2048, .tx_buffer_size = 2048, .keep_alive_s = 10});
429
        L1_INSTANT_POWER_USAGE = getValue(telegram, len, '(', '*');
-
 
430
    }
194
 
431
 
-
 
432
    // 1-0:41.7.0(00.378*kW)
-
 
433
    // 1-0:41.7.0 = Instantaan vermogen Elektriciteit levering L2
-
 
434
    if (strncmp(telegram, "1-0:41.7.0", strlen("1-0:41.7.0")) == 0)
-
 
435
    {
-
 
436
        L2_INSTANT_POWER_USAGE = getValue(telegram, len, '(', '*');
-
 
437
    }
-
 
438
 
-
 
439
    // 1-0:61.7.0(00.378*kW)
-
 
440
    // 1-0:61.7.0 = Instantaan vermogen Elektriciteit levering L3
-
 
441
    if (strncmp(telegram, "1-0:61.7.0", strlen("1-0:61.7.0")) == 0)
-
 
442
    {
-
 
443
        L3_INSTANT_POWER_USAGE = getValue(telegram, len, '(', '*');
-
 
444
    }
-
 
445
 
-
 
446
    // 1-0:31.7.0(002*A)
-
 
447
    // 1-0:31.7.0 = Instantane stroom Elektriciteit L1
-
 
448
    if (strncmp(telegram, "1-0:31.7.0", strlen("1-0:31.7.0")) == 0)
-
 
449
    {
-
 
450
        L1_INSTANT_POWER_CURRENT = getValue(telegram, len, '(', '*');
-
 
451
    }
-
 
452
    // 1-0:51.7.0(002*A)
-
 
453
    // 1-0:51.7.0 = Instantane stroom Elektriciteit L2
-
 
454
    if (strncmp(telegram, "1-0:51.7.0", strlen("1-0:51.7.0")) == 0)
-
 
455
    {
-
 
456
        L2_INSTANT_POWER_CURRENT = getValue(telegram, len, '(', '*');
-
 
457
    }
-
 
458
    // 1-0:71.7.0(002*A)
-
 
459
    // 1-0:71.7.0 = Instantane stroom Elektriciteit L3
-
 
460
    if (strncmp(telegram, "1-0:71.7.0", strlen("1-0:71.7.0")) == 0)
-
 
461
    {
-
 
462
        L3_INSTANT_POWER_CURRENT = getValue(telegram, len, '(', '*');
-
 
463
    }
-
 
464
 
-
 
465
    // 1-0:32.7.0(232.0*V)
-
 
466
    // 1-0:32.7.0 = Voltage L1
-
 
467
    if (strncmp(telegram, "1-0:32.7.0", strlen("1-0:32.7.0")) == 0)
-
 
468
    {
-
 
469
        L1_VOLTAGE = getValue(telegram, len, '(', '*');
-
 
470
    }
-
 
471
    // 1-0:52.7.0(232.0*V)
-
 
472
    // 1-0:52.7.0 = Voltage L2
-
 
473
    if (strncmp(telegram, "1-0:52.7.0", strlen("1-0:52.7.0")) == 0)
-
 
474
    {
-
 
475
        L2_VOLTAGE = getValue(telegram, len, '(', '*');
-
 
476
    }   
-
 
477
    // 1-0:72.7.0(232.0*V)
-
 
478
    // 1-0:72.7.0 = Voltage L3
-
 
479
    if (strncmp(telegram, "1-0:72.7.0", strlen("1-0:72.7.0")) == 0)
-
 
480
    {
-
 
481
        L3_VOLTAGE = getValue(telegram, len, '(', '*');
-
 
482
    }
-
 
483
 
-
 
484
    // 0-1:24.2.1(150531200000S)(00811.923*m3)
-
 
485
    // 0-1:24.2.1 = Gas (DSMR v4.0) on Kaifa MA105 meter
-
 
486
    if (strncmp(telegram, "0-1:24.2.1", strlen("0-1:24.2.1")) == 0)
-
 
487
    {
-
 
488
        GAS_METER_M3 = getValue(telegram, len, '(', '*');
-
 
489
    }
-
 
490
 
-
 
491
    // 0-0:96.14.0(0001)
-
 
492
    // 0-0:96.14.0 = Actual Tarif
-
 
493
    if (strncmp(telegram, "0-0:96.14.0", strlen("0-0:96.14.0")) == 0)
-
 
494
    {
-
 
495
        ACTUAL_TARIF = getValue(telegram, len, '(', ')');
-
 
496
    }
-
 
497
 
-
 
498
    // 0-0:96.7.21(00003)
-
 
499
    // 0-0:96.7.21 = Aantal onderbrekingen Elektriciteit
-
 
500
    if (strncmp(telegram, "0-0:96.7.21", strlen("0-0:96.7.21")) == 0)
-
 
501
    {
-
 
502
        SHORT_POWER_OUTAGES = getValue(telegram, len, '(', ')');
-
 
503
    }
-
 
504
 
-
 
505
    // 0-0:96.7.9(00001)
-
 
506
    // 0-0:96.7.9 = Aantal lange onderbrekingen Elektriciteit
-
 
507
    if (strncmp(telegram, "0-0:96.7.9", strlen("0-0:96.7.9")) == 0)
-
 
508
    {
-
 
509
        LONG_POWER_OUTAGES = getValue(telegram, len, '(', ')');
-
 
510
    }
-
 
511
 
-
 
512
    // 1-0:32.32.0(00000)
-
 
513
    // 1-0:32.32.0 = Aantal korte spanningsdalingen Elektriciteit in fase 1
-
 
514
    if (strncmp(telegram, "1-0:32.32.0", strlen("1-0:32.32.0")) == 0)
-
 
515
    {
-
 
516
        SHORT_POWER_DROPS = getValue(telegram, len, '(', ')');
-
 
517
    }
-
 
518
 
-
 
519
    // 1-0:32.36.0(00000)
-
 
520
    // 1-0:32.36.0 = Aantal korte spanningsstijgingen Elektriciteit in fase 1
-
 
521
    if (strncmp(telegram, "1-0:32.36.0", strlen("1-0:32.36.0")) == 0)
-
 
522
    {
-
 
523
        SHORT_POWER_PEAKS = getValue(telegram, len, '(', ')');
-
 
524
    }
-
 
525
 
-
 
526
    return validCRCFound;
-
 
527
}
-
 
528
 
-
 
529
void read_p1_hardwareserial()
-
 
530
{
-
 
531
    if (mySerial.available())
-
 
532
    {
-
 
533
        memset(telegram, 0, sizeof(telegram));
-
 
534
 
-
 
535
        while (mySerial.available())
-
 
536
        {
-
 
537
            int len = mySerial.readBytesUntil('\n', telegram, P1_MAXLINELENGTH);
-
 
538
 
-
 
539
            processLine(len);
-
 
540
        }
-
 
541
    }
-
 
542
}
-
 
543
 
-
 
544
void processLine(int len) {
-
 
545
    telegram[len] = '\n';
-
 
546
    telegram[len + 1] = 0;
-
 
547
    yield();
-
 
548
 
-
 
549
    bool result = decode_telegram(len + 1);
-
 
550
    if (result) {
-
 
551
        send_data_to_broker();
-
 
552
        LAST_UPDATE_SENT = millis();
-
 
553
    }
-
 
554
}
195
 
555
 
196
////////////////////////////////  SETUP  /////////////////////////////////////////
556
////////////////////////////////  SETUP  /////////////////////////////////////////
197
void setup() {
557
void setup() {
198
  Serial.begin(115200);
558
  Serial.begin(115200);
199
  button.setDebounceTime(50); // set debounce time to 50 milliseconds
559
  button.setDebounceTime(50); // set debounce time to 50 milliseconds
200
  pinMode(BTN_SAVE, INPUT_PULLUP);
560
  pinMode(BTN_SAVE, INPUT_PULLUP);
201
  pinMode(LED_BUILTIN, OUTPUT);
561
  pinMode(LED_BUILTIN, OUTPUT);
202
 
562
 
-
 
563
      // Setup a hw serial connection for communication with the P1 meter and logging (not using inversion)
-
 
564
//    Serial.begin(BAUD_RATE, SERIAL_8N1, 115200);
-
 
565
    Serial.setRxBufferSize(1024);
-
 
566
    Serial.println("");
-
 
567
    Serial.println("Swapping UART0 RX to inverted");
-
 
568
    Serial.flush();
-
 
569
 
-
 
570
    // Invert the RX serialport by setting a register value, this way the TX might continue normally allowing the serial monitor to read println's
-
 
571
    mySerial.begin(BAUD,SERIAL_8N1,RX_PIN,TX_PIN, true);
-
 
572
    Serial.println("Serial port is ready to recieve.");
-
 
573
 
203
  
574
  
204
  // FILESYSTEM INIT
575
  // FILESYSTEM INIT
205
  if (startFilesystem()){
576
  if (startFilesystem()){
206
    // Load configuration (if not present, default will be created when webserver will start)
577
    // Load configuration (if not present, default will be created when webserver will start)
207
    if (loadOptions())
578
    if (loadOptions())
Line 222... Line 593...
222
    myIP = WiFi.softAPIP();
593
    myIP = WiFi.softAPIP();
223
    captiveRun = true;
594
    captiveRun = true;
224
    LEDSpeed = 250;
595
    LEDSpeed = 250;
225
  } else {
596
  } else {
226
    LEDSpeed = 1000;
597
    LEDSpeed = 1000;
-
 
598
    captiveRun = true;
227
  }
599
  }
228
 
600
 
229
  // Add custom page handlers to webserver
601
  // Add custom page handlers to webserver
230
  server.on("/reload", HTTP_GET, handleLoadOptions);
602
  server.on("/reload", HTTP_GET, handleLoadOptions);
231
 
603
 
Line 241... Line 613...
241
  server.addOption(MQTT_CLIENT_LABEL, MQTT_Client);
613
  server.addOption(MQTT_CLIENT_LABEL, MQTT_Client);
242
  server.addOption(MQTT_SERVER_LABEL, MQTT_Server);
614
  server.addOption(MQTT_SERVER_LABEL, MQTT_Server);
243
  server.addOption(MQTT_PORT_LABEL, MQTT_Port);
615
  server.addOption(MQTT_PORT_LABEL, MQTT_Port);
244
  server.addOption(MQTT_USER_LABEL, MQTT_User);
616
  server.addOption(MQTT_USER_LABEL, MQTT_User);
245
  server.addOption(MQTT_PASSWORD_LABEL, MQTT_Password);
617
  server.addOption(MQTT_PASSWORD_LABEL, MQTT_Password);
246
  server.addOption(MQTT_TOPIC_LABEL, MQTT_Topic);
618
  server.addOption(MQTT_PREFIX_LABEL, MQTT_Prefix);
247
  server.addComment(MQTT_TOPIC_LABEL, "Restart is necessary after changing values.");
619
  server.addComment(MQTT_PREFIX_LABEL, "Restart is necessary after changing values.");
248
 
620
 
249
  // Enable ACE FS file web editor and add FS info callback function
621
  // Enable ACE FS file web editor and add FS info callback function
250
  server.enableFsCodeEditor();
622
  server.enableFsCodeEditor();
251
  #ifdef ESP32
623
  #ifdef ESP32
252
  server.setFsInfoCallback(getFsInfo);
624
  server.setFsInfoCallback(getFsInfo);
Line 269... Line 641...
269
 } else {
641
 } else {
270
    pinMode(14, INPUT);    // select on-board antenna
642
    pinMode(14, INPUT);    // select on-board antenna
271
    pinMode(3, INPUT);   // RF switch power off
643
    pinMode(3, INPUT);   // RF switch power off
272
    Serial.println("Internal antenna selected.");
644
    Serial.println("Internal antenna selected.");
273
 }
645
 }
-
 
646
 // Get and print Wifi strenght
274
 long rssi = WiFi.RSSI();
647
 long rssi = WiFi.RSSI();
275
 Serial.print("WiFi Strength (RSSI): ");
648
 Serial.print("WiFi Strength (RSSI): ");
276
 if ((rssi <= -30) && (rssi > -50)) {
649
 if ((rssi <= -30) && (rssi > -50)) {
277
   Serial.print("***** (");
650
   Serial.print("***** (");
278
   Serial.print(rssi);
651
   Serial.print(rssi);
Line 296... Line 669...
296
 } else   if ((rssi <= -90)) {
669
 } else   if ((rssi <= -90)) {
297
   Serial.print("..... (");
670
   Serial.print("..... (");
298
   Serial.print(rssi);
671
   Serial.print(rssi);
299
   Serial.print("dBm.)");
672
   Serial.print("dBm.)");
300
 }
673
 }
301
 
674
 
302
 // if (MQTT_Enabled) {
675
   // Create a unique mqttClient ID and in/out topics
303
      
-
 
304
 // }
-
 
-
 
676
  snprintf(clientId, sizeof(clientId), "ESP-%llX", ESP.getEfuseMac());
-
 
677
  snprintf(inTopic, sizeof(inTopic), "%s/input", MQTT_Prefix.c_str());
-
 
678
  snprintf(outTopic, sizeof(outTopic), "%s/output", MQTT_Prefix.c_str());
305
 
679
 
-
 
680
  Serial.print("MQTT CLiend ID: ");
306
//  if (MQTT_Enabled) {
681
  Serial.println(clientId);
307
//    _mqtt_remote.start([](bool connected) {
682
  Serial.print("Publish output topic: ");
308
//    if (connected) {
683
  Serial.println(outTopic);
-
 
684
  Serial.print("Subscribe input topic: ");
309
//      _mqtt_remote.subscribe(
685
  Serial.println(inTopic);
-
 
686
 
-
 
687
  // Set MQTT server and callback function
310
//            _mqtt_remote.publishMessageVerbose(_mqtt_remote.clientId() + "/initial_message", "oh hello!");
688
  mqttClient.setServer(MQTT_Server.c_str(), MQTT_Port.toInt());
311
//          });
689
  mqttClient.setCallback(mqttCallback);
312
//    };
-
 
313
}
690
}
314
 
691
 
315
////////////////////////////////  LOOP  /////////////////////////////////////////
692
////////////////////////////////  LOOP  /////////////////////////////////////////
316
void loop() {
693
void loop() {
317
 
694
 
-
 
695
  long now = millis();
-
 
696
 
318
  // Send ESP system time (epoch) and heap stats to WS client
697
      // Send ESP system time (epoch) and heap stats to WS client
319
  static uint32_t sendToClientTime;
698
  static uint32_t sendToClientTime;
320
  if (millis() - sendToClientTime > LEDSpeed ) {
699
  if (millis() - sendToClientTime > LEDSpeed ) {
321
    sendToClientTime = millis();
700
    sendToClientTime = millis();
322
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
701
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
323
 
702
 
Line 325... Line 704...
325
    using namespace AsyncFSWebServer;
704
    using namespace AsyncFSWebServer;
326
    CJSON::Json doc;
705
    CJSON::Json doc;
327
    doc.setBool("addPoint", true);
706
    doc.setBool("addPoint", true);
328
    doc.setNumber("timestamp", (double)now);
707
    doc.setNumber("timestamp", (double)now);
329
#ifdef ESP32
708
#ifdef ESP32
-
 
709
    ACTUAL_SUMPOWER = ACTUAL_CONSUMPTION - ACTUAL_RETURNDELIVERY;
330
    doc.setNumber("totalHeap", (double)heap_caps_get_free_size(0));
710
    doc.setNumber("ACTUAL_CONSUMPTION", (double)ACTUAL_CONSUMPTION);
331
    doc.setNumber("maxBlock", (double)heap_caps_get_largest_free_block(0));
711
    doc.setNumber("ACTUAL_RETURNDELIVERY", (double)ACTUAL_RETURNDELIVERY);
-
 
712
    doc.setNumber("ACTUAL_SUMPOWER", (double)ACTUAL_SUMPOWER);
332
#elif defined(ESP8266)
713
#elif defined(ESP8266)
333
    uint32_t free;
714
    uint32_t free;
334
    uint32_t max;
715
    uint32_t max;
335
    ESP.getHeapStats(&free, &max, nullptr);
716
    ESP.getHeapStats(&free, &max, nullptr);
336
    doc.setNumber("totalHeap", (double)free);
717
    doc.setNumber("totalHeap", (double)free);
Line 341... Line 722...
341
  }
722
  }
342
 
723
 
343
  if (captiveRun)
724
  if (captiveRun)
344
    server.updateDNS();
725
    server.updateDNS();
345
 
726
 
346
  // Savew options also on button click
727
  // Handle MQTT client
-
 
728
  if (MQTT_Enabled) {
347
  if (! digitalRead(BTN_SAVE)) {
729
    if (!mqttClient.connected()) {
-
 
730
      // Client not connected, try to reconnect every 5 seconds
348
    saveOptions();
731
      mqttReconnect();
349
    delay(1000);
732
    } else {
-
 
733
      // Client connected
-
 
734
      mqttClient.loop();
-
 
735
      // Publish a new message every 5 seconds
-
 
736
      static uint32_t lastMsgTime = millis();
-
 
737
      static uint16_t value = 0;
-
 
738
      if (millis() - lastMsgTime > 5000) {
-
 
739
        lastMsgTime = millis();
-
 
740
 
-
 
741
        char payload[64];
-
 
742
        snprintf(payload, sizeof(payload), "Hello World from %s #%d", clientId, ++value);
-
 
743
 
-
 
744
        Serial.print("Publish message: ");
-
 
745
        Serial.println(payload);
-
 
746
        mqttClient.publish(outTopic, payload);
-
 
747
        read_p1_hardwareserial();
-
 
748
      }
-
 
749
    }
350
  }
750
  }
351
 
751
 
-
 
752
// read reset button SHORT Press (>1 & <2,5 second restart, >10 seconds (led stays on factory reset))
352
  button.loop(); // MUST call the loop() function first
753
  button.loop(); // MUST call the loop() function first
353
 
754
 
354
  if (button.isPressed()) {
755
  if (button.isPressed()) {
355
    pressedTime = millis();
756
    pressedTime = millis();
356
    isPressing = true;
757
    isPressing = true;
Line 374... Line 775...
374
    if (pressDuration > LONG_PRESS_TIME) {
775
    if (pressDuration > LONG_PRESS_TIME) {
375
      server.clearConfigFile();
776
      server.clearConfigFile();
376
      ESP.restart();
777
      ESP.restart();
377
    }
778
    }
378
  }
779
  }
-
 
780
 
-
 
781
  if (now - LAST_UPDATE_SENT > UPDATE_INTERVAL) {
-
 
782
    read_p1_hardwareserial();
-
 
783
  }
379
}
784
}