#pragma once #include "CCLinkIEControl.h" #include #include #include #include using OutValuesArray = std::array; using Callback = std::function; using AnalyzeCallback = std::function; using LogCallback = std::function; class CPLCSignalListener { public: CPLCSignalListener(); ~CPLCSignalListener(); /** * @brief ³õʼ»¯ PLC ÐźżàÌýÆ÷¡£ * * @param station Ä¿±ê PLC µÄÕ¾ºÅ±êʶ·û¡£ * @param nIntervalMs ÂÖѯÖÜÆÚ£¨µ¥Î»£ººÁÃ룩£¬Ä¬ÈÏ 200ms¡£ * @return true ³õʼ»¯³É¹¦¡£ * @return false ³õʼ»¯Ê§°Ü¡£ */ bool Initialize(StationIdentifier station, int nIntervalMs = 200); /** * @brief ÉèÖÿªÊ¼ÃüÁîµÄ»Øµ÷º¯Êý£¨¶ÔÓ¦ PLC µÄ Start Ðźţ©¡£ * * @param cb Óû§×Ô¶¨ÒåµÄ¿ªÊ¼»Øµ÷º¯Êý¡£ */ void SetStartCallback(Callback cb); /** * @brief ÉèÖÃÍ£Ö¹ÃüÁîµÄ»Øµ÷º¯Êý£¨¶ÔÓ¦ PLC µÄ Stop Ðźţ©¡£ * * @param cb Óû§×Ô¶¨ÒåµÄÍ£Ö¹»Øµ÷º¯Êý¡£ */ void SetStopCallback(Callback cb); /** * @brief ÉèÖ÷ÖÎö¼ÆËã»Øµ÷º¯Êý£¬ÔÚ½ÓÊÕµ½Í£Ö¹ÃüÁîºóµ÷Óᣠ* * @param cb ·µ»Ø¼ÆËã½á¹ûÊý×飨OUT1~OUT4£©µÄº¯Êý¡£ */ void SetAnalyzeCallback(AnalyzeCallback cb); /** * @brief ÉèÖÃÈÕÖ¾Êä³ö»Øµ÷º¯Êý¡£ * * @param cb Óû§ÌṩµÄÈÕÖ¾Êä³ö½Ó¿Ú£¨°üº¬ÈÕÖ¾ÄÚÈݺÍÈÕÖ¾ÀàÐÍ£©¡£ */ void SetLogCallback(LogCallback cb); /** * @brief Æô¶¯ÐźżàÌýÏ̡߳£ * * @return true Æô¶¯³É¹¦¡£ * @return false Æô¶¯Ê§°Ü£¨¿ÉÄÜÒÑÔËÐлòδ³õʼ»¯£©¡£ */ bool Start(); /** * @brief Í£Ö¹ÐźżàÌýÏ̡߳£ */ void Stop(); /** * @brief Ïò PLC дÈë·ÖÎö½á¹ûÖµ£¨Í¨³£Îª OUT1 ~ OUT4£©¡£ * * @param values °üº¬Ëĸö double ÀàÐ͵Ľá¹ûÖµ£¬½«×ª»»ÎªÕûÊýºóдÈë PLC¡£ * @return true дÈë³É¹¦¡£ * @return false дÈëʧ°Ü¡£ */ bool WriteOutValues(const OutValuesArray& values); private: /** * @brief Êä³öÈÕÖ¾ÐÅÏ¢£¨·â×°ÈÕÖ¾»Øµ÷£©¡£ * * @param strText ÈÕÖ¾ÄÚÈÝÎı¾¡£ * @param nType ÈÕÖ¾ÀàÐÍ£¨LOG_TYPE_NORMAL / ERROR / WARNING µÈ£©¡£ */ void LogInfo(const CString& strText, int nType); /** * @brief Ïò PLC дÈëÐÄÌøÐźţ¨½»ÌæÎ»£©¡£ * * @return true дÈë³É¹¦¡£ * @return false дÈëʧ°Ü£¨ÈçδÁ¬½Ó£©¡£ */ bool SendHeartbeat(); /** * @brief ¼ì²é´Ó PLC ¶ÁÈ¡µ½µÄÐÄÌøÐźÅÊÇ·ñ·¢Éú±ä»¯¡£ * * @return true ÐÄÌøÓб仯£¨PLC Õý³£ÔÚÏߣ©¡£ * @return false ÐÄÌøÎޱ仯£¨¿ÉÄÜÀëÏߣ©¡£ */ bool CheckHeartbeat(); /** * @brief ¼à¿Ø PLC ÐÄÌøÊÇ·ñÖжϣ¬²¢×Ô¶¯¼Ç¼״̬¡£ * * @return true PLC ÔÚÏß»òÔÚÔÊÐíµÄδÏìÓ¦´ÎÊýÄÚ¡£ * @return false PLC ÐÄÌøÖжϣ¬³¬¹ýÔÊÐíãÐÖµ¡£ */ bool MonitorHeartbeat(); /** * @brief Æô¶¯ÐÄÌø¼à¿ØỊ̈߳¨¶ÀÁ¢ÓÚÐźżàÌýỊ̈߳©¡£ */ void StartHeartbeatMonitor(); /** * @brief Í£Ö¹ÐÄÌø¼à¿ØÏ̡߳£ */ void StopHeartbeatMonitor(); /** * @brief ÏòÖ¸¶¨ÈíÔª¼þλдÈëÒ»¸öÂö³å£¨ÏÈд1£¬ÑÓʱºó×Ô¶¯Ð´0£©¡£ * * @param eDevType λÈíÔª¼þÀàÐÍ£¨Èç M/B£©¡£ * @param nBitNo λµØÖ·±àºÅ¡£ * @param nDelayMs Âö³å³ÖÐøÊ±¼ä£¬Ä¬ÈÏ50ºÁÃë¡£ */ void PulseBitDevice(DeviceType eDevType, long nBitNo, int nDelayMs = 50); /** * @brief ¹ÜÀí ACK ÏìÓ¦µÄÉúÃüÖÜÆÚ£¬³¬Ê±×Ô¶¯Çå³ý¡£ * * @param i ¿ØÖÆÎ»Ë÷Òý£¨0=Start£¬1=Stop£©¡£ * @param bCurrTriggerBit µ±Ç°´Ó PLC ¶ÁÈ¡µ½µÄ´¥·¢Î»×´Ì¬¡£ */ void HandleAckLife(int i, bool bCurrTriggerBit); /** * @brief Ö÷¼àÌýÏß³ÌÂß¼­£¬Ñ­»·¶ÁÈ¡ PLC ¿ØÖÆÐźŲ¢´¦Àí´¥·¢¡£ */ void ThreadProc(); private: // === PLC ͨÐźËÐĶÔÏó === std::unique_ptr m_pPlc; // PLC ͨÐÅ¿ØÖÆÆ÷ StationIdentifier m_station; // PLC Õ¾ºÅ std::atomic m_bConnected{ false }; // ÊÇ·ñ³É¹¦Á¬½Ó // === ¿ØÖƲÎÊý === int m_nIntervalMs = 200; // ÂÖѯÖÜÆÚ£¨ms£© // === ÃüÁî´¥·¢×´Ì¬»º´æ === std::vector m_vecPrevBits; // ÉÏÒ»ÖÜÆÚµÄÃüÁîλ״̬£¨ÓÃÓÚ¼ì²âÉÏÉýÑØ£© // === »Øµ÷º¯Êý£¨¿ØÖÆ/¼ÆËã/ÈÕÖ¾£©=== Callback m_cbStart; // Start ÃüÁî»Øµ÷ Callback m_cbStop; // Stop ÃüÁî»Øµ÷ AnalyzeCallback m_cbAnalyze; // Analyze ¼ÆËã»Øµ÷£¨·µ»Ø OUT1~OUT4£© LogCallback m_cbLog; // ÈÕÖ¾Êä³ö»Øµ÷ // === Ö÷Ï߳̿ØÖÆ === std::atomic m_bRunning{ false }; // Ö÷¼àÌýÏß³ÌÊÇ·ñÔËÐÐ std::thread m_thread; // Ö÷¼àÌýÏ̶߳ÔÏó // === ACK ÐźÅ״̬ === std::array m_vecAckSent = { false, false }; // ÊÇ·ñÒÑ·¢ËÍÓ¦´ðÐźţ¨B10/B11£© std::array m_vecAckCounter = { 0, 0 }; // ¶ÔÓ¦Ó¦´ðÐźŵÄÉúÃüÖÜÆÚ¼ÆÊýÆ÷ // === ÐÄÌø¼ì²âÏà¹Ø === std::thread m_heartbeatThread; // ÐÄÌø¼ì²âÏ̶߳ÔÏó std::atomic m_bHeartbeatRunning = false; // ÐÄÌøÏß³ÌÔËÐбêÖ¾ std::atomic m_bHeartbeatLost = false; // ÐÄÌø¶ªÊ§±êÖ¾ int m_nMissedHeartbeatCount = 0; // ÐÄÌøÎ´±ä»¯´ÎÊý£¨ÓÃÓÚ¼ì²â PLC µôÏߣ© };