// #include #include #include #include #include #include #include #include "CRC16.h" //===Change values from here=== const char* ssid = "WIFISSID"; const char* password = "PASSWORD"; const char* hostName = "ESPP1Meter"; const char* domoticzIP = "192.168.1.35"; const int domoticzPort = 8090; const int domoticzGasIdx = 291; const int domoticzEneryIdx = 294; const bool outputOnSerial = true; //===Change values to here=== // Vars to store meter readings long mEVLT = 0; //Meter reading Electrics - consumption low tariff long mEVHT = 0; //Meter reading Electrics - consumption high tariff long mEOLT = 0; //Meter reading Electrics - return low tariff long mEOHT = 0; //Meter reading Electrics - return high tariff long mEAV = 0; //Meter reading Electrics - Actual consumption long mEAT = 0; //Meter reading Electrics - Actual return long mGAS = 0; //Meter reading Gas long prevGAS = 0; #define MAXLINELENGTH 128 // longest normal line is 47 char (+3 for \r\n\0) char telegram[MAXLINELENGTH]; #define SERIAL_RX D5 // pin for SoftwareSerial RX SoftwareSerial mySerial(SERIAL_RX, -1, true, MAXLINELENGTH); // (RX, TX. inverted, buffer) unsigned int currentCRC=0; void SendToDomoLog(char* message) { char url[512]; sprintf(url, "http://%s:%d/json.htm?type=command¶m=addlogmessage&message=%s", domoticzIP, domoticzPort, message); } void setup() { Serial.begin(115200); Serial.println("Booting"); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.waitForConnectResult() != WL_CONNECTED) { Serial.println("Connection Failed! Rebooting..."); delay(5000); ESP.restart(); } mySerial.begin(115200); // Port defaults to 8266 // ArduinoOTA.setPort(8266); // Hostname defaults to esp8266-[ChipID] ArduinoOTA.setHostname(hostName); // No authentication by default // ArduinoOTA.setPassword((const char *)"123"); ArduinoOTA.onStart([]() { Serial.println("Start"); }); ArduinoOTA.onEnd([]() { Serial.println("\nEnd"); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }); ArduinoOTA.onError([](ota_error_t error) { Serial.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); else if (error == OTA_END_ERROR) Serial.println("End Failed"); }); ArduinoOTA.begin(); Serial.println("Ready"); Serial.print("IP address: "); Serial.println(WiFi.localIP()); } bool SendToDomo(int idx, int nValue, char* sValue) { HTTPClient http; bool retVal = false; char url[255]; sprintf(url, "http://%s:%d/json.htm?type=command¶m=udevice&idx=%d&nvalue=%d&svalue=%s", domoticzIP, domoticzPort, idx, nValue, sValue); Serial.printf("[HTTP] GET... URL: %s\n",url); http.begin(url); //HTTP int httpCode = http.GET(); // httpCode will be negative on error if (httpCode > 0) { // HTTP header has been send and Server response header has been handled Serial.printf("[HTTP] GET... code: %d\n", httpCode); // file found at server if (httpCode == HTTP_CODE_OK) { String payload = http.getString(); retVal = true; } } else { Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); } http.end(); return retVal; } void UpdateGas() { //sends over the gas setting to domoticz if(prevGAS!=mGAS) { char sValue[10]; sprintf(sValue, "%d", mGAS); if(SendToDomo(domoticzGasIdx, 0, sValue)) prevGAS=mGAS; } } void UpdateElectricity() { char sValue[255]; sprintf(sValue, "%d;%d;%d;%d;%d;%d", mEVLT, mEVHT, mEOLT, mEOHT, mEAV, mEAT); SendToDomo(domoticzEneryIdx, 0, sValue); } bool isNumber(char* res, int len) { for (int i = 0; i < len; i++) { if (((res[i] < '0') || (res[i] > '9')) && (res[i] != '.' && res[i] != 0)) { return false; } } return true; } int FindCharInArrayRev(char array[], char c, int len) { for (int i = len - 1; i >= 0; i--) { if (array[i] == c) { return i; } } return -1; } long getValidVal(long valNew, long valOld, long maxDiffer) { //check if the incoming value is valid if(valOld > 0 && ((valNew - valOld > maxDiffer) && (valOld - valNew > maxDiffer))) return valOld; return valNew; } long getValue(char* buffer, int maxlen) { int s = FindCharInArrayRev(buffer, '(', maxlen - 2); if (s < 8) return 0; if (s > 32) s = 32; int l = FindCharInArrayRev(buffer, '*', maxlen - 2) - s - 1; if (l < 4) return 0; if (l > 12) return 0; char res[16]; memset(res, 0, sizeof(res)); if (strncpy(res, buffer + s + 1, l)) { if (isNumber(res, l)) { return (1000 * atof(res)); } } return 0; } bool decodeTelegram(int len) { //need to check for start int startChar = FindCharInArrayRev(telegram, '/', len); int endChar = FindCharInArrayRev(telegram, '!', len); bool validCRCFound = false; if(startChar>=0) { //start found. Reset CRC calculation currentCRC=CRC16(0x0000,(unsigned char *) telegram+startChar, len-startChar); if(outputOnSerial) { for(int cnt=startChar; cnt=0) { //add to crc calc currentCRC=CRC16(currentCRC,(unsigned char*)telegram+endChar, 1); char messageCRC[5]; strncpy(messageCRC, telegram + endChar + 1, 4); messageCRC[4]=0; //thanks to HarmOtten (issue 5) if(outputOnSerial) { for(int cnt=0; cnt