From 32b4547d3fe8db7c00663862bdefdd367f60a8d5 Mon Sep 17 00:00:00 2001 From: Jan ten Hove Date: Thu, 28 Jan 2016 19:38:51 +0100 Subject: [PATCH] Initial code commit --- CRC16.h | 28 +++++ P1Meter.ino | 300 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 328 insertions(+) create mode 100644 CRC16.h create mode 100644 P1Meter.ino diff --git a/CRC16.h b/CRC16.h new file mode 100644 index 0000000..89c40fa --- /dev/null +++ b/CRC16.h @@ -0,0 +1,28 @@ +#ifndef CRC16_H +#define CRC16_H + +#if defined(ARDUINO) && ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +unsigned int CRC16(unsigned int crc, unsigned char *buf, int len) +{ + for (int pos = 0; pos < len; pos++) + { + crc ^= (unsigned int)buf[pos]; // XOR byte into least sig. byte of crc + + for (int i = 8; i != 0; i--) { // Loop over each bit + if ((crc & 0x0001) != 0) { // If the LSB is set + crc >>= 1; // Shift right and XOR 0xA001 + crc ^= 0xA001; + } + else // Else LSB is not set + crc >>= 1; // Just shift right + } + } + + return crc; +} +#endif diff --git a/P1Meter.ino b/P1Meter.ino new file mode 100644 index 0000000..5d76705 --- /dev/null +++ b/P1Meter.ino @@ -0,0 +1,300 @@ +#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 64 // 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[4]; + strncpy(messageCRC, telegram + endChar + 1, 4); + if(outputOnSerial) + { + for(int cnt=0; cnt