#include "stdafx.h" #include "DIOSBoardController.h" #include "LogicDriverThreadLocker.h" #include "SCFLoader.h" #include "NotifyPacket.h" using namespace DIOS::Dev::Detail::MachineryECOM; using namespace DIOS::Dev::Communication; DIOSBoardController::DIOSBoardController() :m_SCFInstance(nullptr), m_connectStatus(FALSE) { } DIOSBoardController::~DIOSBoardController() { } bool DIOSBoardController::Initialize(SCF* pSCF) { bool ret = true; SCFLoader::Instance()->Initialize(pSCF); m_SCFInstance = SCFLoader::Instance()->GetSCFInstance(); if (!m_SCFInstance) { if(gdriverLog) gdriverLog->Error("DIOSBoardController Initialize failed to get SCFInstance."); ret = false; } return ret; } bool DIOSBoardController::SetPassiveDisconnectEventHandle(HANDLE handle) { if (m_SCFInstance) { //m_SCFInstance->SetPassiveDisconnectEvt(handle); } return m_SCFInstance != nullptr; } bool DIOSBoardController::Connect(ResDataObject& Connection) { if (m_SCFInstance) { if(gdriverLog) gdriverLog->Info("{$}{$}", " DIOSBoardController Connecting", Connection.encode()); int nResult = m_SCFInstance->Connect(Connection.encode(), &DIOSBoardController::EventCallback, SCF_PACKET_TRANSFER, 5000); if (SCF_SUCCEED == nResult) { if(gdriverLog) gdriverLog->Info("DIOSBoardController SCF Connected"); m_connectStatus = TRUE; } else { return false; } } else { } return m_connectStatus; } bool DIOSBoardController::Disonnect() { if (m_SCFInstance) { m_SCFInstance->Disconnect(); } m_connectStatus = FALSE; return true; } DWORD DIOSBoardController::Lock() { LogicDriverThreadLocker::Instance()->Lock(); return 0; } void DIOSBoardController::UnLock() { LogicDriverThreadLocker::Instance()->UnLock(); } bool DIOSBoardController::Send(SCFPacket *sendPacket, SCFPacket *recvPacket) { if (!m_connectStatus) { return false; } if (sendPacket && m_SCFInstance) { SCF::IO oIO = m_SCFInstance->Lock(DIOSCTRLCPU_COM_TIMEOUT); return DoSendSync(oIO, sendPacket, recvPacket); } return false; } int DIOSBoardController::Receive(SCF::IO& oIO, char *pPacket, DWORD length, DWORD timeout) { if (!m_connectStatus) { return -1; } if (!m_SCFInstance) { return -2; } int nResLen = 0; oIO.ReceivePacket(pPacket, length, timeout, nResLen); if (nResLen > 0) { //if(gcommLog) gcommLog->Info("[Recv]->[%02d][%s]", nResLen, FormatPacketString(pPacket, length).c_str()); { if (gcommLog) { gcommLog->Info("[Recv]->[{$}][{$}]", nResLen, FormatPacketString(pPacket, length).c_str()); } } } else { //if(gcommLog) gcommLog->Info("[Recv][Ivalid]->[%02d]", nResLen); { if (gcommLog) { gcommLog->Info("[Recv][Ivalid]->[{$:d02}]", nResLen); } } } return nResLen; } int DIOSBoardController::Receive(SCF::IO& oIO, SCFPacket *pPacket, DWORD timeout) { if (!m_connectStatus) { return -1; } if (!m_SCFInstance) { return -2; } int nResLen = 0; char rev[100]; memset(rev, 0, 100); oIO.ReceivePacket(rev, pPacket->GetBuffLen(), timeout, nResLen); if (nResLen > 0) { pPacket->SetPacket(rev, nResLen); //if(gcommLog) gcommLog->Info("[Recv]->[%02d][%s]", nResLen, FormatPacketString(pPacket).c_str()); { if (gcommLog) { gcommLog->Info("[Recv]->[{$:d02}][{$}]", nResLen, FormatPacketString(pPacket).c_str()); } } } else { if(gcommLog) gcommLog->Info("[Recv][Ivalid]->[{$:d02}]", nResLen); { if (gcommLog) { gcommLog->Info("[Recv][Ivalid]->[{$:d02}]", nResLen); } } } return nResLen; } void DIOSBoardController::QueNotifyPacket(SCFPacket *pPacket) { if (pPacket && m_SCFInstance) { m_SCFInstance->Queue.Enqueue((char*)(pPacket), pPacket->GetPacketLen()); } } std::string GetTime() { SYSTEMTIME st; GetLocalTime(&st); char tmp[64] = { 0 }; sprintf_s(tmp, "[%04d %02d %02d] [%02d:%02d:%02d.%3d]", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); return std::string(tmp); } //Implement details bool DIOSBoardController::DoSendSync(SCF::IO& oIO, SCFPacket *sendPacket, SCFPacket *recvPacket, DWORD Timeout) { //SCF::IO oIO = m_SCFInstance->Lock(Timeout); int nResLen = 0; oIO.SendPacket((char*)(*sendPacket), sendPacket->GetPacketLen(), Timeout, nResLen); if(nResLen == sendPacket->GetPacketLen()) { CTRLPACKETHEAD *pSendHead = (CTRLPACKETHEAD *)((char *)(*sendPacket)); if (!pSendHead) { if(gdriverLog) gdriverLog->Error("SendPacket is NULL"); } //if(gcommLog) gcommLog->Info("[Send]->[%s]", FormatPacketString(sendPacket).c_str()); { if (gcommLog) { gcommLog->Info("[Send]->[{$}]", FormatPacketString(sendPacket).c_str()); } } ULONGLONG StartTick = GetTickCount64(); DWORD TimePeriod = Timeout; while (TimePeriod > 0) { char rev[MAX_PATH]; memset(rev, 0, MAX_PATH); oIO.ReceivePacket(rev, recvPacket->GetBuffLen(), TimePeriod, nResLen); if (nResLen > 0) { recvPacket->SetPacket(rev, nResLen); //if(gcommLog) gcommLog->Info("[Recv]->[%s]", FormatPacketString(recvPacket).c_str()); { if (gcommLog) { gcommLog->Info("[Recv]->[{$}]", FormatPacketString(recvPacket).c_str()); } } CTRLPACKETHEAD *pReceiveHead = (CTRLPACKETHEAD *)((char *)(*recvPacket)); if ( (pReceiveHead->FrameCmd != pSendHead->FrameCmd) || (pReceiveHead->FrameId != pSendHead->FrameId) || (pReceiveHead->FuncId != pSendHead->FuncId) || (pReceiveHead->FrameSize != 5) ) { if(gdriverLog) gdriverLog->Warn("ReceivePacket: Got Other Packet"); //m_SCFInstance->QueNotifyPacket(recvPacket); m_SCFInstance->Queue.Enqueue((char*)(*recvPacket), recvPacket->GetPacketLen()); ULONGLONG CurTick = GetTickCount64(); if (TimePeriod > CurTick - StartTick) { TimePeriod -= CurTick - StartTick; } else { TimePeriod = 0; } continue; } TimePeriod = 0; if(gdriverLog) gdriverLog->Info("DoSendSync SUCCEED"); return true; } else { TimePeriod = 0; } } } return false; } PACKET_RET DIOSBoardController::EventCallback(const char * pRecData, DWORD nLength, DWORD & PacketLength) { DWORD i = 0; for (; i < nLength - 1; i++) { if ((pRecData[i] == (char)PACKET_HEAD1) && (pRecData[i + 1] == (char)PACKET_HEAD2)) { break; } } if (i > 0) { PacketLength = i; if(gdriverLog) gdriverLog->Warn("EventCallback: PACKET_USELESS i>0"); return PACKET_USELESS; } //最小9字节长 if (nLength < 9) { if(gdriverLog) gdriverLog->Warn("EventCallback: PACKET_NOPACKET"); return PACKET_NOPACKET; } //got right title unsigned char NumLen = (unsigned char)pRecData[2]; unsigned char TotalLen = NumLen + 4; if (nLength < TotalLen) { //not enough if(gdriverLog) gdriverLog->Warn("EventCallback: PACKET_NOPACKET"); return PACKET_NOPACKET; } char chksum, chsend, chend; chksum = (char)0xFF; chsend = (0x0d); chend = (0x0a); //check tail if ((pRecData[TotalLen - 3] == chksum) && (pRecData[TotalLen - 2] == chsend) && (pRecData[TotalLen - 1] == chend)) { PacketLength = TotalLen; if(gdriverLog) gdriverLog->Warn("EventCallback: PACKET_ISPACKET"); return PACKET_ISPACKET; } //packet corrupted PacketLength = 2; if(gdriverLog) gdriverLog->Warn("EventCallback: PACKET_USELESS PacketLength=2"); return PACKET_USELESS; } std::string DIOSBoardController::FormatPacketString(SCFPacket *packet) { std::string formated = ""; int nlen = packet->GetPacketLen(); if (packet == nullptr || packet->GetPacketLen() <= 0) { return formated; } auto packetLength = packet->GetPacketLen(); char *chpacket = (char *)(*packet); char tmp[16] = { 0 }; for (DWORD i = 0; i < packetLength; ++i) { if ((i >= 2 && i <= 6) || (i == packetLength - 3)) { formated = formated + "#"; } memset(tmp, 0, sizeof(tmp)); sprintf_s(tmp, "%02X", (unsigned char)chpacket[i]); formated = formated + std::string(tmp); } return formated; } std::string DIOSBoardController::FormatPacketString(const char *packet, int len) { std::string formated = ""; if (!packet || len <= 0) { return formated; } char tmp[16] = { 0 }; for (int i = 0; i < len; ++i) { if ((i >= 2 && i <= 6) || (i == len - 3)) { formated = formated + "#"; } memset(tmp, 0, sizeof(tmp)); sprintf_s(tmp, "%02X", (unsigned char)packet[i]); formated = formated + std::string(tmp); } return formated; } bool DIOSBoardController::ReceiveACK(SCFPacket* sendPacket, SCFPacket* recvPacket, char* pszContext, unsigned int &PacketLen) { if (!m_connectStatus) { return false; } if (sendPacket && m_SCFInstance) { SCF::IO oIO = m_SCFInstance->Lock(DIOSCTRLCPU_COM_TIMEOUT); DoSendSync(oIO, sendPacket, recvPacket); CTRLPACKETHEAD* pSendHead = (CTRLPACKETHEAD*)((char*)(*sendPacket)); ULONGLONG StartTick = GetTickCount64(); DWORD timeout = DIOSCTRLCPU_COM_TIMEOUT; DWORD TimePeriod = DIOSCTRLCPU_COM_TIMEOUT / 10; while ((GetTickCount64() - StartTick) < timeout) { if (Receive(oIO, recvPacket, TimePeriod) > 0) { CTRLPACKETHEAD* pReceiveHead = (CTRLPACKETHEAD*)((char*)(*recvPacket)); if ( (pReceiveHead->FrameCmd != pSendHead->FrameCmd) || (pReceiveHead->FrameId != pSendHead->FrameId) || (pReceiveHead->FuncId != pSendHead->FuncId) ) { QueNotifyPacket(recvPacket); continue; } int dataLen = pReceiveHead->FrameSize - 5; if (dataLen > 0) { dataLen = min((int)PacketLen, dataLen); unsigned char* pData = &(pReceiveHead->Data1); memcpy(pszContext, pData, dataLen); } PacketLen = dataLen; break; } else { TPRINTA_DEBUG("ReceiveAck Failed"); } } } return true; } bool DIOSBoardController::ReceiveFrame(SCFPacket* sendPacket, SCFPacket* recvPacket, FUNCTIONID Id, unsigned char FrameCmd, char* pszContext, unsigned int PacketLen, unsigned int& nDataLen) { if (!m_connectStatus) { return false; } if (sendPacket && m_SCFInstance) { SCF::IO oIO = m_SCFInstance->Lock(DIOSCTRLCPU_COM_TIMEOUT); DoSendSync(oIO, sendPacket, recvPacket); DWORD StartTick = GetTickCount(); DWORD Timeout = DIOSCTRLCPU_COM_TIMEOUT; DWORD TimePeriod = DIOSCTRLCPU_COM_TIMEOUT / 10; int nPacketLen = 0; char pPacket[MAX_PATH] = { 0 }; while ((GetTickCount() - StartTick) < Timeout) { memset(pPacket, 0, MAX_PATH); if ((nPacketLen = Receive(oIO, pPacket, MAX_PATH, TimePeriod)) > 0) { CTRLPACKETHEAD *pReceiveHead = (CTRLPACKETHEAD *)((char *)(pPacket)); if (pReceiveHead->FrameCmd == FrameCmd && pReceiveHead->FuncId == Id.CharPart) { nDataLen = pReceiveHead->FrameSize - 5; if (nDataLen <= PacketLen) { unsigned char *pData = &(pReceiveHead->Data1); memcpy(pszContext, pData, nDataLen); } TPRINTA_DEBUG("Leave ReceiveResult, WaitIO NOTIFY:SUCCEED"); return true; } else { TPRINTA_DEBUG("Got Other Packet"); recvPacket->SetPacket(pPacket, nPacketLen); //NotifyPacket notifyPacket(recvPacket); //Notify(notifyPacket); QueNotifyPacket(recvPacket); } } else { TPRINTA_DEBUG("WaitIO NOTIFY:FAILED"); } } } return true; } //bool DIOSBoardController::ReceiveCANFrame(SCFPacket* sendPacket, SCFPacket* recvPacket, CAN_ID Id, unsigned short stdid, CAN_PARAM& params) //{ // return true; //}