From 0d885fe2e84ac5a6390ddc4d43ab701112eedc64 Mon Sep 17 00:00:00 2001
From: LAPTOP-SNT8I5JK\Boounion <Chenluhua@qq.com>
Date: 星期一, 17 二月 2025 16:53:01 +0800
Subject: [PATCH] 1.各设备Alive状态获取,监听状态变化并回调应用层;
---
SourceCode/Bond/Servo/Servo.vcxproj | 2
SourceCode/Bond/Servo/Servo.vcxproj.filters | 2
SourceCode/Bond/Servo/ToolUnits.cpp | 304 ++++++++++++++++++++++++++++++++++++++
SourceCode/Bond/Servo/CEquipment.cpp | 60 +++++++
SourceCode/Bond/Servo/CMaster.cpp | 27 ++-
SourceCode/Bond/Servo/CMaster.h | 8 +
SourceCode/Bond/Servo/Model.cpp | 7
SourceCode/Bond/Servo/CEquipment.h | 25 +++
SourceCode/Bond/Servo/ToolUnits.h | 32 ++++
9 files changed, 459 insertions(+), 8 deletions(-)
diff --git a/SourceCode/Bond/Servo/CEquipment.cpp b/SourceCode/Bond/Servo/CEquipment.cpp
index 6f8cd0b..6534f88 100644
--- a/SourceCode/Bond/Servo/CEquipment.cpp
+++ b/SourceCode/Bond/Servo/CEquipment.cpp
@@ -1,16 +1,25 @@
#include "stdafx.h"
#include "CEquipment.h"
+#include "ToolUnits.h"
+
namespace SERVO {
CEquipment::CEquipment()
{
+ m_alive = {FALSE, 0, FALSE};
+ m_listener.onAlive = {nullptr};
InitializeCriticalSection(&m_criticalSection);
}
CEquipment::~CEquipment()
{
DeleteCriticalSection(&m_criticalSection);
+ }
+
+ void CEquipment::setListener(EquipmentListener listener)
+ {
+ m_listener.onAlive = listener.onAlive;
}
void CEquipment::init()
@@ -60,6 +69,7 @@
m_blockReadBit.start = start;
m_blockReadBit.end = end;
m_blockReadBit.size = (m_blockReadBit.end - m_blockReadBit.start + 1) / 8;
+ ASSERT(m_blockReadBit.size < BLOCK_BUFFER_MAX);
}
MemoryBlock& CEquipment::getReadBitBlock()
@@ -82,7 +92,19 @@
void CEquipment::onTimer(UINT nTimerid)
{
+ // 每隔一秒,检查一下ALIVE状态
+ static int tick = 0;
+ tick++;
+ if (tick % (4 * 1) == 0) {
+ m_alive.count++;
+ if (m_alive.alive && m_alive.count > ALIVE_TIMEOUT) {
+ m_alive.alive = FALSE;
+ if (m_listener.onAlive != nullptr) {
+ m_listener.onAlive(this, m_alive.alive);
+ }
+ }
+ }
}
void CEquipment::serialize(CArchive& ar)
@@ -90,4 +112,42 @@
}
+ void CEquipment::onReceiveLBData(const char* pszData, size_t size)
+ {
+ TRACE("%s onReceiveLBData: %d bytes\n", m_strName.c_str(), size);
+ for (unsigned int i = 0; i < size; i++) {
+ if (pszData[i] != 0)
+ TRACE("%d[%x]\n", i, pszData[i]);
+ }
+
+
+ // 解释数据
+ BOOL bAliveFlag = isBitOn(pszData, size, 0x340);
+ if (m_alive.flag != bAliveFlag) {
+ m_alive.flag = bAliveFlag;
+ m_alive.count = 0;
+
+ // 状态
+ if (!m_alive.alive) {
+ m_alive.alive = TRUE;
+ if (m_listener.onAlive != nullptr) {
+ m_listener.onAlive(this, m_alive.alive);
+ }
+ }
+ }
+ }
+
+ BOOL CEquipment::isBitOn(const char* pszData, size_t size, int index)
+ {
+ int byteIndex, bitIndex;
+ byteIndex = (index) / 8;
+ bitIndex = (index) % 8;
+
+ return CToolUnits::getBit(pszData[byteIndex], bitIndex);
+ }
+
+ BOOL CEquipment::isAlive()
+ {
+ return m_alive.alive;
+ }
}
diff --git a/SourceCode/Bond/Servo/CEquipment.h b/SourceCode/Bond/Servo/CEquipment.h
index 9f83bb8..37d8e2b 100644
--- a/SourceCode/Bond/Servo/CEquipment.h
+++ b/SourceCode/Bond/Servo/CEquipment.h
@@ -3,13 +3,30 @@
#include "CCLinkIEControl.h"
namespace SERVO {
+#define BLOCK_BUFFER_MAX 1024
+#define ALIVE_TIMEOUT 15
+
+ typedef std::function<void(void* pEiuipment, BOOL bAlive)> ONALIVE;
+ typedef struct _EquipmentListener
+ {
+ ONALIVE onAlive;
+ } EquipmentListener;
+
// Memory Block 结构体定义
typedef struct _MemoryBlock {
unsigned int type;
unsigned int start;
unsigned int end;
unsigned int size;
+ char buffer[BLOCK_BUFFER_MAX];
} MemoryBlock;
+
+ // ALIVE
+ typedef struct _ALIVE {
+ BOOL flag;
+ int count;
+ BOOL alive;
+ } ALIVE;
class CEquipment
{
@@ -20,6 +37,7 @@
public:
virtual const char* getClassName() = 0;
+ virtual void setListener(EquipmentListener listener);
void setName(const char* pszName);
std::string& getName();
void setDescription(const char* pszDescription);
@@ -34,18 +52,25 @@
virtual void term();
virtual void onTimer(UINT nTimerid);
virtual void serialize(CArchive& ar);
+ virtual void onReceiveLBData(const char* pszData, size_t size);
+ BOOL isAlive();
+
+ private:
+ BOOL isBitOn(const char* pszData, size_t size, int index);
protected:
inline void Lock() { EnterCriticalSection(&m_criticalSection); }
inline void Unlock() { LeaveCriticalSection(&m_criticalSection); }
protected:
+ EquipmentListener m_listener;
std::string m_strName;
std::string m_strDescription;
CRITICAL_SECTION m_criticalSection;
StationIdentifier m_station;
MemoryBlock m_blockReadBit;
MemoryBlock m_blockWriteBit;
+ ALIVE m_alive;
};
}
diff --git a/SourceCode/Bond/Servo/CMaster.cpp b/SourceCode/Bond/Servo/CMaster.cpp
index 85bf38e..5ea975d 100644
--- a/SourceCode/Bond/Servo/CMaster.cpp
+++ b/SourceCode/Bond/Servo/CMaster.cpp
@@ -12,7 +12,7 @@
CMaster::CMaster()
{
-
+ m_listener = {nullptr};
}
CMaster::~CMaster()
@@ -21,6 +21,11 @@
delete item;
}
m_listEquipment.clear();
+ }
+
+ void CMaster::setListener(MasterListener listener)
+ {
+ m_listener.onEqAlive = listener.onEqAlive;
}
int CMaster::init()
@@ -93,7 +98,16 @@
int CMaster::addEquipment(CEquipment* pEquipment)
{
+ EquipmentListener listener;
+ listener.onAlive = [&](void* pEquipment, BOOL bAlive) -> void {
+ CEquipment* p = (CEquipment*)pEquipment;
+ if (m_listener.onEqAlive != nullptr) {
+ m_listener.onEqAlive(this, p, bAlive);
+ }
+ };
+ pEquipment->setListener(listener);
m_listEquipment.push_back(pEquipment);
+
return 0;
}
@@ -104,7 +118,7 @@
}
- // 以下为测试代码
+ // 按一定频率扫描LB数据
static int i = 0;
i++;
if (i % (4 * 1) == 0) {
@@ -113,14 +127,11 @@
const StationIdentifier& station = item->getStation();
MemoryBlock& block = item->getReadBitBlock();
- char szBuffer[1024];
int nRet = m_cclink.ReadData2(station, (short)block.type,
- block.start, block.size, szBuffer);
- for (unsigned int i = 0; i < block.size; i++) {
- if(szBuffer[i] != 0)
- TRACE("%d[%x]\n", i, szBuffer[i]);
+ block.start, block.size, block.buffer);
+ if (0 == nRet) {
+ item->onReceiveLBData(block.buffer, block.size);
}
- TRACE("nRet=%d\n", nRet);
}
}
}
diff --git a/SourceCode/Bond/Servo/CMaster.h b/SourceCode/Bond/Servo/CMaster.h
index ad4d0df..f120b12 100644
--- a/SourceCode/Bond/Servo/CMaster.h
+++ b/SourceCode/Bond/Servo/CMaster.h
@@ -7,6 +7,12 @@
namespace SERVO {
+ typedef std::function<void(void* pMaster, CEquipment* pEiuipment, BOOL bAlive)> ONEQALIVE;
+ typedef struct _MasterListener
+ {
+ ONEQALIVE onEqAlive;
+ } MasterListener;
+
class CMaster
{
public:
@@ -15,6 +21,7 @@
public:
+ void setListener(MasterListener listener);
int init();
int term();
void onTimer(UINT nTimerid);
@@ -25,6 +32,7 @@
private:
+ MasterListener m_listener;
CCCLinkIEControl m_cclink;
std::list<CEquipment*> m_listEquipment;
};
diff --git a/SourceCode/Bond/Servo/Model.cpp b/SourceCode/Bond/Servo/Model.cpp
index 7009492..a7db1b4 100644
--- a/SourceCode/Bond/Servo/Model.cpp
+++ b/SourceCode/Bond/Servo/Model.cpp
@@ -89,6 +89,13 @@
m_hsmsPassive.init(this, "APP", 7000);
+ SERVO::MasterListener masterListener;
+ masterListener.onEqAlive = [&](void* pMaster, SERVO::CEquipment* pEquipment, BOOL bAlive) -> void {
+ LOGI("<CModel>Equipment onAlive:%d.\n", pEquipment->getName().c_str(),
+ bAlive ? _T("ON") : _T("OFF"));
+ };
+ m_master.setListener(masterListener);
+
return 0;
}
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj b/SourceCode/Bond/Servo/Servo.vcxproj
index 3fa06f5..864617a 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj
+++ b/SourceCode/Bond/Servo/Servo.vcxproj
@@ -221,6 +221,7 @@
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="TerminalDisplayDlg.h" />
+ <ClInclude Include="ToolUnits.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AlarmManager.cpp" />
@@ -251,6 +252,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="TerminalDisplayDlg.cpp" />
+ <ClCompile Include="ToolUnits.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Servo.rc" />
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj.filters b/SourceCode/Bond/Servo/Servo.vcxproj.filters
index 28a906c..ae0f9c1 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj.filters
+++ b/SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -34,6 +34,7 @@
<ClCompile Include="CBonder.cpp" />
<ClCompile Include="CMaster.cpp" />
<ClCompile Include="CEFEM.cpp" />
+ <ClCompile Include="ToolUnits.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="AlarmManager.h" />
@@ -66,6 +67,7 @@
<ClInclude Include="CBonder.h" />
<ClInclude Include="CMaster.h" />
<ClInclude Include="CEFEM.h" />
+ <ClInclude Include="ToolUnits.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Servo.rc" />
diff --git a/SourceCode/Bond/Servo/ToolUnits.cpp b/SourceCode/Bond/Servo/ToolUnits.cpp
new file mode 100644
index 0000000..664f802
--- /dev/null
+++ b/SourceCode/Bond/Servo/ToolUnits.cpp
@@ -0,0 +1,304 @@
+#include "stdafx.h"
+#include "ToolUnits.h"
+#include <chrono>
+#include <memory>
+
+
+CToolUnits::CToolUnits()
+{
+}
+
+
+CToolUnits::~CToolUnits()
+{
+}
+
+std::string CToolUnits::timeToString(ULONGLONG time)
+{
+ ULONGLONG time1, time2;
+ time1 = time / 1000000000;
+ time2 = time % 1000000000;
+
+ char buffer1[256], buffer[128];
+ struct tm timeinfo;
+ time_t t = time_t(time1);
+ localtime_s(&timeinfo, &t);
+ strftime(buffer, 128, "%Y-%m-%d %H:%M:%S", &timeinfo);
+ sprintf_s(buffer1, 256, "%s.%lld", buffer, time2);
+ return std::string(buffer1);
+}
+
+std::string CToolUnits::timeToString2(ULONGLONG time)
+{
+ ULONGLONG time1;
+ time1 = time / 1000;
+
+ char buffer[256];
+ struct tm timeinfo;
+ time_t t = time_t(time1);
+ localtime_s(&timeinfo, &t);
+ strftime(buffer, 128, "%Y-%m-%d %H:%M:%S", &timeinfo);
+ return std::string(buffer);
+}
+
+std::string CToolUnits::timeToString3(ULONGLONG time)
+{
+ ULONGLONG time1;
+ int ms;
+ time1 = time / 1000;
+ ms = time % 1000;
+
+ char buffer1[256], buffer[128];
+ struct tm timeinfo;
+ time_t t = time_t(time1);
+ localtime_s(&timeinfo, &t);
+ strftime(buffer, 128, "%Y-%m-%d %H:%M:%S", &timeinfo);
+ sprintf_s(buffer1, 256, "%s.%03d", buffer, ms);
+ return std::string(buffer1);
+}
+
+ULONGLONG CToolUnits::stringToTime(const char* pszTime)
+{
+ struct tm tm;
+
+ memset(&tm, 0, sizeof(tm));
+ sscanf_s(pszTime, "%d-%d-%d %d:%d:%d",
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
+ &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
+ tm.tm_year -= 1900;
+ tm.tm_mon--;
+
+ return mktime(&tm) * 1000;
+}
+
+ULONGLONG CToolUnits::getTimestamp()
+{
+ auto now = std::chrono::system_clock::now();
+ auto duration_in_milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch());
+ uint64_t timestamp = duration_in_milliseconds.count();
+ return timestamp;
+}
+
+void CToolUnits::createDir(const char* pszDir)
+{
+ if (isDirectory(std::string(pszDir))) {
+ return;
+ }
+
+ CString strDir = pszDir;
+ int lastIndex = 0;
+ int index = strDir.Find(_T("\\"), lastIndex);
+ while (index > 0) {
+ CString strTempDir = strDir.Left(index);
+ CreateDirectory(strTempDir, NULL);
+
+ lastIndex = index + 1;
+ index = strDir.Find(_T("\\"), lastIndex);
+ }
+ CreateDirectory(strDir, NULL);
+}
+
+CString& CToolUnits::floatToString1(float value, CString& strOut)
+{
+ strOut.Format(_T("%.1f"), value);
+ return strOut;
+}
+
+CString& CToolUnits::floatToString3(float value, CString& strOut)
+{
+ strOut.Format(_T("%.3f"), value);
+ return strOut;
+}
+
+
+BOOL CToolUnits::copyTextToClipboard(CWnd* pWnd, const CString& strText)
+{
+ if (OpenClipboard(pWnd->GetSafeHwnd())) {
+ EmptyClipboard();
+
+ HGLOBAL hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (strText.GetLength() + 1) * sizeof(TCHAR));
+ if (hglbCopy == NULL) {
+ CloseClipboard();
+ return FALSE;
+ }
+
+ LPTSTR lptstrCopy = (LPTSTR)GlobalLock(hglbCopy);
+ strcpy_s(lptstrCopy, strText.GetLength()+1, strText);
+ GlobalUnlock(hglbCopy);
+ SetClipboardData(CF_TEXT, hglbCopy);
+ CloseClipboard();
+ GlobalFree(hglbCopy);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+std::string CToolUnits::getCurrentExePath() {
+ char path[MAX_PATH];
+ GetModuleFileName(NULL, path, MAX_PATH);
+ std::string exePath(path);
+ return exePath.substr(0, exePath.find_last_of("\\/"));
+}
+
+bool CToolUnits::isFile(const std::string& path) {
+ DWORD attributes = GetFileAttributes(path.c_str());
+ return (attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY));
+}
+
+bool CToolUnits::isDirectory(const std::string& path) {
+ DWORD attributes = GetFileAttributes(path.c_str());
+ return (attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY));
+}
+
+int CToolUnits::toInt32(const char* pBuffer)
+{
+ return (pBuffer[0] & 0xff) | ((pBuffer[1] & 0xff) << 8) | ((pBuffer[2] & 0xff) << 16) | ((pBuffer[3] & 0xff) << 24);
+}
+
+int CToolUnits::toInt16(const char* pBuffer)
+{
+ return (pBuffer[0] & 0xff) | (pBuffer[1] & 0xff) << 8;
+}
+
+BOOL CToolUnits::getBit(const char c, int index)
+{
+ switch (index)
+ {
+ case 0:
+ return c & 0x01;
+ break;
+ case 1:
+ return c & 0x02;
+ break;
+ case 2:
+ return c & 0x04;
+ break;
+ case 3:
+ return c & 0x08;
+ break;
+ case 4:
+ return c & 0x10;
+ break;
+ case 5:
+ return c & 0x20;
+ break;
+ case 6:
+ return c & 0x40;
+ break;
+ case 7:
+ return c & 0x80;
+ break;
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+void CToolUnits::setBit(char* p, int index)
+{
+ int byteIndex = 0;
+ byte b = 0;
+ if (index >= 8) byteIndex = 1;
+ switch (index)
+ {
+ case 0:
+ case 8:
+ b = 0x1;
+ break;
+ case 1:
+ case 9:
+ b = 0x2;
+ break;
+ case 2:
+ case 0xA:
+ b = 0x4;
+ break;
+ case 3:
+ case 0xB:
+ b = 0x8;
+ break;
+ case 4:
+ case 0xC:
+ b = 0x10;
+ break;
+ case 5:
+ case 0xD:
+ b = 0x20;
+ break;
+ case 6:
+ case 0xE:
+ b = 0x40;
+ break;
+ case 7:
+ case 0xF:
+ b = 0x80;
+ break;
+ default:
+ break;
+ }
+
+ p[byteIndex] = b;
+}
+
+void CToolUnits::setDlgItemDouble(CWnd* pWnd, int nCtrlId, double value)
+{
+ CString strText;
+ strText.Format(_T("%.03f"), value);
+ pWnd->SetDlgItemText(nCtrlId, strText);
+}
+
+std::vector<CString> CToolUnits::GetFileNamesInDirectory(const CString& strFolderPath, const CString& strExtension)
+{
+ std::vector<CString> fileNames;
+
+ // 确保目录路径最后有反斜杠
+ CString strSearchPath = strFolderPath;
+ if (strSearchPath[strSearchPath.GetLength() - 1] != '\\') {
+ strSearchPath += '\\';
+ }
+
+ CString finalExtension = strExtension;
+ if (finalExtension.Find('.') == -1) {
+ finalExtension = '.' + finalExtension;
+ }
+ strSearchPath += "*" + finalExtension;
+
+ std::unique_ptr<CFileFind> finder = std::make_unique<CFileFind>();
+ BOOL bWorking = finder->FindFile(strSearchPath);
+
+ // 遍历文件夹
+ while (bWorking) {
+ bWorking = finder->FindNextFile();
+ if (!finder->IsDirectory()) {
+ CString fileName = finder->GetFileName();
+ int dotPos = fileName.ReverseFind('.');
+ if (dotPos != -1) {
+ fileName = fileName.Left(dotPos);
+ }
+ fileNames.push_back(fileName);
+ }
+ }
+
+ return fileNames;
+}
+
+std::string CToolUnits::getRecipePath()
+{
+ return getCurrentExePath() + "\\Recipe";
+}
+
+std::string CToolUnits::getCurrentTimeString()
+{
+ struct tm ltm;
+ time_t now = time(0);
+ localtime_s(<m, &now); // 使用安全的 localtime_s 函数
+
+ char buffer[256];
+ sprintf_s(buffer, sizeof(buffer), "%04d-%02d-%02d %02d:%02d:%02d",
+ ltm.tm_year + 1900, ltm.tm_mon + 1, ltm.tm_mday,
+ ltm.tm_hour, ltm.tm_min, ltm.tm_sec);
+
+ return std::string(buffer);
+}
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/ToolUnits.h b/SourceCode/Bond/Servo/ToolUnits.h
new file mode 100644
index 0000000..9e8fdfb
--- /dev/null
+++ b/SourceCode/Bond/Servo/ToolUnits.h
@@ -0,0 +1,32 @@
+#pragma once
+#include <string>
+
+class CToolUnits
+{
+public:
+ CToolUnits();
+ ~CToolUnits();
+
+public:
+ static std::string timeToString(ULONGLONG time);
+ static std::string timeToString2(ULONGLONG time);
+ static std::string timeToString3(ULONGLONG time);
+ static ULONGLONG stringToTime(const char* pszTime);
+ static CString& floatToString1(float value, CString& strOut);
+ static CString& floatToString3(float value, CString& strOut);
+ static ULONGLONG getTimestamp();
+ static void createDir(const char* pszDir);
+ static BOOL copyTextToClipboard(CWnd* pWnd, const CString& strText);
+ static std::string getCurrentExePath();
+ static bool isFile(const std::string& path);
+ static bool isDirectory(const std::string& path);
+ static int toInt32(const char* pBuffer);
+ static int toInt16(const char* pBuffer);
+ static BOOL getBit(const char c, int index);
+ static void setBit(char* p, int index);
+ static void setDlgItemDouble(CWnd* pWnd, int nCtrlId, double value);
+ static std::vector<CString> GetFileNamesInDirectory(const CString& strFolderPath, const CString& strExtension);
+ static std::string getRecipePath();
+ static std::string getCurrentTimeString();
+};
+
--
Gitblit v1.9.3