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 Emma

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) {