1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#pragma once
 
#include "CCLinkIEControl.h"
 
#include <thread>
#include <atomic>
#include <functional>
#include <vector>
 
using OutValuesArray = std::array<double, 4>;
using Callback = std::function<void()>;
using AnalyzeCallback = std::function<OutValuesArray()>;
using LogCallback = std::function<void(const CString& strContent, int type)>;
 
class CPLCSignalListener
{
public:
    CPLCSignalListener();
    ~CPLCSignalListener();
 
    bool Initialize(StationIdentifier station, int nIntervalMs = 200);
 
    void SetStartCallback(Callback cb);
    void SetStopCallback(Callback cb);
    void SetAnalyzeCallback(AnalyzeCallback cb);
    void SetLogCallback(LogCallback cb);
 
    bool Start();
    void Stop();
 
    bool WriteOutValues(const OutValuesArray& values);
 
private:
    void LogInfo(const CString& strText, int nType);
    bool SendHeartbeat();
    bool CheckHeartbeat();
    bool MonitorHeartbeat();
    void StartHeartbeatMonitor();
    void StopHeartbeatMonitor();
    void PulseBitDevice(DeviceType eDevType, long nBitNo, int nDelayMs = 50);
    void HandleAckLife(int i, bool bCurrTriggerBit);
    void ThreadProc();
 
private:
    // === PLC Í¨ÐźËÐĶÔÏó ===
    std::unique_ptr<CCCLinkIEControl> m_pPlc; // PLC Í¨ÐÅ¿ØÖÆÆ÷
    StationIdentifier m_station;              // PLC Õ¾ºÅ
    std::atomic<bool> m_bConnected{ false };  // ÊÇ·ñ³É¹¦Á¬½Ó
 
    // === ¿ØÖƲÎÊý ===
    int m_nIntervalMs = 200;                  // ÂÖѯÖÜÆÚ£¨ms£©
 
    // === ÃüÁî´¥·¢×´Ì¬»º´æ ===
    std::vector<bool> m_vecPrevBits;          // ÉÏÒ»ÖÜÆÚµÄÃüÁîλ״̬£¨ÓÃÓÚ¼ì²âÉÏÉýÑØ£©
 
    // === »Øµ÷º¯Êý£¨¿ØÖÆ/¼ÆËã/ÈÕÖ¾£©===
    Callback m_cbStart;                       // Start ÃüÁî»Øµ÷
    Callback m_cbStop;                        // Stop ÃüÁî»Øµ÷
    AnalyzeCallback m_cbAnalyze;              // Analyze ¼ÆËã»Øµ÷£¨·µ»Ø OUT1~OUT4£©
    LogCallback m_cbLog;                      // ÈÕÖ¾Êä³ö»Øµ÷
 
    // === Ö÷Ï߳̿ØÖÆ ===
    std::atomic<bool> m_bRunning{ false };    // Ö÷¼àÌýÏß³ÌÊÇ·ñÔËÐÐ
    std::thread m_thread;                     // Ö÷¼àÌýÏ̶߳ÔÏó
 
    // === ACK ÐźÅ״̬ ===
    std::array<bool, 2> m_vecAckSent = { false, false }; // ÊÇ·ñÒÑ·¢ËÍÓ¦´ðÐźţ¨B10/B11£©
    std::array<int, 2>  m_vecAckCounter = { 0, 0 };      // ¶ÔÓ¦Ó¦´ðÐźŵÄÉúÃüÖÜÆÚ¼ÆÊýÆ÷
 
    // === ÐÄÌø¼ì²âÏà¹Ø ===
    std::thread m_heartbeatThread;                  // ÐÄÌø¼ì²âÏ̶߳ÔÏó
    std::atomic<bool> m_bHeartbeatRunning = false;  // ÐÄÌøÏß³ÌÔËÐбêÖ¾
    std::atomic<bool> m_bHeartbeatLost = false;     // ÐÄÌø¶ªÊ§±êÖ¾
    int m_nMissedHeartbeatCount = 0;                // ÐÄÌøÎ´±ä»¯´ÎÊý£¨ÓÃÓÚ¼ì²â PLC µôÏߣ©
};