From f5c4a7f3bce165fe2c8c6d934f0f49a363a2ea60 Mon Sep 17 00:00:00 2001
From: LAPTOP-T815PCOQ\25526 <mr.liuyang@126.com>
Date: 星期五, 15 十一月 2024 09:19:31 +0800
Subject: [PATCH] Merge branch 'master' into liuyang
---
SourceCode/Bond/BondEq/CPLC.cpp | 314 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 314 insertions(+), 0 deletions(-)
diff --git a/SourceCode/Bond/BondEq/CPLC.cpp b/SourceCode/Bond/BondEq/CPLC.cpp
new file mode 100644
index 0000000..9b1584c
--- /dev/null
+++ b/SourceCode/Bond/BondEq/CPLC.cpp
@@ -0,0 +1,314 @@
+#include "stdafx.h"
+#include "CPLC.h"
+#include "Log.h"
+
+void CALLBACK TimerFileProc(UINT uID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
+{
+ CPLC* pPlc = (CPLC*)dwUser;
+ SetEvent(pPlc->m_hTimeEvent);
+}
+
+unsigned __stdcall McMonitorThreadFunction(LPVOID lpParam)
+{
+ CPLC* pPlc = (CPLC*)lpParam;
+ return pPlc->onMonitor();
+}
+
+CPLC::CPLC()
+{
+ m_nPort = 0;
+ m_state = PLCSTATE::READY;
+ m_listener.onStateChanged = nullptr;
+ m_listener.onMonitorData = nullptr;
+ m_nUnHeartBeat = 0;
+ m_hMcMonitorStop = NULL;
+ m_hMcMonitorThreadHandle = NULL;
+ m_mcMonitorThrdaddr = 0;
+ m_nTimerId = 0;
+ m_hTimeEvent = nullptr;
+}
+
+CPLC::CPLC(const char* pszName, const char* pszIP, unsigned int nPort)
+{
+ m_strName = pszName;
+ m_strIP = pszIP;
+ m_nPort = nPort;
+ m_state = PLCSTATE::READY;
+ m_listener.onStateChanged = nullptr;
+ m_listener.onMonitorData = nullptr;
+ m_nUnHeartBeat = 0;
+ m_hMcMonitorStop = NULL;
+ m_hMcMonitorThreadHandle = NULL;
+ m_mcMonitorThrdaddr = 0;
+ m_nTimerId = 0;
+ m_hTimeEvent = nullptr;
+}
+
+CPLC::~CPLC()
+{
+
+}
+
+std::string& CPLC::getClassName()
+{
+ static std::string strClassName = "CPLC";
+ return strClassName;
+}
+
+void CPLC::setListener(PLCListener& listener)
+{
+ m_listener.onStateChanged = listener.onStateChanged;
+ m_listener.onMonitorData = listener.onMonitorData;
+}
+
+std::string& CPLC::getIP()
+{
+ return m_strIP;
+}
+
+unsigned int CPLC::getPort()
+{
+ return m_nPort;
+}
+
+int CPLC::addMonitor(int id, int beginAddr, int endAddr, MC::SOFT_COMPONENT softComponent, char* pszRecvBuffer)
+{
+ // 检查是否有重复的
+ Lock();
+ for (auto& m : m_monitors) {
+ if (m.id == id) {
+ Unlock();
+ return -1;
+ }
+ }
+
+ MONITOR m;
+ memset(&m, 0, sizeof(MONITOR));
+ m.id = id;
+ m.beginAddr = beginAddr;
+ m.readLen = (endAddr - beginAddr + 1) * 2;
+ m.softComponent = softComponent;
+ m.szRecvBuffer = pszRecvBuffer;
+ m.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+ m_monitors.push_back(m);
+
+ Unlock();
+ return 0;
+}
+
+void CPLC::init()
+{
+ // mc channel
+ McChannelListener m_mcChannellistener;
+ m_mcChannellistener.funOnConnected = [&](IMcChannel* pChannel, int nErrorCode) -> void {
+ LOGI("<PLC-%s>连接结果<code= %d>", m_strName.c_str(), nErrorCode);
+ if (nErrorCode == 0) {
+ setState(PLCSTATE::CONNECTED);
+ }
+ else {
+ setState(PLCSTATE::DISCONNECTED);
+ }
+ };
+ m_mcChannellistener.funOnClose = [&](IMcChannel* pChannel) -> void {
+ setState(PLCSTATE::DISCONNECTED);
+ };
+ m_mcChannellistener.funOnClosing = [&](IMcChannel* pChannel) -> void {
+ };
+ m_mcChannellistener.funOnRead = [&](IMcChannel* pChannel, char* pData, unsigned int nDataSize, int nDecodeRet) -> void {
+ CString strText;
+ dataToHexString(pData, nDataSize, strText);
+ if (nDecodeRet != 0) {
+ LOGE("<PLC-%s>funOnRead[%s], nDecodeRet=%d", m_strName.c_str(), (LPTSTR)(LPCTSTR)strText, nDecodeRet);
+ }
+ m_nUnHeartBeat = 0;
+ };
+ m_mcChannellistener.funOnWrite = [&](IMcChannel* pChannel) -> void {
+
+ };
+
+ if (0 == MCL_CreateChannel(m_pChannel, m_strName.c_str(), m_strIP.c_str(), m_nPort, 0)
+ && m_pChannel != NULL) {
+ m_pChannel->setChannelListener(&m_mcChannellistener);
+ m_pChannel->setActionInterval(m_nActionInterval);
+ LOGI("<PLC-%s>正在连接PLC.", m_strName.c_str());
+ setState(PLCSTATE::CONNECTING);
+ m_pChannel->connect();
+ }
+ else if (m_pChannel != NULL) {
+ m_pChannel->setChannelListener(&m_mcChannellistener);
+ m_pChannel->setActionInterval(m_nActionInterval);
+ }
+
+ m_hTimeEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+ timeBeginPeriod(1);
+ m_nTimerId = timeSetEvent(200, 1, TimerFileProc, (DWORD_PTR)this, TIME_PERIODIC);
+
+
+ if (m_hMcMonitorStop != NULL) return;
+ m_hMcMonitorStop = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+ m_hMcMonitorThreadHandle = (HANDLE)_beginthreadex(NULL, 0, ::McMonitorThreadFunction, this,
+ 0, &m_mcMonitorThrdaddr);
+
+}
+
+void CPLC::term()
+{
+ timeKillEvent(m_nTimerId);
+ timeEndPeriod(1); // 清除前面对定时器的设置
+
+ ASSERT(m_hMcMonitorStop);
+ SetEvent(m_hMcMonitorStop);
+ if (m_hMcMonitorThreadHandle != NULL) {
+ WaitForSingleObject(m_hMcMonitorThreadHandle, INFINITE);
+ CloseHandle(m_hMcMonitorThreadHandle);
+ m_hMcMonitorThreadHandle = NULL;
+ }
+ CloseHandle(m_hMcMonitorStop);
+ m_hMcMonitorStop = NULL;
+
+ for (auto& m : m_monitors) {
+ CloseHandle(m.hEvent);
+ }
+}
+
+unsigned CPLC::onMonitor()
+{
+ HANDLE hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ int nReadLen = 60 * 2;
+ HANDLE hEvents[2] = { m_hMcMonitorStop, m_hTimeEvent };
+
+ while (1) {
+ int nRet = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);
+ ResetEvent(m_hTimeEvent);
+ if (nRet == WAIT_OBJECT_0) {
+ break;
+ }
+
+ if (!m_bRunning || !isConnected()) {
+ continue;
+ }
+
+ for (auto& m : m_monitors) {
+ monitorReadData(m);
+ }
+ }
+
+ TRACE("CPLC::onMonitor 线程退出\n");
+ return 0;
+}
+
+void CPLC::monitorReadData(MONITOR& monitor)
+{
+ BOOL bOutputLog = FALSE;
+ BOOL bReadOk;
+
+
+ // 批量读数据再解释
+ auto funOnReadData = [&](IMcChannel* pChannel, int addr, char* pData, unsigned int nDataSize, int flag) -> void {
+ if (flag == 0) {
+ if (bOutputLog) {
+ CString s;
+ s.Format(_T("CPLC::monitorReadData::funOnReadData %d ["), nDataSize);
+ for (unsigned int i = 0; i < nDataSize; i++) {
+ s.AppendFormat(" %x", (BYTE)pData[i]);
+ }
+ s.Append("]");
+ LOGD("<CPLC-%d-%d>Received plc data.%s", m_nIndex, monitor.id, (LPTSTR)(LPCTSTR)s);
+ }
+ }
+ else {
+ LOGE("<CPLC-%d-%d>PLC批读取数据位超时.flag=%d", m_nIndex, monitor.id, flag);
+ }
+
+ if (nDataSize == monitor.readLen && flag == 0) {
+ memcpy(monitor.szRecvBuffer, pData, nDataSize);
+ monitor.readCount++;
+ bReadOk = TRUE;
+ }
+ SetEvent(monitor.hEvent);
+ };
+
+
+ bReadOk = FALSE;
+ m_pChannel->readData(monitor.softComponent, monitor.beginAddr, monitor.readLen, funOnReadData);
+ WaitForSingleObject(monitor.hEvent, INFINITE);
+ ResetEvent(monitor.hEvent);
+ if (bReadOk) {
+ ASSERT(m_listener.onMonitorData);
+ m_listener.onMonitorData(this, monitor.id);
+ }
+}
+
+bool CPLC::isConnected()
+{
+ return m_pChannel->isConnected();
+}
+
+int CPLC::readWord(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+ ONREAD funOnRead)
+{
+ return m_pChannel->readWord(softComponent, addr, funOnRead);
+}
+
+int CPLC::readData(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+ unsigned int nReadLen, ONREADDATA funOnReadData)
+{
+ return m_pChannel->readData(softComponent, addr, nReadLen, funOnReadData);
+}
+
+int CPLC::writeBit(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+ BOOL bValue, ONWRITE funOnWrite)
+{
+ return m_pChannel->writeBit(softComponent, addr, bValue, funOnWrite);
+}
+
+int CPLC::writeWord(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+ int value, ONWRITE funOnWrite)
+{
+ return m_pChannel->writeWord(softComponent, addr, value, funOnWrite);
+}
+
+int CPLC::writeData(MC::SOFT_COMPONENT softComponent, unsigned int addr,
+ const char* pszData, unsigned int length, ONWRITE funOnWrite)
+{
+ return m_pChannel->writeData(softComponent, addr, pszData, length, funOnWrite);
+}
+
+CString& CPLC::dataToHexString(const char* pData, const int size, CString& strOut)
+{
+ strOut.Empty();
+ for (int i = 0; i < size; i++) {
+ if (i < size - 1) {
+ strOut.AppendFormat(_T("%02X "), (BYTE)pData[i]);
+ }
+ else {
+ strOut.AppendFormat(_T("%02X"), (BYTE)pData[i]);
+ }
+ }
+
+ return strOut;
+}
+
+void CPLC::setActionInterval(unsigned int nInterval)
+{
+ m_nActionInterval = nInterval;
+}
+
+void CPLC::setState(PLCSTATE state)
+{
+ m_state = state;
+ if (m_listener.onStateChanged != nullptr) {
+ m_listener.onStateChanged(this, (int)m_state);
+ }
+}
+
+void CPLC::OnTimer(UINT nTimerid)
+{
+ static int iii = 0;
+ iii++;
+ if (iii % 5 == 3) {
+ if (!m_pChannel->isConnected())
+ m_pChannel->connect();
+ }
+}
\ No newline at end of file
--
Gitblit v1.9.3