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
Diff: main.cpp
- 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;