1

I'm trying to read data being transferred via Infrared from my Smartmeter on my ESP8266 using the following sketch:

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPUpdateServer.h>
#include <Ticker.h>
#include <AsyncMqttClient.h>

#ifndef STASSID #define STASSID "mySSID" #define STAPSK "myPassword" #endif

#ifndef MQTT_HOST #define MQTT_HOST IPAddress(192, 168, 0, 100) #define MQTT_PORT 1883 #endif

#ifndef IR #define SerialDebug Serial1 #define IR Serial #endif

AsyncMqttClient mqttClient; Ticker mqttReconnectTimer;

WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiDisconnectHandler; Ticker wifiReconnectTimer;

const char* host = "esp8266-webupdate";

const byte firstByte = 0x7E; const byte lastByte = 0x7E;

uint8_t i;

ESP8266WebServer httpServer(80); ESP8266HTTPUpdateServer httpUpdater;

void connectToWifi() { SerialDebug.println("Connecting to WiFi ..."); WiFi.begin(STASSID, STAPSK); }

void connectToMqtt() { SerialDebug.println("Connecting to MQTT ..."); mqttClient.connect(); }

void onWifiConnect(const WiFiEventStationModeGotIP& event) { SerialDebug.println("Connected to Wi-Fi."); connectToMqtt(); }

void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) { SerialDebug.println("Disconnected from Wi-Fi."); mqttReconnectTimer.detach(); wifiReconnectTimer.once(2, connectToWifi); }

void onMqttConnect(bool sessionPresent) { SerialDebug.println("Connected to MQTT."); SerialDebug.print("Session present: "); SerialDebug.println(sessionPresent); }

void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) { SerialDebug.println("Disconnected from MQTT.");

if (WiFi.isConnected()) { mqttReconnectTimer.once(2, connectToMqtt); } }

void array_to_string(byte array[], unsigned int len, char buffer[]) { for (unsigned int i = 0; i < len; i++) { byte nib1 = (array[i] >> 4) & 0x0F; byte nib2 = (array[i] >> 0) & 0x0F; buffer[i*2+0] = nib1 < 0xA ? '0' + nib1 : 'A' + nib1 - 0xA; buffer[i*2+1] = nib2 < 0xA ? '0' + nib2 : 'A' + nib2 - 0xA; } buffer[len*2] = '\0'; }

void setup() {

SerialDebug.begin(115200); IR.begin(9600); SerialDebug.println(); SerialDebug.println("Booting Sketch...");

wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect); wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);

mqttClient.onConnect(onMqttConnect); mqttClient.onDisconnect(onMqttDisconnect); mqttClient.setServer(MQTT_HOST, MQTT_PORT);

connectToWifi();

httpUpdater.setup(&httpServer); httpServer.begin();

mqttClient.setWill("smartmeter/online", 0, true, "no"); }

void loop() { httpServer.handleClient();

uint32_t timeout = 2000;

int readCnt = 0; uint32_t start_time = millis(); byte tempChar = 0; byte *readMessage; uint32_t messageLen = 0;

while ((tempChar != 0x7E) && (millis() - start_time < timeout)) { if (IR.available()) { tempChar = IR.read(); } }

start_time = millis(); timeout = 1000; bool done = false;

if (tempChar == firstByte) { // if first byte == 0x7E while ((millis() - start_time) < timeout && !done) { if (IR.available()) { tempChar = IR.read(); // second byte must be 0xA0 if(tempChar == 0xA0) { while ((millis() - start_time) < timeout && !done) { if (IR.available()) { tempChar = IR.read(); // 3rd byte tells the legth of the message

          readMessage = new byte[tempChar+2];
          memset(readMessage, 0, tempChar+2);
          readMessage[0] = firstByte;
          readMessage[1] = 0xA0;
          readMessage[2] = tempChar;
          messageLen = ((uint32_t)(tempChar))+2;
          readCnt = 3;

          while ( readCnt &lt; messageLen &amp;&amp; ((millis() - start_time) &lt; timeout)) { // minimum len 120 chars for 0x7E format
            if (IR.available()) {
              readMessage[readCnt] = IR.read(); 
              readCnt++; 

              if(readCnt == tempChar+2 &amp;&amp; readMessage[readCnt-1] != lastByte) { // correct len but last byte not 0x7E
                done = true;
                SerialDebug.printf(&quot;Wrong end byte found - %d\n&quot;, readMessage[readCnt-1]);
              } else if(readCnt == tempChar+2) { // correct len and correct last byte
                done = true;
                char str[251] = &quot;&quot;;
                array_to_string(readMessage, readCnt, str);
                mqttClient.publish(&quot;smartmeter/raw&quot;, 0, false, str);
              }
            }
          }
        }
      }
    }
  }
}

} mqttClient.publish("smartmeter/online", 0, true, "yes"); char heap[6] = ""; itoa(ESP.getFreeHeap(), heap, 10); mqttClient.publish("smartmeter/freeHeap", 0, false, heap); }

I'm getting the encoded HEX-data published on my MQTT Topic as desired, the outputs length is 250 characters long (= 125 Bytes) which is correct:

7ea07bcf000200231362b1e6e700db08534d536770075f626120000e32e62addedaede38e64c8c3173035a0a853851a28efc57f7fd76a9df59dbb152f796939328ff0f28df7f257d20b5cb2a458c4eb9188e2c1c251701c891244d859ed9c159714bb4451c090d9b1ed3bbb1fc89785ebafbf59ec4f9d540eb4c90d47e

As I found out, the ESP's heap is decreasing by 100-300 by each iteration of the loop (data is being transmitted every second via Infrared from the power-grid Smartmeter) until the ESP will eventually be rebooted by the watchdog after like 5-8 minutes.

I explicitly did not use String variables in the sketch but I legit cannot find the reason for the memory leak. Tried turning off wifi, webserver and mqtt one after each other which didn't actually made a difference.

The heap-size stays at a constant level though when there is no data being received via the Infrared serial port, so I imagine something is fishy when storing the data in the byte array "readMessage".

Anything obvious that immediately pops into someones eye that I missed?

Michel Keijzers
  • 13,014
  • 7
  • 41
  • 58
1_am_r00t
  • 21
  • 2

1 Answers1

2

You do a new inside the loop

 readMessage = new byte[tempChar+2];

which causes the heap to be filled with tempChar+2 bytes, but you never delete this.

Try reusing this memory (making it a local, or make it 'dirty' global).

Probably (not tested) the above line can be rewritten as:

byte readMessage[tempChar+2];
Michel Keijzers
  • 13,014
  • 7
  • 41
  • 58