emma controller code in production board v1
Dependencies: ADE7758_v1 Crypto DHT11 MQTT MbedJSONValueEmma SDFileSystem TFT_ILI9341 SWSPI SetRTC TFT_fonts Touch W5500Interface mbed-rtos mbed-src SoftSerial
Fork of emma_controller_energy by
Diff: emmaCode.cpp
- Revision:
- 49:d11a1914ee8b
- Parent:
- 48:053e92b6dc1e
- Child:
- 50:50d98fe6cc15
--- a/emmaCode.cpp Tue Sep 01 11:52:52 2015 +0000 +++ b/emmaCode.cpp Thu Sep 03 07:10:35 2015 +0000 @@ -54,6 +54,7 @@ string proxySERVER; string proxyPORT; string proxyAUTH; +int powerPHASE; //nodes settings class NODES { @@ -295,6 +296,7 @@ /*start emma read settings*/ void emmaReadSettings(void) { char s[64]; + string str; DBG.baud(19200); DBG.printf("\r\nemmaReadSettings\r\n"); @@ -342,6 +344,9 @@ DBG.printf("wifiSSID:%s\r\n",wifiSSID.c_str()); wifiPASS = readSetting("wifiPASS"); DBG.printf("wifiPASS:%s\r\n",wifiPASS.c_str()); + str = readSetting("powerPHASE"); + sscanf(str.c_str(),"%d",&powerPHASE); + DBG.printf("powerPHASE:%d\r\n",powerPHASE); } /*end emma read settings*/ @@ -363,8 +368,8 @@ //check available interface isEthAvailable(); //check whether cable is connected - //wifiAvailable = true; //wifi module will always on the board - wifiAvailable = false; //for testing purpose + wifiAvailable = true; //wifi module will always on the board + gprsAvailable = true; //gprs module will always on the board DBG.printf("eth:%d\r\n",ethAvailable); @@ -1031,7 +1036,7 @@ //register sscanf(restPORT.c_str(),"%d",&connPort); connBodyLen = sprintf(connBody,"{\"uid\":\"%s\",\"hmac\":\"%s\"}",emmaUID.c_str(),hmac.c_str()); - sprintf(s,"POST /emma/api/controller/register HTTP/1.1\nHost: %s:%d\nContent-Length: %d\n\n%s\n\n%c",restSERVER.c_str(),connPort,connBodyLen,connBody,26); + sprintf(s,"POST /%s/api/controller/register HTTP/1.1\nHost: %s:%d\nContent-Length: %d\n\n%s\n\n%c",appNAME.c_str(),restSERVER.c_str(),connPort,connBodyLen,connBody,26); while(!emmaGetRegKey) { str = gprsREST(restSERVER,connPort,s); @@ -1085,7 +1090,7 @@ //verify registration connBodyLen = sprintf(connBody,"{\"uid\":\"%s\",\"registrationKey\":\"%s\",\"hmac\":\"%s\"}",emmaUID.c_str(),regKey.c_str(),hmac.c_str()); - sprintf(s,"POST /emma/api/controller/verify HTTP/1.1\nHost: %s:%d\nContent-Length: %d\n\n%s\n\n%c",restSERVER.c_str(),connPort,connBodyLen,connBody,26); + sprintf(s,"POST /%s/api/controller/verify HTTP/1.1\nHost: %s:%d\nContent-Length: %d\n\n%s\n\n%c",appNAME.c_str(),restSERVER.c_str(),connPort,connBodyLen,connBody,26); while(!emmaRegistered && loop < 12) { str = gprsREST(restSERVER,connPort,s); DBG.printf("rsp vrf:%s\r\n",str.c_str()); @@ -1268,7 +1273,7 @@ tNodes.start(); wait(1); while(1) { - checkVoltagePower(); //need revision to support ethernet + checkVoltagePower(); //set allowAlertXxxx to enable controller send alert if(tAlert.read() > 300.0f) { //300.0f is 5 minutes @@ -1303,7 +1308,7 @@ if(newEnergyData) { //for(int i=1; i<4; i++) { - for(int i=1; i<2; i++) { + for(int i=1; i<(powerPHASE+1); i++) { DBG.printf("sending channel: %d\r\n",i); if(i==1){ XWattHr = AWattHr; @@ -1952,7 +1957,7 @@ if(newEnergyData) { //for(int i=1; i<4; i++) { - for(int i=1; i<2; i++) { + for(int i=1; i<(powerPHASE+1); i++) { DBG.printf("sending channel: %d\r\n",i); if(i==1){ XWattHr = AWattHr; @@ -2100,7 +2105,7 @@ DBG.printf("getNodesTemperature\r\n"); for(int i=0; i<NODES_MAX; i++) { - if(!nodes[i].ipAddr.empty()) { + if(!nodes[i].ipAddr.empty() && nodes[i].type == 1) { //get node's temp string temp; nodes[i].restConn->get("/","<?xml version=\"1.0\" encoding=\"utf-8\"?><app_cmd cmd=\"2\"/>\r\n"); @@ -2417,6 +2422,468 @@ } } else if(gprsConnected) { DBG.printf("emmaModeOperation - gprs\r\n"); + + //new log indicator + seconds = time(NULL); + strftime(q, 32, "%Y-%m-%d %H:%M:%S",localtime(&seconds)); + DBG.printf("newLog:%d\r\n",writeLog(q,"++++++++++GPRS++++++++++")); + + //check firmware update + + //execute last state of switches on board + + //get list of nodes from server + connBodyLen = sprintf(connBody,"{\"uid\":\"%s\",\"hmac\":\"%s\"}",emmaUID.c_str(),hmac.c_str()); + sprintf(s,"POST /%s/api/controller/wifinodes HTTP/1.0\nHost: %s\nContent-Length:%d\n\n%s\r\n\r\n",appNAME.c_str(),restSERVER.c_str(),connBodyLen,connBody); + sscanf(restPORT.c_str(),"%d",&connPort); + str.clear(); + str = gprsREST(restSERVER,connPort,s); + //DBG.printf("str:%s\r\n",str.c_str()); + + if(str.rfind("[{\"type\"") != std::string::npos) { + DBG.printf("get nodes from server\r\n"); + str.erase(str.begin(),str.begin()+str.rfind("[{\"type\"")); + str.erase(str.begin()+str.rfind("}]")+2,str.end()); + + MbedJSONValue jsonValue; + parse(jsonValue,str.c_str()); + char *parameter[3] = {"type","mac","ip"}; + + TFT.locate(0,40); + TFT.printf(" "); + TFT.locate(0,40); + TFT.printf("get %d nodes from server",jsonValue.size()); + wait(0.5); + TFT.locate(0,40); + TFT.printf(" "); + + //check whether nodes valid + bool validNodes = true; + for(int i=0; i<jsonValue.size(); i++) { + for(int j=0; j<3; j++) { + validNodes = validNodes && jsonValue[i].hasMember(parameter[j]); + } + } + DBG.printf("nodes validity:%d\r\n",validNodes); + + if(validNodes) { + for(int i=0; i<jsonValue.size(); i++) { + int typeValue = jsonValue[i][parameter[0]].get<int>(); + string macValue = jsonValue[i][parameter[1]].get<std::string>(); + string ipValue = jsonValue[i][parameter[2]].get<std::string>(); + nodes[i].type = typeValue; + nodes[i].macAddr = macValue; + nodes[i].ipAddr = ipValue; + DBG.printf("nodes[%d]type:%d\r\n",i,nodes[i].type); + DBG.printf("nodes[%d]mac:%s\r\n",i,nodes[i].macAddr.c_str()); + DBG.printf("nodes[%d]ip:%s\r\n",i,nodes[i].ipAddr.c_str()); + } + } + + } else { + DBG.printf("no nodes from server\r\n"); + } + + //create nodes connection via wifi (we assume that when using gprs, user should provide wifi for node control) + //init rest to remotes + for(int i=0; i<NODES_MAX; i++) { + if(!nodes[i].ipAddr.empty()) { + DBG.printf("restConn nodes[%d] is created\r\n",i); + nodes[i].restConn->begin(nodes[i].ipAddr.c_str(),REMOTE_TCP_PORT,false); + wait(1); + } else { + DBG.printf("restConn nodes[%d] is NOT created\r\n",i); + wait(1); + } + } + + _ESP.attach(&rxInterrupt,Serial::RxIrq); + + //define thread + osThreadDef(energyThread, osPriorityBelowNormal, (8*DEFAULT_STACK_SIZE)); + //create thread + osThreadCreate(osThread(energyThread),NULL); + + tAlert.start(); + tPanelEnergy.start(); + tPanel.start(); + tNodes.start(); + wait(1); + while(1) { + //checkVoltagePower(); //need revision to support gprs + + //panelEnergy, panelVoltage, and panelPower + if(tPanelEnergy.read() > 30.0f) { + DBG.printf("[%d]WattHR for each phase: %.2f, %.2f, %.2f\r\n", loop, AWattHr, BWattHr, CWattHr); + TFT.locate(0,60); + TFT.printf(" "); + TFT.locate(0,60); + TFT.printf("[%d]WHR: %.1f, %.1f, %.1f", loop, AWattHr, BWattHr, CWattHr); + + DBG.printf("VRMS for each phase: %.2f, %.2f, %.2f\r\n", AVrms, BVrms, CVrms); + TFT.locate(0,80); + TFT.printf(" "); + TFT.locate(0,80); + TFT.printf("VRMS: %.1f, %.1f, %.1f", AVrms, BVrms, CVrms); + + DBG.printf("Watt for each phase: %.2f, %.2f, %.2f\r\n", AWatt, BWatt, CWatt); + TFT.locate(0,100); + TFT.printf(" "); + TFT.locate(0,100); + TFT.printf("Watt: %.1f, %.1f, %.1f", AWatt, BWatt, CWatt); + + if(newEnergyData) { + for(int i=1; i<(powerPHASE+1); i++) { + DBG.printf("sending channel: %d\r\n",i); + if(i==1){ + XWattHr = AWattHr; + XVrms = AVrms; + XWatt = AWatt; + } else if(i==2) { + XWattHr = BWattHr; + XVrms = BVrms; + XWatt = BWatt; + } else { + XWattHr = CWattHr; + XVrms = CVrms; + XWatt = CWatt; + } + + if(XWattHr != 0.0f) { + seconds = time(NULL); + strftime(q, 32, "%Y-%m-%d %H:%M:%S",localtime(&seconds)); + + sprintf(p,"emma-%s-%s",emmaUID.c_str(),q); + hmacTime = calculateMD5(p); + + connBodyLen = sprintf(connBody,"{\"uid\":\"%s\",\"hmac\":\"%s\",\"time\":\"%s\",\"energy\":%.2f,\"voltage\":%.2f,\"power\":%.2f}", + emmaUID.c_str(),hmacTime.c_str(),q,XWattHr,XVrms,XWatt); + sprintf(s,"POST /%s/api/controller/energy/%d HTTP/1.0\nHost:%s\nContent-Length:%d\n\n%s\r\n\r\n",appNAME.c_str(),i,restSERVER.c_str(),connBodyLen,connBody); + + //DBG.printf("dataEnergy:\r\n%s\r\n",connBody); + + str.clear(); + sscanf(restPORT.c_str(),"%d",&connPort); + str = gprsREST(restSERVER,connPort,s); + //DBG.printf("str:%s\r\n",str.c_str()); + + if(str.find("\"status\":\"success\"") != std::string::npos) { + //logging purpose + seconds = time(NULL); + strftime(q, 32, "%Y-%m-%d %H:%M:%S",localtime(&seconds)); + DBG.printf("logPE:%d\r\n",writeLog(q,"sendEnergyData success")); + + DBG.printf("send channel: %d success\r\n",i); + TFT.foreground(Green); + TFT.locate(0,120); + TFT.printf(" "); + TFT.locate(0,120); + TFT.printf("send ch%d success",i); + wait(1); + TFT.locate(0,120); + TFT.printf(" "); + TFT.foreground(White); + } else { + //logging purpose + seconds = time(NULL); + strftime(q, 32, "%Y-%m-%d %H:%M:%S",localtime(&seconds)); + DBG.printf("logPE:%d\r\n",writeLog(q,"sendEnergyData failed")); + + DBG.printf("send channel: %d failed\r\n",i); + TFT.foreground(Red); + TFT.locate(0,120); + TFT.printf(" "); + TFT.locate(0,120); + TFT.printf("send ch%d failed",i); + wait(1); + TFT.locate(0,120); + TFT.printf(" "); + TFT.foreground(White); + } + } + } + newEnergyData = false; + } + + tPanelEnergy.reset(); + loop++; + } + + //panel environment + if(tPanel.read() > 900.0f) { //900.0f is 15 minutes + int dTemp=0; + int dHum=0; + int dGas=0; + + DBG.printf("getPanelEnvironment\r\n"); + + //get environment sensor + trial=0; + while(1) { + if(trial>=2) { //two times trial + break; + } + if(d.readData() == DHT11::OK) { + dTemp = d.readTemperature(); + dHum = d.readHumidity(); + break; + } + trial++; + wait(3); + } + + //send environment sensor + if(dTemp!=0 && dHum!=0) { + seconds = time(NULL); + strftime(q, 32, "%Y-%m-%d %H:%M:%S",localtime(&seconds)); + + //calculate hmacTime + sprintf(p,"emma-%s-%s",emmaUID.c_str(),q); + hmacTime = calculateMD5(p); + + connBodyLen = sprintf(connBody,"{\"uid\":\"%s\",\"hmac\":\"%s\",\"time\":\"%s\",\"temp\":%d,\"hum\":%d,\"gas\":%d}", + emmaUID.c_str(),hmacTime.c_str(),q,dTemp,dHum,dGas); + sprintf(s,"POST /%s/api/controller/environment HTTP/1.0\nHost:%s\nContent-Length:%d\n\n%s\r\n\r\n",appNAME.c_str(),restSERVER.c_str(),connBodyLen,connBody); + + //DBG.printf("dataEnvironment:\r\n%s\r\n",s); + + str.clear(); + sscanf(restPORT.c_str(),"%d",&connPort); + str = gprsREST(restSERVER,connPort,s); + //DBG.printf("str:%s\r\n",str.c_str()); + + if(str.find("\"status\":\"success\"") != std::string::npos) { + //logging purpose + seconds = time(NULL); + strftime(q, 32, "%Y-%m-%d %H:%M:%S",localtime(&seconds)); + DBG.printf("logPEnv:%d\r\n",writeLog(q,"sendPanelEnv success")); + DBG.printf("send panel environment success\r\n"); + } else { + //logging purpose + seconds = time(NULL); + strftime(q, 32, "%Y-%m-%d %H:%M:%S",localtime(&seconds)); + DBG.printf("logPEnv:%d\r\n",writeLog(q,"sendPanelEnv failed")); + DBG.printf("send panel environment failed\r\n"); + } + } + tPanel.reset(); + } + + //nodeTemp + checkRxBuffer(); + if(tNodes.read() > 900.0f) { //900 is 15 minutes + DBG.printf("getNodesTemperature\r\n"); + + for(int i=0; i<NODES_MAX; i++) { + if(!nodes[i].ipAddr.empty() && nodes[i].type == 1) { + //get node's temp + string temp; + nodes[i].restConn->get("/","<?xml version=\"1.0\" encoding=\"utf-8\"?><app_cmd cmd=\"2\"/>\r\n"); + wait(2); + temp = rxBuf; + if(temp.rfind(nodes[i].ipAddr) != std::string::npos) { + temp.erase(temp.begin(),temp.begin()+temp.rfind(nodes[i].ipAddr)); + if(temp.rfind("temp=") != std::string::npos) { + temp.erase(temp.begin(),temp.begin()+temp.rfind("temp=")+6); + temp.erase(temp.begin()+temp.find("\""),temp.end()); + } else { + temp = "0"; //connect to node, but receive none + } + } else { + temp = "0"; //not connected to node + } + + DBG.printf("nodeTemp[%d]:%s\r\n",i,temp.c_str()); + + //send node's temp + if(temp != "0") { + seconds = time(NULL); + strftime(q, 32, "%Y-%m-%d %H:%M:%S",localtime(&seconds)); + + //calculate hmacTime + sprintf(p,"emma-%s-%s",emmaUID.c_str(),q); + hmacTime = calculateMD5(p); + + connBodyLen = sprintf(connBody,"{\"uid\":\"%s\",\"hmac\":\"%s\",\"time\":\"%s\",\"mac\":%s,\"value\":%s}", + emmaUID.c_str(),hmacTime.c_str(),q,nodes[i].macAddr.c_str(),temp.c_str()); + sprintf(s,"POST /%s/api/controller/nodetemp HTTP/1.0\nHost:%s\nContent-Length:%d\n\n%s\r\n\r\n",appNAME.c_str(),restSERVER.c_str(),connBodyLen,connBody); + + //DBG.printf("dataNodeTemp:\r\n%s\r\n",s); + + str.clear(); + sscanf(restPORT.c_str(),"%d",&connPort); + str = gprsREST(restSERVER,connPort,s); + //DBG.printf("str:%s\r\n",str.c_str()); + + if(str.find("\"status\":\"success\"") != std::string::npos) { + DBG.printf("send nodeTemp success\r\n"); + } else { + DBG.printf("send nodeTemp failed\r\n"); + } + } + } + } + tNodes.reset(); + } + + //command + connBodyLen = sprintf(connBody,"{\"uid\":\"%s\",\"hmac\":\"%s\"}",emmaUID.c_str(),hmac.c_str()); + sprintf(s,"POST /%s/api/controller/command HTTP/1.0\nHost: %s\nContent-Length:%d\n\n%s\r\n\r\n",appNAME.c_str(),restSERVER.c_str(),connBodyLen,connBody); + sscanf(restPORT.c_str(),"%d",&connPort); + str = gprsREST(restSERVER,connPort,s); + //DBG.printf("str:%s\r\n",str.c_str()); + + if(str.rfind("[{\"from\"") != std::string::npos) { + str.erase(str.begin(),str.begin()+str.rfind("[{\"from\"")); + if(str.find("[{") != std::string::npos && str.rfind("}]") != std::string::npos) { + str.erase(str.begin(),str.begin()+str.find("[{")); + str.erase(str.begin()+str.rfind("}]")+2,str.end()); + } + //DBG.printf("newCommand:\r\n%s\r\n",str.c_str()); + TFT.locate(0,160); + TFT.printf(" "); + TFT.locate(0,160); + TFT.printf("newCommand"); + + MbedJSONValue jsonValue; + parse(jsonValue,str.c_str()); + char *parameter[5] = {"from","nType","nAddr","dType","cmd"}; + + DBG.printf("get %d command\r\n",jsonValue.size()); + + //processing each command + bool validCommand; + for(int i=0; i<jsonValue.size(); i++) { + //check whether command is valid + DBG.printf("\r\nprocessing cmd[%d]\r\n",i); + validCommand = true; + for(int j=0; j<5; j++) { + validCommand = validCommand && jsonValue[i].hasMember(parameter[j]); + } + DBG.printf("command validity:%d\r\n",validCommand); + + if(validCommand) { + string commandFrom = jsonValue[i][parameter[0]].get<std::string>(); + string commandNType = jsonValue[i][parameter[1]].get<std::string>(); + string commandNAddr = jsonValue[i][parameter[2]].get<std::string>(); + string commandDType = jsonValue[i][parameter[3]].get<std::string>(); + string commandCmd = jsonValue[i][parameter[4]].get<std::string>(); + + if(commandNType == "0") { //switch on panel controller + DBG.printf("command for switch\r\n"); + } + else if(commandNType == "1" || commandNType == "2") { //ir&rf remote control or wifi smart plug + DBG.printf("command for remote control\r\n"); + + //get index of node list based on mac address + int idx = NODES_INVALID; + for(int i=0; i<NODES_MAX; i++) { + if(!nodes[i].macAddr.compare(commandNAddr)) { + idx = i; + } + } + + //execution process + string execResult = "failed"; + if(idx != NODES_INVALID) { + DBG.printf("index found at %d\r\n",idx); + + if(commandNType == "1"){ + //get cmd string based on device type and command number + string nodeCmd; + nodeCmd = readNodeCmd(commandDType,commandCmd); + sprintf(s,"<?xml version=\"1.0\" encoding=\"utf-8\"?><app_cmd cmd=\"5\" /><app_data code=\"%s\"/>\r\n",nodeCmd.c_str()); + } else if(commandNType == "2") { + sprintf(s,"<?xml version=\"1.0\" encoding=\"utf-8\"?><app_cmd cmd=\"13\"/><app_data on-off=\"%s\"/>\r\n",commandCmd.c_str()); + } + + //execute command + DBG.printf("executing command\r\n"); + + trial=0; + while(1) { + rxBuf.clear(); + if(trial>=2) { //two times trial + DBG.printf("cmd is not executed\r\n"); + TFT.foreground(Red); + TFT.locate(0,180); + TFT.printf(" "); + TFT.locate(0,180); + TFT.printf("cmd is not executed"); + wait(1); + TFT.locate(0,180); + TFT.printf(" "); + TFT.foreground(White); + break; + } + nodes[idx].restConn->get("/",s); + wait(2); + if(rxBuf.find("REST: status = 200") != std::string::npos) { + DBG.printf("cmd is executed\r\n"); + TFT.foreground(Green); + TFT.locate(0,180); + TFT.printf(" "); + TFT.locate(0,180); + TFT.printf("cmd is executed"); + wait(1); + TFT.locate(0,180); + TFT.printf(" "); + TFT.foreground(White); + execResult = "success"; + break; + } + trial++; + } + } else { + TFT.foreground(Red); + TFT.locate(0,180); + TFT.printf(" "); + TFT.locate(0,180); + TFT.printf("node is invalid"); + wait(1); + TFT.locate(0,180); + TFT.printf(" "); + TFT.foreground(White); + } + wait(2); + + //send execution result + sprintf(p,"emma-%s-%s",emmaUID.c_str(),commandCmd.c_str()); + hmacCmd = calculateMD5(p); + + connBodyLen = sprintf(connBody,"{\"uid\":\"%s\",\"nType\":\"%s\",\"nAddr\":\"%s\",\"dType\":\"%s\",\"cmd\":\"%s\",\"from\":\"%s\",\"result\":\"%s\",\"hmac\":\"%s\"}", + emmaUID.c_str(), commandNType.c_str(),commandNAddr.c_str(),commandDType.c_str(),commandCmd.c_str(),commandFrom.c_str(),execResult.c_str(),hmacCmd.c_str()); + + sprintf(s,"POST /%s/api/controller/result HTTP/1.0\nHost: %s\nContent-Length:%d\n\n%s\r\n\r\n",appNAME.c_str(),restSERVER.c_str(),connBodyLen,connBody); + sscanf(restPORT.c_str(),"%d",&connPort); + + trial=0; + while(1) { + if(trial>=2) { //two times trial + DBG.printf("failed to send execution result\r\n"); + break; + } + str = gprsREST(restSERVER,connPort,s); + wait(2); + if(str.rfind("[{\"status\"") != std::string::npos) { + str.erase(str.begin(),str.begin()+str.rfind("[{\"status\"")); + if(str.find("\"status\":\"success\"") != std::string::npos) { + DBG.printf("success to send execution result\r\n"); + break; + } + } + str.clear(); + trial++; + } + } + } + } + //clear text on lcd + TFT.locate(0,160); + TFT.printf(" "); + } + osDelay(5000); + } } } void emmaModeFirmwareDownload(void) { @@ -2684,7 +3151,7 @@ BWattHrSum = 0; CWattHrSum = 0; - while(tEnergy.read() < 1*60.0) { + while(tEnergy.read() < 5*60.0) { AWattHrValue = ADE.getWattHR(PHASE_A); BWattHrValue = ADE.getWattHR(PHASE_B); CWattHrValue = ADE.getWattHR(PHASE_C); @@ -3259,8 +3726,9 @@ if(str.find("CLOSE OK") != std::string::npos) { break; } - if(n>5) { - return "ERROR:CIPCLOSE"; //unable to close connection + if(n>3) { + //return "ERROR:CIPCLOSE"; //unable to close connection + return rLong; //assumption if unable to close connection because it already been closed } n++; } @@ -3614,7 +4082,7 @@ DBG.printf("IP Addr:%s\r\n",str.c_str()); //test connection sscanf(restPORT.c_str(),"%d",&connPort); - sprintf(cmd,"GET /emma/api/controller/test HTTP/1.0\nHost: %s:%d\n\n\n\n%c",restSERVER.c_str(),connPort,26); + sprintf(cmd,"GET /%s/api/controller/test HTTP/1.0\nHost: %s:%d\n\n\n\n%c",appNAME.c_str(),restSERVER.c_str(),connPort,26); str = gprsREST(restSERVER,connPort,cmd); DBG.printf("str:%s\r\n",str.c_str()); if(str.find("\"status\":\"OK\"") != std::string::npos) {