123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- #ifndef Message_H
- #include "message.h"
- #include "serial.h"
- #endif
- //#include <QByteArray>
- #include "string.h"
- const unsigned char xSTX = 0xF2;
- const unsigned char xETX = 0x03;
- const unsigned char xENQ = 0x05;
- const unsigned char xACK = 0x06;
- const unsigned char xNAK = 0x15;
- const unsigned char DLE_EOT[2] = {0x10, 0x04};
- #define MAX_CMD_LEN 1024
- #define MAX_RSP_LEN 1024
- #define POLINOMIAL 0x1021 /*Polynormial X16+X12+X5+1*/
- static unsigned short cal_crc(unsigned short crc,unsigned short ch);
- static unsigned short getCRC(unsigned char *p, unsigned short n);
- Message::Message()
- : isOpen(false),
- _needClearMessage(true),
- _haveExtRes(false)
- {
- m_serial.SetCtrl(8, 1, Parity_EVEN, Flow_NO);
- }
- Message::~Message()
- {
- }
- int Message::open(const char *spName, const int baudRate)
- {
- //open port
- if(false == isOpen)
- {
- isOpen = m_serial.Open(spName, baudRate);
- }
- if(isOpen)
- {
- return 0;
- }
- return -1;
- }
- void Message::close()
- {
- if(isOpen)
- {
- m_serial.Close();
- isOpen = false;
- }
- }
- void Message::haveExtRes(bool ext)
- {
- _haveExtRes = ext;
- }
- bool Message::sendRecv(const SANKYO_CMD* cmd)
- {
- clearMessage();
- if (!isOpen)
- return false;
- if (&_sankyoCommand != cmd)
- addCommand(cmd);
- unsigned char* cmdSend = new unsigned char[MAX_CMD_LEN];
- memset(cmdSend, 0, MAX_CMD_LEN);
- int cmdSendLen = MAX_CMD_LEN;
- serializeRequest(cmdSend, cmdSendLen);
- unsigned char* cmdResponse = new unsigned char[MAX_RSP_LEN];
- unsigned cmdResponseLen = 0;
- bool needSend = true;
- bool operationSuccess = false;
- unsigned retryCount = 0;
- do
- {
- if (needSend && sendRequest(cmdSend, cmdSendLen))
- needSend = false;
- else
- usleep(30000);
- if (!needSend && receiveResponse(cmdResponse, cmdResponseLen))
- {
- operationSuccess = true;
- break;
- }
- retryCount++;
- } while (5 > retryCount);
- // ┌───────┬─────────┬─────────────────┬──────────┐
- // │ STX │ LEN │ DATA │ CRCC │
- // ├───────┼─────────┼─────────────────┼──────────┤
- // │ (F2H) │ (2byte) │ (data xx bytes) │ (2bytes) │
- // └───────┴─────────┴─────────────────┴──────────┘
- // |<------LEN------>|
- // |<------------ CRCC range --------->|
- // |<------------- MAX 1024 bytes --------------->|
- if (operationSuccess && 3 < cmdResponseLen)
- deserializeResponse(cmdResponse+3, cmdResponseLen-3);
- delete[] cmdSend;
- delete[] cmdResponse;
- return operationSuccess;
- }
- ///////////////////////////////////////////////////////////////
- /// \brief Message::Private functions
- void Message::clearMessage()
- {
- if (_needClearMessage)
- {
- memset(&_sankyoCommand, 0, sizeof(_sankyoCommand));
- memset(&_hotsResponse, 0, sizeof(_hotsResponse));
- }
- }
- void Message::addCommand(const SANKYO_CMD *cmd)
- {
- _needClearMessage = true;
- memcpy(&_sankyoCommand, cmd, sizeof(SANKYO_CMD));
- if ('C' != _sankyoCommand.idn)
- _sankyoCommand.idn = 'C';
- }
- bool Message::sendRequest(unsigned char *cmdSend, unsigned cmdSendLen)
- {
- bool sendOk = false;
- //写之前先清除可能存在的残存数据
- m_serial.Flush();
- int writedLen = m_serial.Send((const char*)cmdSend, cmdSendLen);
- unsigned char ack = xACK;
- if (writedLen == cmdSendLen && waitExpectedResponse(&ack, 1, 300))
- sendOk = true;
- return sendOk;
- }
- // command format
- // _______________________________________________
- // | STX | LEN | DATA | CRCC |
- // |(F2H) | (2byte) | (data xx bytes) | (2bytes) |
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // |<------LEN------>|
- // |<----------- CRCC range --------->|
- // |<------------ MAX 1024 bytes --------------->|
- bool Message::receiveResponse(unsigned char *cmdResponse, unsigned& cmdResponseLen)
- {
- cmdResponseLen = 0;
- memset(cmdResponse, 0, MAX_RSP_LEN);
- bool receiveOk = false;
- // step1: wait STX byte
- unsigned char stx = xSTX;
- if (waitExpectedResponse(&stx, 1, 20000))
- {
- cmdResponse[cmdResponseLen] = xSTX;
- cmdResponseLen++;
- // step2: read the 'LEN' part, 2 bytes
- unsigned char tmpBuffer[2];
- memset(tmpBuffer, 0, 2);
- int responseLen = readMsg(tmpBuffer, 2, 100);
- if (responseLen > 0)
- memcpy(cmdResponse+cmdResponseLen, tmpBuffer, responseLen);
- cmdResponseLen += responseLen;
- if (2 == responseLen)
- {
- // step3: read 'DATA' part, xx bytes
- int dataPartLen = ((tmpBuffer[0] << 8) + tmpBuffer[1]);
- responseLen = readMsg(cmdResponse+cmdResponseLen, dataPartLen, 250);
- cmdResponseLen += responseLen;
- if (dataPartLen == responseLen)
- {
- // step4: calculate CRCC code
- unsigned short crcRet = getCRC(cmdResponse, cmdResponseLen);
- unsigned char crccExpected[2] = {0x00};
- crccExpected[0] = (crcRet>>8);
- crccExpected[1] = (crcRet&0xFF);
- // step5: read 'CRCC' part, 2 bytes, and check
- unsigned char crcc[2] = {0x00};
- responseLen = readMsg(crcc, 2, 150);
- if (0 == memcmp(crcc, crccExpected, 2))
- {
- receiveOk = true;
- // step6: give ICRW ack response
- char ack = xACK;
- m_serial.Send(&ack, 1);
- }
- else
- {
- logBinaryInfo(cmdResponse, cmdResponseLen, "original bytes to calculate CRCC");
- logBinaryInfo(crccExpected, 2, "crccExpected");
- logBinaryInfo(crcc, 2, "crcc original");
- }
- }
- }
- }
- else
- {
- char dle[2];
- dle[0] = DLE_EOT[0];
- dle[1] = DLE_EOT[1];
- m_serial.Send(dle, 2);
- }
- return receiveOk;
- }
- // command format
- // _________________________________________________________________________
- // | STX | LEN | IDN | CMD | Parameter(CMP) | CRCC |
- // |(F2H) | (2byte) |'C' or 'c'|(cm+pm=2bytes)| (data xx bytes) | (2bytes) |
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // |<------------------LEN-------------------->|
- // |<----------------------- CRCC range ----------------------->|
- // |<------------------------ MAX 1024 bytes ----------------------------->|
- void Message::serializeRequest(unsigned char* cmdSend, int& cmdSendLen)
- {
- cmdSendLen = 0;
- // step1 start of text
- cmdSend[cmdSendLen++] = xSTX;
- // step2 LEN
- unsigned int len = 3 + _sankyoCommand.parameterLen;
- cmdSend[cmdSendLen++] = len>>8;
- cmdSend[cmdSendLen++] = len&0xFF;
- // step3 IDN
- cmdSend[cmdSendLen++] = _sankyoCommand.idn;
- // step4 CMD
- memcpy(cmdSend+cmdSendLen, _sankyoCommand.command, 2);
- cmdSendLen += 2;
- // step5 Parameter
- if (_sankyoCommand.parameterLen > 0)
- {
- memcpy(cmdSend+cmdSendLen, _sankyoCommand.parameter, _sankyoCommand.parameterLen);
- cmdSendLen += _sankyoCommand.parameterLen;
- }
- // step6 CRC check code
- unsigned short crcRet = getCRC(cmdSend, cmdSendLen);
- cmdSend[cmdSendLen++] = (crcRet>>8);
- cmdSend[cmdSendLen++] = (crcRet&0xFF);
- }
- bool Message::waitExpectedResponse(const unsigned char *expectRsp, const int expectLen, long timeOut)
- {
- bool waitOk = false;
- unsigned char* cmdResponse = new unsigned char[expectLen];
- int responseLen = readMsg(cmdResponse, expectLen, timeOut);
- if (expectLen == responseLen && 0 == memcmp(cmdResponse, expectRsp, expectLen))
- {
- waitOk = true;
- }
- else
- {
- logBinaryInfo(cmdResponse, responseLen, "waitExpectedResponse original");
- logBinaryInfo(expectRsp, expectLen, "waitExpectedResponse expect");
- }
- delete[] cmdResponse;
- return waitOk;
- }
- // serialize the 'DATA' part
- // __________________________________________________________________
- // | jdg part | rcm part | res part | rdt part |
- // | 'P' or 'N' | (cm+pm=2bytes) | 2 or 3 bytes | xx bytes |
- // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- void Message::deserializeResponse(const unsigned char *response, const int responseLen)
- {
- int pos = 0;
- _hotsResponse.jdgPart = response[pos++];
- _hotsResponse.rcm[0] = response[pos++];
- _hotsResponse.rcm[1] = response[pos++];
- _hotsResponse.res[0] = response[pos++];
- _hotsResponse.res[1] = response[pos++];
- if('P' == _hotsResponse.jdgPart && _haveExtRes && responseLen > pos)
- _hotsResponse.res_ext = response[pos++];
- _hotsResponse.rdtLen = responseLen - pos;
- if (_hotsResponse.rdtLen > 0)
- memcpy(_hotsResponse.rdt, response+pos, _hotsResponse.rdtLen);
- }
- unsigned Message::readMsg(void *dataBuf, unsigned dataNeedRead, long timeOut)
- {
- unsigned responseLen = m_serial.Receive((char*)dataBuf, dataNeedRead, timeOut);
- if (0 < responseLen && responseLen != dataNeedRead)
- {
- // xLogFmt("IDCSankyo", "error", format("read failed! dataNeedReadLen: %1% != %2%") % dataNeedRead % responseLen);
- logBinaryInfo((unsigned char*)dataBuf, responseLen, "readMsg");
- }
- return responseLen;
- }
- void Message::logBinaryInfo(const unsigned char *msgInfo, unsigned msgLen, const char *summaryInfo)
- {
- // if (0 == msgLen || 0 == msgInfo)
- // return;
- // std::string strInfo(summaryInfo);
- // char cTempArr[1024] = {0x00};
- // memset(cTempArr, 0, sizeof(cTempArr));
- // memcpy(cTempArr, msgInfo, msgLen);
- // QByteArray byteArrayStr = QByteArray::fromRawData(cTempArr, msgLen).toHex().toUpper();
- // xLogFmt("IDCSankyo", "debug", format("%1%, binary info: %2%") % strInfo.data() % byteArrayStr.data());
- }
- static unsigned short cal_crc(unsigned short crc,unsigned short ch)
- {
- //计算CRC
- unsigned short i;
- ch <<= 8;
- for(i=8; i>0; i--)
- {
- if((ch^crc)&0x8000)
- {
- crc = (crc << 1)^POLINOMIAL;
- }
- else
- {
- crc <<= 1;
- }
- ch <<= 1;
- }
- return crc;
- }
- static unsigned short getCRC(unsigned char *p, unsigned short n)
- {
- //计算CRC
- unsigned char ch;
- unsigned short i;
- unsigned short crc = 0X0000;
- for(i=0; i<n; i++)
- {
- ch = *p++;
- crc = ::cal_crc(crc,(unsigned short)ch);
- }
- return crc;
- }
|