JayV
Published © MIT

P1 Energy Hub

P1 energy monitoring hub with Arduino MKR - WiFi

IntermediateWork in progress4 hours5,719
P1 Energy Hub

Things used in this project

Story

Read more

Schematics

Schematics

Code

P1_demo.json

JSON
Node-Red Json setup
[{"id":"906ddf10.b3ce8","type":"http in","z":"9acd9aec.bc22d8","name":"Post /JSON","url":"/JSON","method":"post","upload":false,"swaggerDoc":"","x":210,"y":200,"wires":[["55b1a28f.66945c"]]},{"id":"55b1a28f.66945c","type":"json","z":"9acd9aec.bc22d8","name":"","property":"payload","action":"","pretty":false,"x":430,"y":200,"wires":[["2bd473e2.4d8f8c"]]},{"id":"acde231e.0561b","type":"ui_chart","z":"9acd9aec.bc22d8","name":"ActualPowerUse","group":"ff7229bb.c9d068","order":1,"width":"18","height":10,"label":"<small>Power Use Kw","chartType":"line","legend":"false","xformat":"dd HH:mm","interpolate":"cubic","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":"12","removeOlderPoints":"5000","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#e60000","#f40101","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"x":960,"y":200,"wires":[[]]},{"id":"2bd473e2.4d8f8c","type":"function","z":"9acd9aec.bc22d8","name":"ActualPower","func":"msg.payload = msg.payload.eactualuse; \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":750,"y":200,"wires":[["acde231e.0561b","999b3f10.d7076"]]},{"id":"f8f6c942.6af088","type":"comment","z":"9acd9aec.bc22d8","name":"P1 HTTP SERVER","info":"","x":230,"y":120,"wires":[]},{"id":"999b3f10.d7076","type":"debug","z":"9acd9aec.bc22d8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":950,"y":140,"wires":[]},{"id":"de98f380.0bd28","type":"http response","z":"9acd9aec.bc22d8","name":"Reply Mode","statusCode":"","headers":{},"x":750,"y":320,"wires":[]},{"id":"d2f8232c.24a1c","type":"function","z":"9acd9aec.bc22d8","name":"Push Mode","func":"// set new mode if requested\nif(msg.payload ==9 || msg.payload ==1  ) // set mode if we received number only 1 = low power 9= continues (test)\n{\n    global.set(\"P1Mode\", msg.payload );\n}\nelse  // send reponse if we require mode set\n{\n    msg.payload = global.get(\"P1Mode\");\n    global.set(\"P1Mode\", -1 );\n    return msg;    \n}\n","outputs":1,"noerr":0,"initialize":"// Code added here will be run once\n// whenever the node is deployed.\nglobal.set(\"P1Mode\", -1 );","finalize":"","x":390,"y":320,"wires":[["63641ef4.ae1ad"]]},{"id":"a801bf49.1ad07","type":"inject","z":"9acd9aec.bc22d8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"P1","payload":"9","payloadType":"num","x":190,"y":360,"wires":[["d2f8232c.24a1c"]]},{"id":"63641ef4.ae1ad","type":"template","z":"9acd9aec.bc22d8","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<! DOCTYPE html>\n<html>\n<body>\n{\"MODE\":{{payload}}}\n</body>\n</html>\n","output":"str","x":560,"y":320,"wires":[["de98f380.0bd28","fcea8db7.96bcc"]]},{"id":"fcea8db7.96bcc","type":"debug","z":"9acd9aec.bc22d8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":750,"y":380,"wires":[]},{"id":"8d80f2f.a4cf11","type":"http in","z":"9acd9aec.bc22d8","name":"Get /P1","url":"/P1","method":"get","upload":false,"swaggerDoc":"","x":190,"y":280,"wires":[["d2f8232c.24a1c"]]},{"id":"45d7e0b6.591bc","type":"inject","z":"9acd9aec.bc22d8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"P1","payload":"1","payloadType":"num","x":190,"y":320,"wires":[["d2f8232c.24a1c"]]},{"id":"ff7229bb.c9d068","type":"ui_group","name":"P1 Demo","tab":"74fdc55.0ac173c","order":2,"disp":true,"width":"24","collapse":false},{"id":"74fdc55.0ac173c","type":"ui_tab","name":"Test","icon":"dashboard","order":2,"disabled":false,"hidden":false}]

P1_Server_V1.ino

C/C++
C-code Arduino
/*
P1 Port Reader for WifiNiNa Wireless Hub
Dutch Energy Meters

App Flow:
Setup Hardware - Serial, Serial1, RTC
Setup Wifi - if no Wifi - halt !
Main loop Modes :

1 = HTTP post server (sleepmode)
9 = test mode: read & post continiously Actual Power

(c) JayFox 2020
*************************************************************/
#include <WiFiNINA.h>
#include <EasyWiFi.h>
#include <RTCZero.h>
#include <ArduinoLowPower.h>

#define DEBUG_X 1  // Debug info for messages
#define DEBUG_XX 1  // Debug info for stream data

//
//Defines
//
#define VERSION "1.1.0"               // Software verson nr
#define MAX_MISSED_DATA 2000          // MAX data missed from Client/Web HTTP reply before time-out (accept short messages only)
#define MAXBUFFER   1024              // MAX buffer size of P1 Telegram
#define P1_en_port 7                  // Enable pin - optional on Hardware print
#define P1START "/"
#define P1TEST 9
#define P1POSTNODE 1

IPAddress G_Myip;
IPAddress G_Hostip=IPAddress(192,168,200,20); // Node-Red Server
EasyWiFi MyEasyWiFi;
char MyAPName[]= {"P1Demo_AP"},MyTest[]={"JSON"}; // node-red HTTP side for Test mode
long G_Myrssi;
//
//Define RTCSettings
//
RTCZero G_rtc;                         // RTC Clock
unsigned long G_timer,G_Epoch= 1541062800UL;   // epoch time global variable, adapted by NTP routines
//
//Define P1 Settings
//
String G_P1header="/";
String G_backdoor= "P1"; // backdoor HTTP get for mode change
String G_P1error="";
char G_P1buffer[MAXBUFFER],G_Time[16],G_Date[16];
unsigned int G_P1crc=0; 
int G_P1length=0;
boolean G_P1valid = false,G_Noled = false;
struct P1_data { // /status P! port
  String header;      // /
  String etimestamp;  // 0-0:1.0.0
  String eserial;     // 0-0:96.1.1    
  String eusage1;     // 1-0:1.8.1
  String esupply1;    // 1-0:2.8.1
  String eusage2;     // 1-0:1.8.2
  String esupply2;    // 1-0:2.8.2
  String eactualuse;  // 1-0:1.7.0
  String eactualsupply; // 1-0:2.7.0 
  String epowerfailures; //  0-0:96.7.21 
  String einstantcurrent; //  1-0:31.7.0 
  String gserial; //  0-1:96.1.0
  String gtimestamp; //  0-1:24.2.1 first () -> double () used for this entry (timestamp)(gasusage)
  String gusage; //  0-1:24.2.1 second ()
  } G_Smartmeter;    

struct P1_setting {
  byte mode;                // 1byte
  IPAddress hostip;         // 4 bytes
  unsigned int hostport;    // 2 bytes
  unsigned int sleeptime;   // 2 bytes
  char topic[16];           // 16 bytes
  char login[16];           // 16 bytes  // not used
  char pass[16];            // 16 bytes  // not used
  } G_Setting;              // total 57 bytes *2 = 114 = MAXSIZE ASCII HEX-array

//
// Setup
//
void setup() {
pinMode(P1_en_port, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(P1_en_port, LOW);
Mkrled(false);

/*********** Serial SETUP  **********/
 
#if DEBUG_X
int t=10;  //Initialize serial and wait for port to open, max 10 second waiting
  Serial.begin(115200);
  while (!Serial) {
    ; delay(1000);
    if ( (t--)== 0 ) break;
  }
Serial.println("* P1 Server, serial setup, Starting Initialisation");
#endif 
/*********** RTC SETUP  **********/
G_rtc.begin();
G_rtc.disableAlarm();                         

/*********** P1 @ Serial1 SETUP  **********/
Serial1.begin(115200,SERIAL_8N1);
Serial1.flush();
G_Epoch=P1_checktime();
if (G_P1valid == false){
#if DEBUG_X
    Serial.println("* !! No P1 Port or Message !!");
#endif  
}
else {
#if DEBUG_X
    Serial.println("* P1 Port found");
#endif
}

/*********** WIFI SETUP  **********/
if (WiFi.status() == WL_NO_SHIELD) {   // check for the presence of the shield:
#if DEBUG_X
    Serial.println("* WiFi shield not present - halted");
#endif
    while (true);     // don't continue if no shield
  }
delay(1000);
#if DEBUG_X
   Serial.println("* WiFi starting...");
#endif  
MyEasyWiFi.apname(MyAPName);
MyEasyWiFi.seed(4);     // set seed for encoded storage
MyEasyWiFi.start();     // Start Wifi login 
if ( WiFi.status() != WL_CONNECTED){
#if DEBUG_X
   Serial.println("* WiFi cant connect- halted.");
#endif
    while (true);     // don't continue if no wifi
    }
G_Myip = WiFi.localIP();

//*********** Init settings for Server settings to Node-Red  **********/
  G_Setting.mode=9;
  G_Setting.hostport=1880;
  G_Setting.hostip=G_Hostip;
  G_Setting.topic[0]='J';G_Setting.topic[1]='S';G_Setting.topic[2]='O';G_Setting.topic[3]='N';G_Setting.topic[4]=0;
  G_Setting.sleeptime=1;
  
#if DEBUG_X
Serial.println("* Checking P1 Data..");
#endif  
P1_Fillstructure();P1_Poststructure(G_Setting.topic);
G_timer=G_rtc.getEpoch();

#if DEBUG_X
Serial.println("* Starting Main Program.");
#endif 
}








void loop() {
int t;

switch (G_Setting.mode) {
  case (P1TEST) :             
       Serial.println("* Test loop...");
       P1_Fillstructure();
       Serial.println(G_P1buffer);
       if (G_P1valid) 
          {
          NINAled(0,0,8) ; // turn blue
          P1_Poststructure(MyTest);
          }
       else NINAled(8,0,0) ; // turn red
       delay(500);
       break;
  case (P1POSTNODE) :            
#if DEBUG_X
       Serial.print("* PostServer: Good Night, sleeping for ");Serial.print(G_Setting.sleeptime);Serial.println(" minute(s)..");
       Serial.end();
#endif
       WiFi.end();WiFi.lowPowerMode();
       Serial1.end();
       NINAled(0,0,0) ; // turn off
       t=G_Setting.sleeptime*60000;
       LowPower.deepSleep(t);
       // *************************************  at HTTP Sleep ******************************
#if DEBUG_X
      Serial.begin(115200);delay(1000);
      Serial.println("* I'll be back ..");
#endif   
      G_rtc.begin();
      Serial1.begin(115200,SERIAL_8N1);
      WiFi.noLowPowerMode();  // turn off low power wifi
      MyEasyWiFi.start();     // Start Wifi login 
      G_Epoch=P1_checktime();
      NINAled(8,0,8) ; // turn led purple
      P1_Fillstructure();
      P1_Poststructure(G_Setting.topic);
      break;
  default :
      break; 
    } // end Switch           
} // end main loop


/***************** P1 Routines ****************************/

boolean P1_Fillstructure()
{
int pos=0;
// Parse meter data into G_Smartmeter Structure
P1_dump(G_P1buffer,&G_P1length,&G_P1crc);       // load buffer into Global Memory variables
if (G_P1valid )                                       // if there is a valif buffer, start parsing
  {
  P1_parse_item(G_P1buffer,pos,&pos,"0-0:1.0.0",&(G_Smartmeter.etimestamp) ); 
  P1_parse_item(G_P1buffer,pos,&pos,"0-0:96.1.1",&(G_Smartmeter.eserial) ); 
  P1_parse_item(G_P1buffer,pos,&pos,"1-0:1.8.1",&(G_Smartmeter.eusage1) ); 
  P1_parse_item(G_P1buffer,pos,&pos,"1-0:2.8.1",&(G_Smartmeter.esupply1) ); 
  P1_parse_item(G_P1buffer,pos,&pos,"1-0:1.8.2",&(G_Smartmeter.eusage2) );
  P1_parse_item(G_P1buffer,pos,&pos,"1-0:2.8.2",&(G_Smartmeter.esupply2) ); 
  P1_parse_item(G_P1buffer,pos,&pos,"1-0:1.7.0",&(G_Smartmeter.eactualuse) );
  P1_parse_item(G_P1buffer,pos,&pos,"1-0:2.7.0",&(G_Smartmeter.eactualsupply) );
  P1_parse_item(G_P1buffer,pos,&pos,"0-0:96.7.21",&(G_Smartmeter.epowerfailures) ); 
  P1_parse_item(G_P1buffer,pos,&pos,"1-0:31.7.0",&(G_Smartmeter.einstantcurrent) ); 
  P1_parse_item(G_P1buffer,pos,&pos,"0-1:96.1.0",&(G_Smartmeter.gserial) ); 
  P1_parse_item(G_P1buffer,pos,&pos,"0-1:24.2.1",&(G_Smartmeter.gtimestamp) );  // EXCEPTION WITH DOUBLE INFO
  G_Smartmeter.gusage="";G_Smartmeter.gusage.concat(G_Smartmeter.gtimestamp.substring(13,G_Smartmeter.gtimestamp.length()) );
  G_Smartmeter.gtimestamp.remove(13,G_Smartmeter.gtimestamp.length()-13);
#if DEBUG_XX
    Serial.print("\nTime: ");Serial.println(G_Smartmeter.etimestamp);
    Serial.print("Header: ");Serial.println(G_Smartmeter.header);
    Serial.print("e-Serial: ");Serial.println(G_Smartmeter.eserial);
    Serial.print("ActualUse: ");Serial.println(G_Smartmeter.eactualuse);
    Serial.print("e-Usage1: ");Serial.println(G_Smartmeter.eusage1);
    Serial.print("e-Usage2: ");Serial.println(G_Smartmeter.eusage2);
    Serial.print("Failures: ");Serial.println(G_Smartmeter.epowerfailures);
    Serial.print("GasSerial: ");Serial.println(G_Smartmeter.gserial);
    Serial.print("GasTimestamp: ");Serial.println(G_Smartmeter.gtimestamp);
    Serial.print("GasUsage: ");Serial.println(G_Smartmeter.gusage);
#endif
    return(1);
    }
else return(0);
} // end P1 functiuon


// Check Serial P1 and set time of the global RTC
unsigned long P1_checktime()
{
String h;  
P1_dump(G_P1buffer,&G_P1length,&G_P1crc);       // load buffer into Global Memory variables

if (G_P1valid )  // if P1 buffer is valid
  { 
  int t;
   P1_parse_item(G_P1buffer,0,&t,"0-0:1.0.0",&(G_Smartmeter.etimestamp));     // Time-content is 201210211313W = YYMMDDHHMMSSW
    t= 2000+ (G_Smartmeter.etimestamp[0]-48)*10 + G_Smartmeter.etimestamp[1]-48;
    G_rtc.setYear(t);
    t= (G_Smartmeter.etimestamp[2]-48)*10 + G_Smartmeter.etimestamp[3]-48;
    G_rtc.setMonth(t);
    t= (G_Smartmeter.etimestamp[4]-48)*10 + G_Smartmeter.etimestamp[5]-48;
    G_rtc.setDay(t);
    t= (G_Smartmeter.etimestamp[6]-48)*10 + G_Smartmeter.etimestamp[7]-48;
    G_rtc.setHours(t);
    t= (G_Smartmeter.etimestamp[8]-48)*10 + G_Smartmeter.etimestamp[9]-48;
    G_rtc.setMinutes(t);
    t= (G_Smartmeter.etimestamp[10]-48)*10 + G_Smartmeter.etimestamp[11]-48;
    G_rtc.setSeconds(t);
#if DEBUG_X
    Serial.println("* Time set");
#endif  
   }

return(G_rtc.getEpoch()); // return Epoch time old or new
     
}

// Parse Start item in buffer and return content "[header]([item])", start parse at position from, post back last position
boolean P1_parse_item(char*buff,int from,int *last,String header,String *item)
{
String telegramLine = ""; 
char c;
int ct,pos=from;
boolean line_complete=false;
boolean  message_error = false;
while( !line_complete && !message_error && G_P1valid)
  {
  if (buff[pos]!=0) 
    {
    c= buff[pos++]; //Serial.print(c);
    telegramLine+=c;
    if (telegramLine.endsWith(header)) 
        { //Serial.print("Item found"); 
          telegramLine = "";
          pos++; // read the "("
          line_complete=false;
          while ( !line_complete )   
                {
                  if(buff[pos]==0){message_error=true; break; } //escape when end of buffer is reached
                  c=buff[pos++]; 
                  if(c!=')') telegramLine+=c; 
                  else line_complete=true;
                  }
#if DEBUG_X
           Serial.print("* Parsed item [");Serial.print(telegramLine);Serial.println("]");
#endif
        } // end found item-header  

        }  
    else  message_error=true; // end of buffer reached
       
    if (header.endsWith("0-1:24.2.1") && line_complete==true) // EXCEPTION FOR GAS INFO: Double info (xxx)(yyyy)
    {
          pos++; // read the 2nd "("
          line_complete=false;
          while ( !line_complete )   
                {
                 if (Serial1.available())
                  { if(buff[pos]==0){message_error=true; break; } //escape when end of buffer is reached
                  c=buff[pos++];
                  if(c!=')') telegramLine+=c; 
                  else line_complete=true;}
                  }
    }    
    if (c == '\r') {telegramLine = "";}  // end of line
    if (c == '!')  {message_error=true; } // end of Telegram, no item found

  }
if (message_error == false && G_P1valid)
{
 *item = "";
(*item).concat(telegramLine);  // write item date
*last=pos-1;                   // write back last position
return (true);
}
else return(false);
}


// Parse Start of Serial1 stream and dump data into buffer, return length -
boolean P1_dump(char *b,int *l, unsigned int *p_crc)
{
char c,*buffer,bcrc[4];
long t=0,timer;
// Parsing Flags
boolean message_start=false;
boolean message_end=false;
boolean  message_error = false;
G_P1error="";
// initialise counter and string buffer
buffer=b;
timer=G_rtc.getEpoch();
delay(1000); // short delay for repititive reads
digitalWrite(P1_en_port, HIGH); Mkrled(true);
delay(1000); // short delay for repititive reads
Serial1.flush();
while (!message_end && !message_error) // find message end
  {
  if (G_rtc.getEpoch()-timer > 25000) {message_error=true; G_P1error="Time out";break;} //takes too lonm > 25s, should be in a message every 10 seconds
  if (Serial1.available()) 
    {
    c= Serial1.read(); 
    if (c == '/')  { message_start=true; break;}  //found the end
    }
  }
if(!message_error)
  {
#if DEBUG_X
  Serial.print("* Dump P1, found start, parsing, ");
#endif
  message_end=false;message_error=false;t=0;buffer[t++]='/'; //Serial.print(c);
  while (!message_end && !message_error) // find message end or error
    {
      if (Serial1.available()) 
        {
        c=Serial1.read(); //Serial.print(c);
        buffer[t++]=c;                             // fill buffer, calcualte crc16
        if (t>MAXBUFFER ){message_error=true; G_P1error="Max buffer"; break;}       // check max buffer
        if (c == '!') { message_end=true; break;}  //check end of telegrtam '!' 
        }
    } // while end
   buffer[t]=0; *l=t-1;        // close buffer, set length  
   P1_bufcrc16(buffer, p_crc);
   //read CRC
           while(! Serial1.available()) ; // wait for next char
           bcrc[0]=Serial1.read(); // read the CRC
           while(! Serial1.available()) ; // wait for next char
           bcrc[1]=Serial1.read(); // read the CRC
           while(! Serial1.available()) ; // wait for next char
           bcrc[2]=Serial1.read(); // read the CRC
           while(! Serial1.available()) ; // wait for next char
           bcrc[3]=Serial1.read(); // read the CRC
           bcrc[4]=0;
           if(*p_crc == hexstringtoint(bcrc) ) {G_P1valid=true;}
           else {message_error=true;G_P1error="CRC error";G_P1valid=false;}
#if DEBUG_X
Serial.print("Size=[");Serial.print(*l);Serial.print("], crc=[");Serial.print(bcrc);Serial.print("]");
Serial.print("vs CRC=[");Serial.print(*p_crc,HEX);Serial.print("], = ");Serial.println(G_P1valid);
#endif   
  }

if(message_error)
    {
    buffer[0]=0; *l=0;G_P1valid=false;
#if DEBUG_X
    Serial.print("* P1 Telegram is invalid: ");Serial.println(G_P1error);
#endif   
    }
else
   {
    G_P1error="";G_P1valid=true;  
    }
digitalWrite(P1_en_port, LOW); Mkrled(false);
return (!message_error);  // 1 = ok, 0 = error
}


// CRC16 calculator : ca lcrc of whole buffer (end character = zero)
void P1_bufcrc16(char *b,unsigned int *crc)
{
  unsigned int t,i,tmp;
  tmp=0;t=0;
  while(b[t]!=0)
  {
  tmp ^=  (unsigned int) b[t];
  for (i = 0; i < 8; i++)
    {
    if ((tmp & 0x0001) == 0x0001) tmp = (tmp >> 1) ^ 0xA001;
    else tmp >>= 1;
    }
   t++;
  }
  *crc = tmp;    
}

// hex String to integer, assumes end of sting is zero (0) and max converstion is 4 bytes (8 characters)
unsigned int hexstringtoint(char *b)
{
 int i,l,m=1;
 unsigned int t=0;
 for(i=0;i<8;++i) if(b[i]==0) {l=i-1;i=8;} // caclualte length of hex string
 for(i=l;i>=0;--i){
    if(b[i]>=65 && b[i]<=70 ) t=t+(b[i]-55)*m;
    if(b[i]>=48 && b[i]<=57 ) t=t+(b[i]-48)*m;
  m=m*16;
  }
#if DEBUG_X
//Serial.print("* Hex$_to_Int Input [");Serial.print(b);Serial.print("], Output=[");Serial.print(t,HEX);Serial.println("]");
#endif  
return t;  
}


boolean P1_convertunit(String s1, float *val, String *un)
{
String tt;
byte t,l=0;  
for(t=1;t<128;++t)
  {
   if (s1[t] == '*') l=t;  // calculate index for *
  }
if(l==0) return(0);
tt="";
tt.concat(  s1.substring(0,l) );
*(val)=tt.toFloat();
*un="";
(*un).concat(  s1.substring(l+1,s1.length()) );
return(1);
}


boolean P1_buildpayload(String *payloadstring)
{
String s2,s;
float f;
if(G_P1valid) // check valid payload;
{
  s="{";
  if(G_P1valid == true) s+="\"p1\":true,";
  else s+="\"p1\":false,";
  s+="\"header\":\"";s+=G_Smartmeter.header;s+="\",";
  s+="\"etime\":\"";s+=G_Smartmeter.etimestamp;s+="\",";
  s+="\"eserial\":\"";s+=G_Smartmeter.eserial;s+="\",";
    P1_convertunit(G_Smartmeter.eusage1, &f, &s2);
  s+="\"eusageunit\":\"";s+=s2;s+="\",";
  s+="\"eusage1\":";s+=f;s+=",";
    P1_convertunit(G_Smartmeter.esupply1, &f, &s2);
  s+="\"esupply1\":";s+=f;s+=",";
     P1_convertunit(G_Smartmeter.eusage2, &f, &s2);
  s+="\"eusage2\":";s+=f;s+=",";
    P1_convertunit(G_Smartmeter.esupply2, &f, &s2);
  s+="\"esupply2\":";s+=f;s+=",";
    P1_convertunit(G_Smartmeter.eactualuse, &f, &s2);
  s+="\"eactualunit\":\"";s+=s2;s+="\",";
  s+="\"eactualuse\":";s+=f;s+=",";
    P1_convertunit(G_Smartmeter.eactualsupply, &f, &s2);
  s+="\"eactualsupply\":";s+=f;s+=",";
  s+="\"efailures\":";s+=G_Smartmeter.epowerfailures.toInt();s+=",";
    P1_convertunit(G_Smartmeter.einstantcurrent, &f, &s2);  
  s+="\"eiunit\":\"";s+=s2;s+="\",";
  s+="\"eicurrent\":";s+=f,3;s+=",";
  s+="\"gserial\":\"";s+=G_Smartmeter.gserial;s+="\",";
  s+="\"gtime\":\"";s+=G_Smartmeter.gtimestamp;s+="\",";
    P1_convertunit(G_Smartmeter.gusage, &f, &s2);  
  s+="\"gunit\":\"";s+=s2;s+="\",";  
  s+="\"gusage\":";s+=f;s+="";  
  s+="}";
  *payloadstring = "";        // set payload to empty
  (*payloadstring).concat(s); // copy build string into payload
  return(1);
}
else { *payloadstring = "";return(0);} // no valid payload
}

// HTTP /POST function with /GET readback for mode changes
boolean P1_Poststructure(char *suburl)
{
String s;
char c;
long unsigned timer;
G_Myip = WiFi.localIP();
P1_buildpayload(&s);
WiFiClient client1,client2;
  if (client1.connect(G_Setting.hostip,G_Setting.hostport)){
#if DEBUG_X
      Serial.print("* Connected to server ");Serial.print(G_Setting.hostip);Serial.print(":");Serial.println(G_Setting.hostport);
#endif
      client1.print("POST /");client1.print(suburl);client1.println(" HTTP/1.1");
      client2.print("Host: http://"); client2.println(G_Myip);
//      client1.println("Content-type: application/json"); // does not work at Node-red, fucks up
      client1.print("content-length: ");client1.println(s.length());
      client1.println("Connection: close");
      client1.println();
      client1.println(s);
      client1.println();
      Serial.println("* HTTP-Post DataSend");  
      client1.stop();
      delay(1000); // wait 1 second
  if (client2.connect(G_Setting.hostip,G_Setting.hostport)){
      client2.print("GET /");client2.print(G_backdoor);client2.println(" HTTP/1.1");
      client2.print("Host: http://"); client2.println(G_Myip);
      client2.println("Connection: close");
      client2.println();
      Serial.print("* HTTP-Get DataSend for ");Serial.println(G_backdoor);
      s="";
      timer =G_rtc.getEpoch();
      while (client2.connected()) {           // loop while the client's connected
      if (client2.available()) {             // if there's bytes to read from the client,
         c = client2.read();  // Serial.print(c); 
         s=s+c; 
         if(s.endsWith("{\"MODE\":") ) // parse JSON MODE
             {
             c = client2.read(); // Serial.print(c);
             if (c=='0' || c=='9' || c=='1') { // only mode 0 of mode 9 accepter (Server or Test)
                G_Setting.mode = (byte) c-48;
#if DEBUG_X    
      Serial.print("* HTTP-Get found new mode ");Serial.println(G_Setting.mode);
#endif          
                }
             break;
             }
        if(s.length()>512) break;
        }
      if (G_rtc.getEpoch() - timer > 25000) break;  // break after 5 sec no resonse
      }
  }        
      client2.stop();
      return(1);   
  }else{
#if DEBUG_X    
      Serial.println("* Connection to server failed");
#endif    
     return(0);  
  }

}


// MKR1010 RGB Led via NINA module
void NINAled(char r, char g, char b)
{
 if (!G_Noled) 
  {
  // Set LED pin modes to output
  WiFiDrv::pinMode(25, OUTPUT);
  WiFiDrv::pinMode(26, OUTPUT);
  WiFiDrv::pinMode(27, OUTPUT);
  
  // Set all LED color 
  WiFiDrv::analogWrite(25, g%128);    // GREEN
  WiFiDrv::analogWrite(26, r%128);    // RED
  WiFiDrv::analogWrite(27, b%128);    // BLUE
  }
}

void Mkrled(boolean s)
{
  if(s==true) digitalWrite(LED_BUILTIN, HIGH);
  else digitalWrite(LED_BUILTIN, LOW);
}

EasyWiFi Library

Credits

JayV
29 projects • 34 followers
Silicon crazy for profession, silicon do-it-yourselves at Home.
Contact

Comments

Please log in or sign up to comment.