This demonstrates the process of communicating through ethernet to a SEL-2431 Voltage Regulator Control Panel using SEL Fast Message. Basic device commands and data cna be requested and displayed over a connected serial port. This is a basic version and full testing and documentation has yet to be completed.

Dependencies:   BufferedSerial analogAverager voltageRegulator netStatReg analogMinMax CounterMinMax

Revision:
10:9da863a6da3e
Parent:
9:d6e7981dfc89
Child:
11:d40adc7de05f
--- a/main.cpp	Tue Oct 01 15:51:59 2019 +0000
+++ b/main.cpp	Wed Oct 02 12:12:30 2019 +0000
@@ -39,7 +39,6 @@
 //Provides the deivce poll timing
 void heartbeat()
 {
-    //polltick=true;
     setTick(true);
 }
 
@@ -52,7 +51,6 @@
     net1.cltCloseConnection=false;
     net1.pollTime=0;
     net1.pollTimeout=0;
-    net1.pollInterval=setpollinterval;
     net1.pollRequestSent=false;
     net1.pollResponseReceived=false;
     net1.srv_sock.set_blocking(true);
@@ -62,13 +60,14 @@
     net1.srv.set_timeout(100);
     net1.pollEnabled=setpollenabled;
     net1.pollTimeoutCount=0;
-    net1.pollState=0;
+    net1.configState=0;
     net1.pollTimeoutCount=0;
     net1.sendRetryCount=0;
     net1.messageFailCount=0;
     net1.txMessageCount=0;
     net1.rxMessageCount=0;
-    net1.connectCmd=false;
+    net1.fmEnabled=false;
+    net1.fmdEnabled=false;
     
     /* Open the server on ethernet stack */
     net1.srv.open(eth);
@@ -96,12 +95,14 @@
     
     while(1)
     {
+        //Check to see if the Receive Buffer has anything
         while (!receiveBuffer.empty())
         {
             receiveBuffer.pop(cchar);
             cbuf[clen]=cchar;
             clen++;
         }
+        //If a Poll Request has been made and data has been received set flag
         if (net2->pollRequestSent)
         {
             if (clen>0)
@@ -109,17 +110,22 @@
                 net2->pollResponseReceived=true;
             }
         }
+        //Check to see if bulk data and reports being sent from device due to serial command
         if (net2->devMsgOpenRx)
         {
             sport0.write(cbuf,clen);
             clen=0;
         }
+        //Check to see if at least 4 characters have been received
         else if (clen>3)
         {
+            //Cycle through received data to search for a command
             for (cbc=0;cbc<clen-3;cbc++)
             {
+                //Check to see if serial commands are currently being received
                 if (net2->serIsActive==true)
                 {
+                    //If relay acknowledges max metering command set bulk receive flag
                     if ((cbuf[cbc]==0x4d) && (cbuf[cbc+1]==0x45) && (cbuf[cbc+2]==0x54))
                     {
                         sport0.write(cbuf,clen);
@@ -128,7 +134,7 @@
                         clen=0;
                         break;
                     }
-                    
+                    //If relay acknowledges tap report command set bulk receive flag
                     if ((cbuf[cbc]==0x54) && (cbuf[cbc+1]==0x41) && (cbuf[cbc+2]==0x50))
                     {
                         sport0.write(cbuf,clen);
@@ -137,6 +143,7 @@
                         clen=0;
                         break;
                     }
+                    //If relay acknowledges level 1 login attempt increment command pointer to password
                     if ((cbuf[cbc]==0x41) && (cbuf[cbc+1]==0x43) && (cbuf[cbc+2]==0x43))
                     {
                         sport0.write(cbuf,clen);
@@ -144,6 +151,7 @@
                         clen=0;
                         break;
                     }
+                    //If relay sends mask character increment command pointer to send \r\n
                     if (cbuf[cbc]==0x2a)
                     {
                         sport0.write(cbuf,clen);
@@ -151,6 +159,7 @@
                         clen=0;
                         break;
                     }
+                    //If relay is in access level 1 or higher increment command pointer to desired command
                     if ((cbuf[cbc]==0x3d) && (cbuf[cbc+1]==0x3e))
                     {
                         sport0.write(cbuf,clen);
@@ -158,6 +167,7 @@
                         clen=0;
                         break;
                     }
+                    //If relay in level 0 increment command pointer to access command
                     if ((cbuf[cbc]==0x3d))
                     {
                         sport0.write(cbuf,clen);
@@ -166,32 +176,35 @@
                         break;
                     }
                 }
+                //Check fast message conficuration
                 if ((cbuf[cbc]==0xA5) && (cbuf[cbc+1]==0xC0))
                 {
                     sport0.write(cbuf,clen);
-                    net2->pollState=1;
+                    net2->configState=1;
                     clen=0;
                     break;
                 }
+                //Check fast meter configuration
                 if ((cbuf[cbc]==0xA5) && (cbuf[cbc+1]==0xC1))
                 {
                     sport0.write(cbuf,clen);
+                    //Ensure Analog channl count is correct
                     if (vReg1.numAnalog!=cbuf[6])
                     {
-                        printf("\r\nAnalog Channel Count Off\r\n");
-                        net2->pollState=0;
+                        printf("\r\nFast Meter Analog Channel Count Off\r\n");
                         clen=0;
                         break;
                     }
+                    //Ensure Digital register count is correct
                     if (vReg1.numDigital!=cbuf[8])
                     {
-                        printf("\r\nDigital Channel Count Off\r\n");
-                        net2->pollState=0;
+                        printf("\r\nFast Meter Digital Channel Count Off\r\n");
                         clen=0;
                         break;
                     }
                     char anum=16;
                     char nxc;
+                    //Verify Analog names are correct
                     for (txc=0;txc<vReg1.numAnalog;txc++)
                     {
                         for (nxc=0;nxc<6;nxc++)
@@ -204,10 +217,12 @@
                         }
                         anum = anum + 11;
                     }
-                    net2->pollState=2;
+                    net2->configState=3;
+                    net2->fmEnabled=true;
                     clen=0;
                     break;
                 }
+                //Receive data
                 if ((cbuf[cbc]==0xA5) && (cbuf[cbc+1]==0xD1))
                 {
                     char anum=cbc+4;
@@ -239,6 +254,64 @@
                     clen=0;
                     break;
                 }
+                //Check fast demand meter configuration
+                if ((cbuf[cbc]==0xA5) && (cbuf[cbc+1]==0xC2))
+                {
+                    sport0.write(cbuf,clen);
+                    //Ensure Analog channl count is correct
+                    if (vReg1.numDemAnalog!=cbuf[6])
+                    {
+                        printf("\r\nDemand Analog Channel Count Off\r\n");
+                        clen=0;
+                        break;
+                    }
+                    char anum=18;
+                    char nxc;
+                    //Verify Analog names are correct
+                    for (txc=0;txc<vReg1.numDemAnalog;txc++)
+                    {
+                        for (nxc=0;nxc<6;nxc++)
+                        {
+                            if(vReg1.analogs[txc+vReg1.numAnalog].analogName[nxc]!=cbuf[anum+nxc])
+                            {
+                                printf("%c %c\r\n",vReg1.analogs[txc+vReg1.numAnalog].analogName[nxc],cbuf[anum+nxc]);
+                                printf("\r\nPoint %d Failed\r\n",txc);
+                                break;
+                            }
+                        }
+                        anum = anum + 11;
+                    }
+                    net2->configState=9;
+                    net2->fmdEnabled=true;
+                    clen=0;
+                    break;
+                }
+                //Receive demand data
+                if ((cbuf[cbc]==0xA5) && (cbuf[cbc+1]==0xD2))
+                {
+                    char anum=cbc+4;
+                    for (txc=0;txc<vReg1.numDemAnalog;txc++)
+                    {
+                        valpack.bytes[3]=cbuf[anum];
+                        valpack.bytes[2]=cbuf[anum+1];
+                        valpack.bytes[1]=cbuf[anum+2];
+                        valpack.bytes[0]=cbuf[anum+3];
+                        vReg1.analogs[txc].analog1Value = valpack.cmdflt;
+                        anum = anum + 4;
+                        printf("%.2f\r\n",vReg1.analogs[txc].analog1Value);
+                    }
+                    vReg1.demTimeStamp.month=cbuf[anum];
+                    vReg1.demTimeStamp.day=cbuf[anum+1];
+                    vReg1.demTimeStamp.year=cbuf[anum+2];
+                    vReg1.demTimeStamp.hour=cbuf[anum+3];
+                    vReg1.demTimeStamp.min=cbuf[anum+4];
+                    vReg1.demTimeStamp.sec=cbuf[anum+5];
+                    timepack.bytes[1]=cbuf[anum+6];
+                    timepack.bytes[0]=cbuf[anum+7];
+                    vReg1.demTimeStamp.msec=timepack.cmdshort;
+                    printf("%d/%d/%d %d:%d:%d.%d\r\n",vReg1.demTimeStamp.month,vReg1.demTimeStamp.day,vReg1.demTimeStamp.year,vReg1.demTimeStamp.hour,vReg1.demTimeStamp.min,vReg1.demTimeStamp.sec,vReg1.demTimeStamp.msec);
+                    break;
+                }
             }
             if (clen>0)
             {
@@ -256,35 +329,40 @@
     {
         if (net2->cltIsActive)
         {
+            //Attempt to connect to server
             while (net2->sendState==3)
             {
+                //delay connect attempt if previous attempt unsuccessful
                 if (net2->connectRetry == true)
                 {
                     wait_ms(100);
                 }
-                net2->connectCmd=true;
+                //Attempt to connectg
                 ret = net2->srv_sock.connect(net2->srv_addr,net2->cltPort);
+                //If connect successful proceed to send data
                 if (ret==0)
                 {
                     net2->connectRetry = false;
                     printf("Connected %d\r\n",ret);
                     net2->sendState=4;
                 }
+                //If connect attempt failed check to see if may already be connected
                 else if (ret==-3015)
                 {
                     printf("May already be connected, attempting send.\r\n");
                     net2->connectRetry = false;
                     net2->sendState=4;
                 }
+                //If connect attempt failed on other error attempt reconnect
                 else
                 {
                     net2->connectRetry = true;
                     net2->sendRetryCount++;
                     printf("Connect Attempt Failed, Code: %d\r\n",ret);
+                    //If connect attempt failed exceeds 3 then end attempt
                     if (net2->sendRetryCount>3)
                     {
                         printf("Communication Failed, Closing\r\n");
-                        net2->connectCmd=false;
                         net2->connectRetry = false;
                         net2->sendRetryCount = 0;
                         net2->messageFailCount++;
@@ -294,14 +372,17 @@
                     }
                 }
             }
+            //Attempt to send data
             while (net2->sendState==4)
             {
+                //Delay send data attempt if previous attempt failed
                 if (net2->sendRetry == true)
                 {
                     wait_ms(100);
                 }
-                net2->connectCmd=false;
+                //Attempt to send data
                 ret = net2->srv_sock.send(net2->sendString,net2->sendLen);
+                //If data send successful proceed to wait for response
                 if (ret>=0)
                 {
                     printf("Send Result %d\r\n",ret);
@@ -310,11 +391,13 @@
                     net2->sendState=5;
                     net2->sendTime=0;
                 }
+                //If send attempt failed attempt to re-send data
                 else
                 {
                     net2->sendRetry = true;
                     net2->sendRetryCount++;
                     printf("Send Attempt Failed, Code: %d\r\n",ret);
+                    //If send attempt failed exceeds 3 then end attempt
                     if (net2->sendRetryCount>3)
                     {
                         printf("Communication Failed, Closing\r\n");
@@ -339,9 +422,12 @@
     int rxc;
     while (1)
     {
+        //If the client is active check to see if data has been received
         while (net2->cltIsActive)
         {
+            //Store the length of the received data
             rxlen=net2->srv_sock.recv(rxbuf, sizeof(rxbuf));
+            //if there is data then push data into received buffer
             if (rxlen>0)
             {
                 net2->aliveTime=0;
@@ -350,6 +436,7 @@
                     receiveBuffer.push(rxbuf[rxc]);
                 }
                 printf("Client Received Data\r\n");
+                //Increment received message counter
                 net2->rxMessageCount++;
             }
         }
@@ -364,9 +451,12 @@
     int rxc;
     while (1)
     {
+        //If the server is active check to see if data has been received
         while (net2->srvIsActive)
         {
+            //Store the length of the received data
             rxlen=net2->clt_sock.recv(rxbuf, sizeof(rxbuf));
+            //if there is data then push data into received buffer
             if (rxlen>0)
             {
                 net2->aliveTime=0;
@@ -375,6 +465,7 @@
                     receiveBuffer.push(rxbuf[rxc]);
                 }
                 printf("Server Received Data\r\n");
+                //Increment received message counter
                 net2->rxMessageCount++;
             }
         }
@@ -393,23 +484,30 @@
     
     while (1)
     {
+        //Check to see if there is any data received by serial port and store length
         rxlen=sport0.readable();
+        //If data is ready push into receive buffer
         if (rxlen>0)
         {
             for (rxc=0;rxc<rxlen;rxc++)
             {
                 rxbuf[rxindex+rxc]=sport0.getc();
+                //Check to see if a carriage return has been detected
                 if (rxbuf[rxindex+rxc]=='\r')
                 {
                     crRx=true;
                 }
             }
+            //Store the current cursor location in the buffer
             rxindex=rxindex+rxlen;
-            printf("%d\r\n",rxlen);
-            printf("%d\r\n",rxindex);
+            //printf("%d\r\n",rxlen);
+            //printf("%d\r\n",rxindex);
+            //Set the received length to zero
             rxlen=0;
+            //If there is data in the buffer and a carriage return has been detected search for a command
             if ((rxindex>2) && (crRx==true))
             {
+                //Set the carriage return flag false
                 crRx=false;
                 for (rxc=0;rxc<=rxindex-3;rxc++)
                 {
@@ -417,7 +515,8 @@
                     cmdpack.bytes[2]=rxbuf[rxc+1];
                     cmdpack.bytes[1]=rxbuf[rxc+2];
                     cmdpack.bytes[0]=rxbuf[rxc+3];
-                    printf("%08x\r\n",cmdpack.cmdint);
+                    //printf("%08x\r\n",cmdpack.cmdint);
+                    //Search for the Min/Max command
                     if (cmdpack.cmdint==0x4d45544d)
                     {
                         printf("MIN MAX METERING\r\n");
@@ -425,6 +524,7 @@
                         net2->devMsgPos=2;
                         rxindex=0;
                     }
+                    //Search for the Tap Report Command
                     if (cmdpack.cmdint==0x54415052)
                     {
                         printf("TAP REPORT\r\n");
@@ -433,6 +533,7 @@
                         rxindex=0;
                     }
                 }
+                //If no command found set cursor location to zero
                 if (rxindex>0)
                 {
                     printf("Serial Command Not Found");
@@ -452,6 +553,7 @@
     
     while(1)
     {
+        //Wait for someone to connect
         while (server->accept(client_socket, client_address) < 0)
         {
             //printf("Connection Failed.\r\n");
@@ -463,6 +565,15 @@
     }
 }
 
+void sendCmd(char cmdNum)
+{
+    sendLength.push(2);
+    for (char txc=0;txc<2;txc++)
+    {
+        sendBuffer.push(fmCmd[cmdNum][txc]);
+    }
+}
+
 int main()
 {
     EthernetInterface eth;
@@ -499,6 +610,8 @@
             incTime();
             currenttime=getTime();
             net1.pollTime++;
+            net1.fmPollTime++;
+            net1.fmdPollTime++;
             net1.sendTime++;
             if (net1.srvIsActive)
             {
@@ -514,7 +627,7 @@
             }
             if (net1.pollEnabled)
             {
-                if (net1.pollTime >= net1.pollInterval)
+                if (net1.pollTime >= setpollinterval)
                 {
                     if ((net1.sendState==0)||(net1.sendState==5))
                     {
@@ -533,19 +646,75 @@
                         }
                         else
                         {
-                            sendLength.push(2);
-                            for (txc=0;txc<2;txc++)
+                            if (net1.configState<9)
                             {
-                                sendBuffer.push(fmCmd[net1.pollState][txc]);
+                                sendCmd(net1.configState);
+                                if (net1.sendState==0)
+                                {
+                                    net1.sendState=1;
+                                    net1.pollRequestSent=true;
+                                }
+                            }
+                        }
+                        
+                    }
+                    net1.pollTime=0;
+                }
+                if (net1.fmPollTime >= setfmpollinterval)
+                {
+                    if (net1.serIsActive==false)
+                    {
+                        if ((net1.sendState==0)||(net1.sendState==5))
+                        {
+                            {
+                                if (net1.fmEnabled)
+                                {
+                                    sendCmd(2);
+                                    if (net1.sendState==0)
+                                    {
+                                        net1.sendState=1;
+                                        net1.pollRequestSent=true;
+                                    }
+                                }
                             }
                         }
-                        if (net1.sendState==0)
+                        if (net1.fmPollTime>setfmpollinterval)
                         {
-                            net1.sendState=1;
-                            net1.pollRequestSent=true;
+                            net1.fmPollTime=net1.fmPollTime-setfmpollinterval;
+                        }
+                        else
+                        {
+                            net1.fmPollTime=0;
                         }
                     }
-                    net1.pollTime=0;
+                }
+                if (net1.fmdPollTime >= setfmdemandpollinterval)
+                {
+                    if (net1.serIsActive==false)
+                    {
+                        if ((net1.sendState==0)||(net1.sendState==5))
+                        {
+                            {
+                                if (net1.fmdEnabled)
+                                {
+                                    sendCmd(4);
+                                    if (net1.sendState==0)
+                                    {
+                                        net1.sendState=1;
+                                        net1.pollRequestSent=true;
+                                    }
+                                }
+                            }
+                        }
+                        if (net1.fmdPollTime>setfmdemandpollinterval)
+                        {
+                            net1.fmdPollTime=net1.fmdPollTime-setfmdemandpollinterval;
+                        }
+                        else
+                        {
+                            net1.fmdPollTime=0;
+                        }
+                    }
                 }
                 if ((net1.sendState==5) || (net1.serIsActive))
                 {
@@ -573,9 +742,9 @@
                         }
                         if (net1.serIsActive)
                         {
-                            net1.devMsgOpenRx=false;
                             if ((net1.serTimeoutCount==sertimeoutperiods) || (net1.devMsgReq==0))
                             {
+                                net1.devMsgOpenRx=false;
                                 net1.cltCloseConnection=true;
                                 net1.devMsgReq=0;
                                 net1.serIsActive=false;