| | |
| | | CCCLinkIEControl::~CCCLinkIEControl() = default; |
| | | |
| | | int CCCLinkIEControl::SetBoardModeEx(CCLinkIEControlMode mode) { |
| | | return SetBoardMode(static_cast<short>(mode)); |
| | | return SetBoardMode(static_cast<short>(mode)); |
| | | } |
| | | |
| | | CCLinkIEControlMode CCCLinkIEControl::GetBoardModeEx() { |
| | | short nMode = 0; |
| | | const int nResult = GetBoardMode(nMode); |
| | | if (nResult != 0) { |
| | | return CCLinkIEControlMode::UNKNOWN; |
| | | } |
| | | short nMode = 0; |
| | | const int nResult = GetBoardMode(nMode); |
| | | if (nResult != 0) { |
| | | return CCLinkIEControlMode::UNKNOWN; |
| | | } |
| | | |
| | | return ConvertToCCLinkIEControlMode(nMode); |
| | | return ConvertToCCLinkIEControlMode(nMode); |
| | | } |
| | | |
| | | int CCCLinkIEControl::GetBoardStatusEx(BoardStatus& status) { |
| | | const int nResult = GetBoardStatus(status); |
| | | if (nResult != 0) { |
| | | return nResult; |
| | | } |
| | | const int nResult = GetBoardStatus(status); |
| | | if (nResult != 0) { |
| | | return nResult; |
| | | } |
| | | |
| | | return ValidateBoardStatus(status); |
| | | return ValidateBoardStatus(status); |
| | | } |
| | | |
| | | int CCCLinkIEControl::ReadLedStatus(LedStatus& outLedStatus) { |
| | | std::vector<short> vecLedBuffer; |
| | | const int nRet = ReadBoardLed(vecLedBuffer); |
| | | if (nRet != 0) { |
| | | return nRet; |
| | | } |
| | | std::vector<short> vecLedBuffer; |
| | | const int nRet = ReadBoardLed(vecLedBuffer); |
| | | if (nRet != 0) { |
| | | return nRet; |
| | | } |
| | | |
| | | if (vecLedBuffer.empty()) { |
| | | UpdateLastError(ERROR_CODE_INVALID_DATA); |
| | | return ERROR_CODE_INVALID_DATA; |
| | | } |
| | | if (vecLedBuffer.empty()) { |
| | | UpdateLastError(ERROR_CODE_INVALID_DATA); |
| | | return ERROR_CODE_INVALID_DATA; |
| | | } |
| | | |
| | | // è§£æåä½ç¶æ |
| | | const short nBuffer = vecLedBuffer[0]; |
| | | outLedStatus.bExtPw = (nBuffer & (1 << 15)) != 0; |
| | | outLedStatus.bRd = (nBuffer & (1 << 6)) != 0; |
| | | outLedStatus.bDLnk = (nBuffer & (1 << 5)) != 0; |
| | | outLedStatus.bPrm = (nBuffer & (1 << 4)) != 0; |
| | | outLedStatus.bErr = (nBuffer & (1 << 3)) != 0; |
| | | outLedStatus.bSd = (nBuffer & (1 << 2)) != 0; |
| | | outLedStatus.bMode = (nBuffer & (1 << 1)) != 0; |
| | | outLedStatus.bRun = (nBuffer & (1 << 0)) != 0; |
| | | // è§£æåä½ç¶æ |
| | | const short nBuffer = vecLedBuffer[0]; |
| | | outLedStatus.bExtPw = (nBuffer & (1 << 15)) != 0; |
| | | outLedStatus.bRd = (nBuffer & (1 << 6)) != 0; |
| | | outLedStatus.bDLnk = (nBuffer & (1 << 5)) != 0; |
| | | outLedStatus.bPrm = (nBuffer & (1 << 4)) != 0; |
| | | outLedStatus.bErr = (nBuffer & (1 << 3)) != 0; |
| | | outLedStatus.bSd = (nBuffer & (1 << 2)) != 0; |
| | | outLedStatus.bMode = (nBuffer & (1 << 1)) != 0; |
| | | outLedStatus.bRun = (nBuffer & (1 << 0)) != 0; |
| | | |
| | | return 0; |
| | | return 0; |
| | | } |
| | | |
| | | CCLinkIEControlMode CCCLinkIEControl::ConvertToCCLinkIEControlMode(const short nMode) { |
| | | switch (static_cast<CCLinkIEControlMode>(nMode)) { |
| | | case CCLinkIEControlMode::ONLINE: return CCLinkIEControlMode::ONLINE; // å¨çº¿ |
| | | case CCLinkIEControlMode::OFFLINE: return CCLinkIEControlMode::OFFLINE; // 离线 |
| | | case CCLinkIEControlMode::INTER_STATION_TEST: return CCLinkIEControlMode::INTER_STATION_TEST; // ç«é´æµè¯ |
| | | case CCLinkIEControlMode::LINE_TEST: return CCLinkIEControlMode::LINE_TEST; // 线路æµè¯ |
| | | case CCLinkIEControlMode::LOOPBACK_TEST: return CCLinkIEControlMode::LOOPBACK_TEST; // èªåéæµè¯ |
| | | case CCLinkIEControlMode::HW_TEST: return CCLinkIEControlMode::HW_TEST; // H/Wæµè¯ |
| | | case CCLinkIEControlMode::BUS_IF_TEST: return CCLinkIEControlMode::BUS_IF_TEST; // æ»çº¿I/Fæµè¯ |
| | | default: return CCLinkIEControlMode::UNKNOWN; |
| | | } |
| | | switch (static_cast<CCLinkIEControlMode>(nMode)) { |
| | | case CCLinkIEControlMode::ONLINE: return CCLinkIEControlMode::ONLINE; // å¨çº¿ |
| | | case CCLinkIEControlMode::OFFLINE: return CCLinkIEControlMode::OFFLINE; // 离线 |
| | | case CCLinkIEControlMode::INTER_STATION_TEST: return CCLinkIEControlMode::INTER_STATION_TEST; // ç«é´æµè¯ |
| | | case CCLinkIEControlMode::LINE_TEST: return CCLinkIEControlMode::LINE_TEST; // 线路æµè¯ |
| | | case CCLinkIEControlMode::LOOPBACK_TEST: return CCLinkIEControlMode::LOOPBACK_TEST; // èªåéæµè¯ |
| | | case CCLinkIEControlMode::HW_TEST: return CCLinkIEControlMode::HW_TEST; // H/Wæµè¯ |
| | | case CCLinkIEControlMode::BUS_IF_TEST: return CCLinkIEControlMode::BUS_IF_TEST; // æ»çº¿I/Fæµè¯ |
| | | default: return CCLinkIEControlMode::UNKNOWN; |
| | | } |
| | | } |
| | | |
| | | int CCCLinkIEControl::ValidateBoardStatus(const BoardStatus& status) { |
| | | if (status.nStationValue < 1 || status.nStationValue > 120) { |
| | | return ERROR_CODE_STATION_OUT_OF_RANGE; // ç«å·è¶
åºèå´ |
| | | } |
| | | if (status.nGroupValue < 0 || status.nGroupValue > 32) { |
| | | return ERROR_CODE_GROUP_OUT_OF_RANGE; // ç»è¶
åºèå´ |
| | | } |
| | | if (status.nNetworkValue < 1 || status.nNetworkValue > 239) { |
| | | return ERROR_CODE_NETWORK_OUT_OF_RANGE; // ç½ç»å·è¶
åºèå´ |
| | | } |
| | | return 0; // æ ¡éªéè¿ |
| | | if (status.nStationValue < 1 || status.nStationValue > 120) { |
| | | return ERROR_CODE_STATION_OUT_OF_RANGE; // ç«å·è¶
åºèå´ |
| | | } |
| | | if (status.nGroupValue < 0 || status.nGroupValue > 32) { |
| | | return ERROR_CODE_GROUP_OUT_OF_RANGE; // ç»è¶
åºèå´ |
| | | } |
| | | if (status.nNetworkValue < 1 || status.nNetworkValue > 239) { |
| | | return ERROR_CODE_NETWORK_OUT_OF_RANGE; // ç½ç»å·è¶
åºèå´ |
| | | } |
| | | return 0; // æ ¡éªéè¿ |
| | | } |
| | | |
| | | int CCCLinkIEControl::ReadDataEx(const StationIdentifier& station, DeviceType enDevType, long devNo, long size, void* pData) |
| | | { |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStationAndSize(station, static_cast<short>(size)); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStationAndSize(station, static_cast<short>(size)); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | nRet = mdReceiveEx(m_nPath, station.nNetNo, station.nStNo, nDevType, devNo, &size, pData); |
| | | } |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | nRet = mdReceiveEx(m_nPath, station.nNetNo, station.nStNo, nDevType, devNo, &size, pData); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | } |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | |
| | | #include "PerformanceMelsec.h" |
| | | |
| | | enum class CCLinkIEControlMode : short { |
| | | UNKNOWN = 0x0194, // δ֪ |
| | | ONLINE = 0x0000, // å¨çº¿ |
| | | OFFLINE = 0x0002, // 离线 |
| | | INTER_STATION_TEST = 0x0005, // ç«é´æµè¯ |
| | | LINE_TEST = 0x0006, // 线路æµè¯ |
| | | LOOPBACK_TEST = 0x0007, // èªåéæµè¯ |
| | | HW_TEST = 0x0009, // H/Wæµè¯ |
| | | BUS_IF_TEST = 0x000E // æ»çº¿I/Fæµè¯ |
| | | UNKNOWN = 0x0194, // æªç¥ |
| | | ONLINE = 0x0000, // å¨çº¿ |
| | | OFFLINE = 0x0002, // 离线 |
| | | INTER_STATION_TEST = 0x0005, // ç«é´æµè¯ |
| | | LINE_TEST = 0x0006, // 线路æµè¯ |
| | | LOOPBACK_TEST = 0x0007, // èªåéæµè¯ |
| | | HW_TEST = 0x0009, // H/Wæµè¯ |
| | | BUS_IF_TEST = 0x000E // æ»çº¿I/Fæµè¯ |
| | | }; |
| | | |
| | | class CCCLinkIEControl final : public CPerformanceMelsec { |
| | | public: |
| | | CCCLinkIEControl(); |
| | | ~CCCLinkIEControl() override; |
| | | CCCLinkIEControl(); |
| | | ~CCCLinkIEControl() override; |
| | | |
| | | struct LedStatus { |
| | | bool bExtPw; // å¤é¨çµæºç¶æ (b15) |
| | | bool bRd; // æ°æ®æ¥æ¶ç¶æ (b6) |
| | | bool bDLnk; // æ°æ®é¾æ¥ç¶æ (b5) |
| | | bool bPrm; // 管çåè½ç¶æ (b4) |
| | | bool bErr; // éè¯¯ç¶æ (b3) |
| | | bool bSd; // æ°æ®åéç¶æ (b2) |
| | | bool bMode; // å¨ä½æ¨¡å¼ (b1) |
| | | bool bRun; // è¿è¡ç¶æ (b0) |
| | | struct LedStatus { |
| | | bool bExtPw; // å¤é¨çµæºç¶æ (b15) |
| | | bool bRd; // æ°æ®æ¥æ¶ç¶æ (b6) |
| | | bool bDLnk; // æ°æ®é¾æ¥ç¶æ (b5) |
| | | bool bPrm; // 管çåè½ç¶æ (b4) |
| | | bool bErr; // éè¯¯ç¶æ (b3) |
| | | bool bSd; // æ°æ®åéç¶æ (b2) |
| | | bool bMode; // å¨ä½æ¨¡å¼ (b1) |
| | | bool bRun; // è¿è¡ç¶æ (b0) |
| | | |
| | | // 转æ¢ä¸ºå符串ï¼ç¨äºè°è¯ |
| | | std::string ToString() const { |
| | | std::ostringstream oss; |
| | | oss << "CC-Link IE Control Network LED Status: {" |
| | | << "\n Ext Power: " << (bExtPw ? "ON" : "OFF") |
| | | << "\n Receive Data: " << (bRd ? "Receiving" : "Not Receiving") |
| | | << "\n Data Link: " << (bDLnk ? "Linked" : "Not Linked") |
| | | << "\n Management: " << (bPrm ? "Managing" : "Not Managing") |
| | | << "\n Error: " << (bErr ? "Error Detected" : "No Error") |
| | | << "\n Send Data: " << (bSd ? "Sending" : "Not Sending") |
| | | << "\n Mode: " << (bMode ? "Executing" : "Not Executing") |
| | | << "\n Run: " << (bRun ? "Running" : "Stopped") |
| | | << "\n}"; |
| | | return oss.str(); |
| | | } |
| | | }; |
| | | // 转æ¢ä¸ºå符串ï¼ç¨äºè°è¯ |
| | | std::string ToString() const { |
| | | std::ostringstream oss; |
| | | oss << "CC-Link IE Control Network LED Status: {" |
| | | << "\n Ext Power: " << (bExtPw ? "ON" : "OFF") |
| | | << "\n Receive Data: " << (bRd ? "Receiving" : "Not Receiving") |
| | | << "\n Data Link: " << (bDLnk ? "Linked" : "Not Linked") |
| | | << "\n Management: " << (bPrm ? "Managing" : "Not Managing") |
| | | << "\n Error: " << (bErr ? "Error Detected" : "No Error") |
| | | << "\n Send Data: " << (bSd ? "Sending" : "Not Sending") |
| | | << "\n Mode: " << (bMode ? "Executing" : "Not Executing") |
| | | << "\n Run: " << (bRun ? "Running" : "Stopped") |
| | | << "\n}"; |
| | | return oss.str(); |
| | | } |
| | | }; |
| | | |
| | | // 读åç®æ ç«ç¹CPUç±»å |
| | | // short ReadCPUCodeEx(const StationIdentifier& station, short& nCPUCode); |
| | | // 读åç®æ ç«ç¹CPUç±»å |
| | | // short ReadCPUCodeEx(const StationIdentifier& station, short& nCPUCode); |
| | | |
| | | // æ¿æ¨¡å¼è·å/设置 |
| | | int SetBoardModeEx(CCLinkIEControlMode mode); |
| | | CCLinkIEControlMode GetBoardModeEx(); |
| | | // æ¿æ¨¡å¼è·å/设置 |
| | | int SetBoardModeEx(CCLinkIEControlMode mode); |
| | | CCLinkIEControlMode GetBoardModeEx(); |
| | | |
| | | // è·åæ¿ç¶æ |
| | | int GetBoardStatusEx(BoardStatus& status); |
| | | // è·åæ¿ç¶æ |
| | | int GetBoardStatusEx(BoardStatus& status); |
| | | |
| | | // 读åLEDç¶æ |
| | | int ReadLedStatus(LedStatus& outLedStatus); |
| | | // 读åLEDç¶æ |
| | | int ReadLedStatus(LedStatus& outLedStatus); |
| | | |
| | | int ReadDataEx(const StationIdentifier& station, DeviceType enDevType, long devNo, long size, void* pData); |
| | | int ReadDataEx(const StationIdentifier& station, DeviceType enDevType, long devNo, long size, void* pData); |
| | | |
| | | private: |
| | | static CCLinkIEControlMode ConvertToCCLinkIEControlMode(short nMode); |
| | | static int ValidateBoardStatus(const BoardStatus& status); |
| | | static CCLinkIEControlMode ConvertToCCLinkIEControlMode(short nMode); |
| | | static int ValidateBoardStatus(const BoardStatus& status); |
| | | }; |
| | | |
| | | |
| | |
| | | #define LOG_DEBUG(msg) |
| | | #endif |
| | | |
| | | // åå§åéææååé |
| | | // åå§åéææååé |
| | | std::unordered_map<int, std::string> CPerformanceMelsec::m_mapError = { |
| | | // æ¿åSDKé误ç |
| | | {0, "No error, communication successful."}, |
| | | {1, "Driver not started. The driver is not running."}, |
| | | {2, "Timeout error (board response error). Request not completed within timeout."}, |
| | | {66, "Already OPEN error. The specified channel is OPEN."}, |
| | | {68, "Path error. The specified path is invalid."}, |
| | | {69, "Unsupported function execution error."}, |
| | | {70, "Station number error. The specified station number is invalid."}, |
| | | {71, "No received data error (during RECV function)."}, |
| | | {77, "Memory allocation error / insufficient memory resources."}, |
| | | {85, "SEND/RECV channel number error."}, |
| | | {100, "Board H/W resource busy."}, |
| | | {101, "Routing exception."}, |
| | | {102, "Board driver I/F error: Failed to send request data to the board driver."}, |
| | | {103, "Board driver I/F error: Failed to receive response data from the board driver."}, |
| | | {130, "Initial software component No. Error."}, |
| | | {131, "Capacity error."}, |
| | | {133, "Parameter error."}, |
| | | {16385, "Specified target station number does not exist."}, |
| | | {16386, "Received a request that the target station cannot process."}, |
| | | {16418, "Failed to create the event history file."}, |
| | | {16420, "Failed to access the event history file."}, |
| | | {16421, "Another board driver is using the event history file."}, |
| | | {16432, "The specified soft component type does not exist."}, |
| | | {16433, "Soft component specification error: Out of range or invalid start I/O or block number."}, |
| | | {16512, "Request data exception: Invalid data or unsupported module."}, |
| | | {16685, "File association error: Failed to create the event history file."}, |
| | | {16837, "File association error: Event history file does not exist."}, |
| | | {18944, "Link association error: Network does not exist, unsupported CPU, or incorrect network No./station number."}, |
| | | {-1, "Invalid path. The specified function is not supported for this path."}, |
| | | {-2, "Start component No. error. The specified component is out of range."}, |
| | | {-3, "Capacity error. The capacity exceeds the component range."}, |
| | | {-6, "Component type error. The specified type during write is invalid."}, |
| | | {-8, "Channel No. error. The channel specified is invalid."}, |
| | | {-12, "Target path error. The specified path points to an invalid target."}, |
| | | {-13, "Write protection area error. The specified range is protected."}, |
| | | {-16, "Target path conflict. The path conflicts with write protection settings."}, |
| | | {-17, "Device not found or target not responding."}, |
| | | {-18, "Invalid target. The device does not support the operation."}, |
| | | {-19, "Invalid path operation. An unsupported path operation was executed."}, |
| | | {-31, "DLL library call failed or path not initialized."}, |
| | | {-32, "Resource timeout error. Communication timed out or exceeded resource limits."}, |
| | | {-33, "Communication timeout error. The target is not responding or timed out."}, |
| | | {-34, "Unsupported communication target error. The specified network No. or station No. points to an unsupported model."}, |
| | | {-35, "Registry access error."}, |
| | | {-36, "Registry access error."}, |
| | | {-37, "Communication initialization error. The settings for initializing the communication path are invalid."}, |
| | | {-42, "Key information error. Authentication failed."}, |
| | | {-43, "Marking event error. TC waiting event write was executed on the CPU."}, |
| | | {-61, "Marking event error. TC waiting event write was executed on the CPU."}, |
| | | {-62, "Event waiting timeout. The specified external event waiting timed out."}, |
| | | {-63, "Timeout value is out of range."}, |
| | | {-64, "Timeout value is out of range."}, |
| | | {-65, "Event waiting timeout. The specified external event waiting timed out."}, |
| | | {-66, "Timeout-induced resource shortage."}, |
| | | {-67, "Irrelevant file access execution error."}, |
| | | {-69, "Operation executed, but the module does not support the function."}, |
| | | {-70, "The target event processing module returned a rejection."}, |
| | | {-71, "The remote station did not return data correctly."}, |
| | | {-72, "Pointer error. The specified pointer value is invalid."}, |
| | | {-73, "Specified address error."}, |
| | | {-2174, "Buffer data queue exception occurred. Read/write exception to device."}, |
| | | {-7656, "Buffer data queue exception. Read/write exception to the device."}, |
| | | {-7672, "Buffer data queue exception. Read/write exception to the device."}, |
| | | {-11683, "Buffer data transfer error."}, |
| | | {-11717, "Network No. error."}, |
| | | {-11746, "Station No. error."}, |
| | | {-12128, "Buffer data send/response error."}, |
| | | {-18560, "Module mode setting error."}, |
| | | {-18572, "Communication method error."}, |
| | | {-25056, "Processor error."}, |
| | | {-26334, "Duplicate program call or illegal CPU operation."}, |
| | | {-26336, "Routing request error to a station without routing function support."}, |
| | | {-27902, "Event register timeout error."}, |
| | | {-28079, "Communication No. read error."}, |
| | | {-28080, "Communication No. incorrect error."}, |
| | | {-28136, "Unsupported function in fast mode error."}, |
| | | {-28139, "Link disconnection error."}, |
| | | {-28140, "Incorrect mode setting error."}, |
| | | {-28141, "System reboot error."}, |
| | | {-28142, "Mode error."}, |
| | | {-28143, "Hardware self-diagnosis error."}, |
| | | {-28144, "Hardware self-diagnosis error."}, |
| | | {-28150, "Data reception interruption at remote station error."}, |
| | | {-28151, "Data reception interruption at remote station error."}, |
| | | {-28153, "Data reception interruption at remote station error."}, |
| | | {-28154, "Abnormal data reception error."}, |
| | | {-28158, "Driver WDT error."}, |
| | | {-28160, "Hardware resource error."}, |
| | | {-28622, "Dedicated instruction channel in-use error."}, |
| | | {-28634, "Hardware self-diagnosis error."}, |
| | | {-28636, "Hardware self-diagnosis error."}, |
| | | // æ¿åSDKé误ç |
| | | {0, "No error, communication successful."}, |
| | | {1, "Driver not started. The driver is not running."}, |
| | | {2, "Timeout error (board response error). Request not completed within timeout."}, |
| | | {66, "Already OPEN error. The specified channel is OPEN."}, |
| | | {68, "Path error. The specified path is invalid."}, |
| | | {69, "Unsupported function execution error."}, |
| | | {70, "Station number error. The specified station number is invalid."}, |
| | | {71, "No received data error (during RECV function)."}, |
| | | {77, "Memory allocation error / insufficient memory resources."}, |
| | | {85, "SEND/RECV channel number error."}, |
| | | {100, "Board H/W resource busy."}, |
| | | {101, "Routing exception."}, |
| | | {102, "Board driver I/F error: Failed to send request data to the board driver."}, |
| | | {103, "Board driver I/F error: Failed to receive response data from the board driver."}, |
| | | {130, "Initial software component No. Error."}, |
| | | {131, "Capacity error."}, |
| | | {133, "Parameter error."}, |
| | | {16385, "Specified target station number does not exist."}, |
| | | {16386, "Received a request that the target station cannot process."}, |
| | | {16418, "Failed to create the event history file."}, |
| | | {16420, "Failed to access the event history file."}, |
| | | {16421, "Another board driver is using the event history file."}, |
| | | {16432, "The specified soft component type does not exist."}, |
| | | {16433, "Soft component specification error: Out of range or invalid start I/O or block number."}, |
| | | {16512, "Request data exception: Invalid data or unsupported module."}, |
| | | {16685, "File association error: Failed to create the event history file."}, |
| | | {16837, "File association error: Event history file does not exist."}, |
| | | {18944, "Link association error: Network does not exist, unsupported CPU, or incorrect network No./station number."}, |
| | | {-1, "Invalid path. The specified function is not supported for this path."}, |
| | | {-2, "Start component No. error. The specified component is out of range."}, |
| | | {-3, "Capacity error. The capacity exceeds the component range."}, |
| | | {-6, "Component type error. The specified type during write is invalid."}, |
| | | {-8, "Channel No. error. The channel specified is invalid."}, |
| | | {-12, "Target path error. The specified path points to an invalid target."}, |
| | | {-13, "Write protection area error. The specified range is protected."}, |
| | | {-16, "Target path conflict. The path conflicts with write protection settings."}, |
| | | {-17, "Device not found or target not responding."}, |
| | | {-18, "Invalid target. The device does not support the operation."}, |
| | | {-19, "Invalid path operation. An unsupported path operation was executed."}, |
| | | {-31, "DLL library call failed or path not initialized."}, |
| | | {-32, "Resource timeout error. Communication timed out or exceeded resource limits."}, |
| | | {-33, "Communication timeout error. The target is not responding or timed out."}, |
| | | {-34, "Unsupported communication target error. The specified network No. or station No. points to an unsupported model."}, |
| | | {-35, "Registry access error."}, |
| | | {-36, "Registry access error."}, |
| | | {-37, "Communication initialization error. The settings for initializing the communication path are invalid."}, |
| | | {-42, "Key information error. Authentication failed."}, |
| | | {-43, "Marking event error. TC waiting event write was executed on the CPU."}, |
| | | {-61, "Marking event error. TC waiting event write was executed on the CPU."}, |
| | | {-62, "Event waiting timeout. The specified external event waiting timed out."}, |
| | | {-63, "Timeout value is out of range."}, |
| | | {-64, "Timeout value is out of range."}, |
| | | {-65, "Event waiting timeout. The specified external event waiting timed out."}, |
| | | {-66, "Timeout-induced resource shortage."}, |
| | | {-67, "Irrelevant file access execution error."}, |
| | | {-69, "Operation executed, but the module does not support the function."}, |
| | | {-70, "The target event processing module returned a rejection."}, |
| | | {-71, "The remote station did not return data correctly."}, |
| | | {-72, "Pointer error. The specified pointer value is invalid."}, |
| | | {-73, "Specified address error."}, |
| | | {-2174, "Buffer data queue exception occurred. Read/write exception to device."}, |
| | | {-7656, "Buffer data queue exception. Read/write exception to the device."}, |
| | | {-7672, "Buffer data queue exception. Read/write exception to the device."}, |
| | | {-11683, "Buffer data transfer error."}, |
| | | {-11717, "Network No. error."}, |
| | | {-11746, "Station No. error."}, |
| | | {-12128, "Buffer data send/response error."}, |
| | | {-18560, "Module mode setting error."}, |
| | | {-18572, "Communication method error."}, |
| | | {-25056, "Processor error."}, |
| | | {-26334, "Duplicate program call or illegal CPU operation."}, |
| | | {-26336, "Routing request error to a station without routing function support."}, |
| | | {-27902, "Event register timeout error."}, |
| | | {-28079, "Communication No. read error."}, |
| | | {-28080, "Communication No. incorrect error."}, |
| | | {-28136, "Unsupported function in fast mode error."}, |
| | | {-28139, "Link disconnection error."}, |
| | | {-28140, "Incorrect mode setting error."}, |
| | | {-28141, "System reboot error."}, |
| | | {-28142, "Mode error."}, |
| | | {-28143, "Hardware self-diagnosis error."}, |
| | | {-28144, "Hardware self-diagnosis error."}, |
| | | {-28150, "Data reception interruption at remote station error."}, |
| | | {-28151, "Data reception interruption at remote station error."}, |
| | | {-28153, "Data reception interruption at remote station error."}, |
| | | {-28154, "Abnormal data reception error."}, |
| | | {-28158, "Driver WDT error."}, |
| | | {-28160, "Hardware resource error."}, |
| | | {-28622, "Dedicated instruction channel in-use error."}, |
| | | {-28634, "Hardware self-diagnosis error."}, |
| | | {-28636, "Hardware self-diagnosis error."}, |
| | | |
| | | // èªå®ä¹é误ç |
| | | {ERROR_CODE_UNKNOWN, "Error: Unknown error code."}, |
| | | {ERROR_CODE_NOT_CONNECTED, "Error: Not connected to the device."}, |
| | | {ERROR_CODE_INVALID_PARAM, "Error: Invalid parameter."}, |
| | | {ERROR_CODE_INVALID_DATA, "Error: Invalid data provided."}, |
| | | {ERROR_CODE_STATION_OUT_OF_RANGE, "Error: Station number is out of range."}, |
| | | {ERROR_CODE_GROUP_OUT_OF_RANGE, "Error: Group number is out of range."}, |
| | | {ERROR_CODE_NETWORK_OUT_OF_RANGE, "Error: Network number is out of range."} |
| | | // èªå®ä¹é误ç |
| | | {ERROR_CODE_UNKNOWN, "Error: Unknown error code."}, |
| | | {ERROR_CODE_NOT_CONNECTED, "Error: Not connected to the device."}, |
| | | {ERROR_CODE_INVALID_PARAM, "Error: Invalid parameter."}, |
| | | {ERROR_CODE_INVALID_DATA, "Error: Invalid data provided."}, |
| | | {ERROR_CODE_STATION_OUT_OF_RANGE, "Error: Station number is out of range."}, |
| | | {ERROR_CODE_GROUP_OUT_OF_RANGE, "Error: Group number is out of range."}, |
| | | {ERROR_CODE_NETWORK_OUT_OF_RANGE, "Error: Network number is out of range."} |
| | | }; |
| | | |
| | | ////////////////////////////////////////////////////////////////////// |
| | | // Construction/Destruction |
| | | ////////////////////////////////////////////////////////////////////// |
| | | CPerformanceMelsec::CPerformanceMelsec(const BoardType enBoardType) { |
| | | m_nPath = 0; |
| | | m_enBoardType = enBoardType; |
| | | m_bConnected.store(false); |
| | | m_nPath = 0; |
| | | m_enBoardType = enBoardType; |
| | | m_bConnected.store(false); |
| | | } |
| | | |
| | | // ææå½æ° |
| | | // ææå½æ° |
| | | CPerformanceMelsec::~CPerformanceMelsec() { |
| | | Disconnect(); |
| | | Disconnect(); |
| | | } |
| | | |
| | | // è·åæè¿çéè¯¯ä¿¡æ¯ |
| | | // è·åæè¿çéè¯¯ä¿¡æ¯ |
| | | std::string CPerformanceMelsec::GetLastError() const { |
| | | return m_strLastError; |
| | | return m_strLastError; |
| | | } |
| | | |
| | | // ä¿åéè¯¯ä¿¡æ¯ |
| | | // ä¿åéè¯¯ä¿¡æ¯ |
| | | bool CPerformanceMelsec::SaveErrorInfoToFile(const std::string& filename) { |
| | | // æå¼æä»¶ |
| | | std::ofstream file(filename); |
| | | if (!file.is_open()) { |
| | | std::cerr << "Failed to open file for saving: " << filename << std::endl; |
| | | return false; |
| | | } |
| | | // æå¼æä»¶ |
| | | std::ofstream file(filename); |
| | | if (!file.is_open()) { |
| | | std::cerr << "Failed to open file for saving: " << filename << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | // éåéææååé m_mapError å¹¶å°æ¯ä¸ªé误信æ¯åå
¥æä»¶ |
| | | for (const auto& entry : m_mapError) { |
| | | const int nCode = entry.first; |
| | | const std::string& strMessage = entry.second; |
| | | file << nCode << "|" << strMessage << "\n"; |
| | | } |
| | | file.close(); |
| | | // éåéææååé m_mapError å¹¶å°æ¯ä¸ªé误信æ¯åå
¥æä»¶ |
| | | for (const auto& entry : m_mapError) { |
| | | const int nCode = entry.first; |
| | | const std::string& strMessage = entry.second; |
| | | file << nCode << "|" << strMessage << "\n"; |
| | | } |
| | | file.close(); |
| | | |
| | | return true; |
| | | return true; |
| | | } |
| | | |
| | | // å è½½éè¯¯ä¿¡æ¯ |
| | | // å è½½éè¯¯ä¿¡æ¯ |
| | | bool CPerformanceMelsec::LoadErrorInfoFromFile(const std::string& filename) { |
| | | std::ifstream inFile(filename); |
| | | if (!inFile.is_open()) { |
| | | std::cerr << "Failed to open file for loading: " << filename << std::endl; |
| | | return false; |
| | | } |
| | | std::ifstream inFile(filename); |
| | | if (!inFile.is_open()) { |
| | | std::cerr << "Failed to open file for loading: " << filename << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | m_mapError.clear(); |
| | | std::string line; |
| | | while (std::getline(inFile, line)) { |
| | | std::istringstream iss(line); |
| | | int nCode = 0; |
| | | std::string strToken; |
| | | std::string strMessage; |
| | | m_mapError.clear(); |
| | | std::string line; |
| | | while (std::getline(inFile, line)) { |
| | | std::istringstream iss(line); |
| | | int nCode = 0; |
| | | std::string strToken; |
| | | std::string strMessage; |
| | | |
| | | // 使ç¨åé符 "|" è§£ææ¯ä¸è¡ |
| | | if (std::getline(iss, strToken, '|')) { |
| | | nCode = std::stoi(strToken); |
| | | } |
| | | // 使ç¨åé符 "|" è§£ææ¯ä¸è¡ |
| | | if (std::getline(iss, strToken, '|')) { |
| | | nCode = std::stoi(strToken); |
| | | } |
| | | |
| | | if (std::getline(iss, strToken)) { |
| | | strMessage = strToken; |
| | | } |
| | | if (std::getline(iss, strToken)) { |
| | | strMessage = strToken; |
| | | } |
| | | |
| | | if (!strMessage.empty()) { |
| | | m_mapError[nCode] = strMessage; |
| | | } |
| | | } |
| | | if (!strMessage.empty()) { |
| | | m_mapError[nCode] = strMessage; |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | return true; |
| | | } |
| | | |
| | | // è¿æ¥å°PLC |
| | | // è¿æ¥å°PLC |
| | | int CPerformanceMelsec::Connect(const short nChannel, const short nMode) { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | |
| | | if (m_bConnected.load()) { |
| | | return 0; |
| | | } |
| | | if (m_bConnected.load()) { |
| | | return 0; |
| | | } |
| | | |
| | | const BoardType enBoardType = FindBoardTypeByChannel(nChannel); |
| | | if (enBoardType == BoardType::UNKNOWN || enBoardType != m_enBoardType) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | const BoardType enBoardType = FindBoardTypeByChannel(nChannel); |
| | | if (enBoardType == BoardType::UNKNOWN || enBoardType != m_enBoardType) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | // è¿æ¥PLCï¼æ¾å¼ç±»å转æ¢ä»¥å¹é
mdOpen çç¾å |
| | | const short nRet = mdOpen(nChannel, nMode, &m_nPath); |
| | | if (nRet == 0) { |
| | | m_bConnected.store(true); |
| | | m_enBoardType = enBoardType; |
| | | } |
| | | else { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | // è¿æ¥PLCï¼æ¾å¼ç±»å转æ¢ä»¥å¹é
mdOpen çç¾å |
| | | const short nRet = mdOpen(nChannel, nMode, &m_nPath); |
| | | if (nRet == 0) { |
| | | m_bConnected.store(true); |
| | | m_enBoardType = enBoardType; |
| | | } |
| | | else { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // æå¼è¿æ¥ |
| | | // æå¼è¿æ¥ |
| | | int CPerformanceMelsec::Disconnect() { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | |
| | | short nRet = 0; |
| | | if (m_bConnected.load()) { |
| | | nRet = mdClose(m_nPath); |
| | | m_bConnected.store(false); |
| | | m_nPath = 0; |
| | | } |
| | | short nRet = 0; |
| | | if (m_bConnected.load()) { |
| | | nRet = mdClose(m_nPath); |
| | | m_bConnected.store(false); |
| | | m_nPath = 0; |
| | | } |
| | | |
| | | UpdateLastError(nRet); |
| | | LOG_DEBUG("Close connect."); |
| | | UpdateLastError(nRet); |
| | | LOG_DEBUG("Close connect."); |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // å¯ç¼ç¨æ§å¶å¨è½¯å
ä»¶ä¿¡æ¯è¡¨çåå§å |
| | | // å¯ç¼ç¨æ§å¶å¨è½¯å
ä»¶ä¿¡æ¯è¡¨çåå§å |
| | | int CPerformanceMelsec::InitializeController() { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | |
| | | if (!m_bConnected.load()) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | if (!m_bConnected.load()) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | |
| | | const short nRet = mdInit(m_nPath); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | const short nRet = mdInit(m_nPath); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // è·åçæ¬ä¿¡æ¯ |
| | | // è·åçæ¬ä¿¡æ¯ |
| | | int CPerformanceMelsec::GetBoardVersion(BoardVersion& version) { |
| | | if (!m_bConnected.load()) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | if (!m_bConnected.load()) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | |
| | | // è·åçæ¬ä¿¡æ¯ |
| | | short buf[32] = { 0 }; |
| | | const short nRet = mdBdVerRead(m_nPath, buf); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | return nRet; |
| | | } |
| | | // è·åçæ¬ä¿¡æ¯ |
| | | short buf[32] = { 0 }; |
| | | const short nRet = mdBdVerRead(m_nPath, buf); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | return nRet; |
| | | } |
| | | |
| | | // å¡«å
çæ¬ä¿¡æ¯å°ç»æä½ |
| | | version.fixedValue[0] = static_cast<char>(buf[0] & 0xFF); |
| | | version.fixedValue[1] = static_cast<char>((buf[0] >> 8) & 0xFF); |
| | | // å¡«å
çæ¬ä¿¡æ¯å°ç»æä½ |
| | | version.fixedValue[0] = static_cast<char>(buf[0] & 0xFF); |
| | | version.fixedValue[1] = static_cast<char>((buf[0] >> 8) & 0xFF); |
| | | |
| | | version.checksum[0] = static_cast<char>(buf[1] & 0xFF); |
| | | version.checksum[1] = static_cast<char>((buf[1] >> 8) & 0xFF); |
| | | version.checksum[0] = static_cast<char>(buf[1] & 0xFF); |
| | | version.checksum[1] = static_cast<char>((buf[1] >> 8) & 0xFF); |
| | | |
| | | version.swVersion[0] = static_cast<char>(buf[2] & 0xFF); |
| | | version.swVersion[1] = static_cast<char>((buf[2] >> 8) & 0xFF); |
| | | version.swVersion[0] = static_cast<char>(buf[2] & 0xFF); |
| | | version.swVersion[1] = static_cast<char>((buf[2] >> 8) & 0xFF); |
| | | |
| | | std::memcpy(version.date, &buf[3], 6); |
| | | std::memcpy(version.date, &buf[3], 6); |
| | | |
| | | version.reserved = static_cast<uint32_t>(buf[6]) | (static_cast<uint32_t>(buf[7]) << 16); |
| | | version.reserved = static_cast<uint32_t>(buf[6]) | (static_cast<uint32_t>(buf[7]) << 16); |
| | | |
| | | std::memcpy(version.swModel, &buf[8], 16); |
| | | std::memcpy(version.hwModel, &buf[16], 16); |
| | | std::memcpy(version.swModel, &buf[8], 16); |
| | | std::memcpy(version.hwModel, &buf[16], 16); |
| | | |
| | | version.twoPortMemory[0] = static_cast<char>(buf[18] & 0xFF); |
| | | version.twoPortMemory[1] = static_cast<char>((buf[18] >> 8) & 0xFF); |
| | | version.twoPortMemory[0] = static_cast<char>(buf[18] & 0xFF); |
| | | version.twoPortMemory[1] = static_cast<char>((buf[18] >> 8) & 0xFF); |
| | | |
| | | version.twoPortAttribute[0] = static_cast<char>(buf[19] & 0xFF); |
| | | version.twoPortAttribute[1] = static_cast<char>((buf[19] >> 8) & 0xFF); |
| | | version.twoPortAttribute[0] = static_cast<char>(buf[19] & 0xFF); |
| | | version.twoPortAttribute[1] = static_cast<char>((buf[19] >> 8) & 0xFF); |
| | | |
| | | version.availableBias[0] = static_cast<char>(buf[20] & 0xFF); |
| | | version.availableBias[1] = static_cast<char>((buf[20] >> 8) & 0xFF); |
| | | version.availableBias[0] = static_cast<char>(buf[20] & 0xFF); |
| | | version.availableBias[1] = static_cast<char>((buf[20] >> 8) & 0xFF); |
| | | |
| | | std::memcpy(version.moduleType, &buf[21], 10); |
| | | std::memcpy(version.moduleType, &buf[21], 10); |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // 读åç®æ ç«ç¹CPUç±»å |
| | | // 读åç®æ ç«ç¹CPUç±»å |
| | | int CPerformanceMelsec::ReadCPUCode(const StationIdentifier& station, short& nCPUCode) { |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | nCPUCode = 0; |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | nRet = mdTypeRead(m_nPath, CombineStation(station), &nCPUCode); |
| | | } |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | nCPUCode = 0; |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | nRet = mdTypeRead(m_nPath, CombineStation(station), &nCPUCode); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // æ¿æ¨¡å¼è®¾ç½® |
| | | // æ¿æ¨¡å¼è®¾ç½® |
| | | int CPerformanceMelsec::SetBoardMode(const short nMode) { |
| | | // æ£æ¥æ¯å¦å·²ç»è¿æ¥ |
| | | if (!m_bConnected.load()) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | // æ£æ¥æ¯å¦å·²ç»è¿æ¥ |
| | | if (!m_bConnected.load()) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | short nRet = 0; |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | nRet = mdBdModSet(m_nPath, nMode); |
| | | } |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | short nRet = 0; |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | nRet = mdBdModSet(m_nPath, nMode); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // è·åæ¿æ¨¡å¼ |
| | | // è·åæ¿æ¨¡å¼ |
| | | int CPerformanceMelsec::GetBoardMode(short& nMode) { |
| | | // æ£æ¥æ¯å¦å·²ç»è¿æ¥ |
| | | if (!m_bConnected.load()) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | // æ£æ¥æ¯å¦å·²ç»è¿æ¥ |
| | | if (!m_bConnected.load()) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | |
| | | short nRet = 0; |
| | | { |
| | | nMode = 0; |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | nRet = mdBdModRead(m_nPath, &nMode); |
| | | } |
| | | short nRet = 0; |
| | | { |
| | | nMode = 0; |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | nRet = mdBdModRead(m_nPath, &nMode); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_DEBUG("Raw Mode: " << nMode); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_DEBUG("Raw Mode: " << nMode); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return 0; |
| | | return 0; |
| | | } |
| | | |
| | | // æ¿å¤ä½ |
| | | // æ¿å¤ä½ |
| | | int CPerformanceMelsec::BoardReset() { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | if (!m_bConnected.load()) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | if (!m_bConnected.load()) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | |
| | | const short nRet = mdBdRst(m_nPath); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | const short nRet = mdBdRst(m_nPath); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // æ¿LED读å |
| | | // æ¿LED读å |
| | | int CPerformanceMelsec::ReadBoardLed(std::vector<short>& vecLedBuffer) { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | if (!m_bConnected.load()) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | if (!m_bConnected.load()) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | |
| | | // æ¸
空 LED ç¼å²åº |
| | | vecLedBuffer.clear(); |
| | | vecLedBuffer.resize(16, 0); |
| | | // æ¸
空 LED ç¼å²åº |
| | | vecLedBuffer.clear(); |
| | | vecLedBuffer.resize(16, 0); |
| | | |
| | | // è°ç¨ SDK 彿°è¯»å LED æ°æ® |
| | | const short nRet = mdBdLedRead(m_nPath, vecLedBuffer.data()); |
| | | if (nRet != 0) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | LOG_ERROR("Error reading board LED, ErrorCode: " << nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | // è°ç¨ SDK 彿°è¯»å LED æ°æ® |
| | | const short nRet = mdBdLedRead(m_nPath, vecLedBuffer.data()); |
| | | if (nRet != 0) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | LOG_ERROR("Error reading board LED, ErrorCode: " << nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // è·åæ¿ç¶æ |
| | | // è·åæ¿ç¶æ |
| | | int CPerformanceMelsec::GetBoardStatus(BoardStatus& status) { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | if (!m_bConnected) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | if (!m_bConnected) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | |
| | | short buf[6] = { 0 }; |
| | | const short nRet = mdBdSwRead(m_nPath, buf); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | short buf[6] = { 0 }; |
| | | const short nRet = mdBdSwRead(m_nPath, buf); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | // å° buf æ å°å°ç»æä½ |
| | | status = BoardStatus::fromBuffer(buf); |
| | | return 0; |
| | | // å° buf æ å°å°ç»æä½ |
| | | status = BoardStatus::fromBuffer(buf); |
| | | return 0; |
| | | } |
| | | |
| | | // éç¨è¯»æ°æ® |
| | | // éç¨è¯»æ°æ® |
| | | int CPerformanceMelsec::ReadData(const StationIdentifier& station, const long nDevType, const long nDevNo, long nSize, std::vector<short>& vecData) { |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStationAndSize(station, static_cast<short>(nSize)); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStationAndSize(station, static_cast<short>(nSize)); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | // åå§å读åç¼å²åº |
| | | vecData.clear(); |
| | | vecData.resize(nSize, 0); |
| | | // åå§å读åç¼å²åº |
| | | vecData.clear(); |
| | | vecData.resize(nSize, 0); |
| | | |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | short* pData = vecData.data(); |
| | | nSize *= sizeof(short); |
| | | nRet = mdReceiveEx(m_nPath, station.nNetNo, station.nStNo, nDevType, (long)(unsigned short)nDevNo, &nSize, pData); |
| | | } |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | short* pData = vecData.data(); |
| | | nSize *= sizeof(short); |
| | | nRet = mdReceiveEx(m_nPath, station.nNetNo, station.nStNo, nDevType, (long)(unsigned short)nDevNo, &nSize, pData); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | vecData.clear(); // å¦æè¯»åå¤±è´¥ï¼æ¸
空ç¼å²åº |
| | | } |
| | | if (nRet != 0) { |
| | | vecData.clear(); // å¦æè¯»åå¤±è´¥ï¼æ¸
空ç¼å²åº |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // 读å使°æ® |
| | | // 读å使°æ® |
| | | int CPerformanceMelsec::ReadBitData(const StationIdentifier& station, const DeviceType enDevType, const short nDevNo, const short nBitCount, BitContainer& vecData) { |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStationAndSize(station, nBitCount); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStationAndSize(station, nBitCount); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | if (nDevNo % 8 != 0) { |
| | | nRet = -2; |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | if (nDevNo % 8 != 0) { |
| | | nRet = -2; |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const auto nSize = static_cast<short>((static_cast<int>(nBitCount) + 15) / 16); // 计ç®éè¦è¯»åçåæ°éï¼åä¸åæ´ï¼ |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const auto nSize = static_cast<short>((static_cast<int>(nBitCount) + 15) / 16); // 计ç®éè¦è¯»åçåæ°éï¼åä¸åæ´ï¼ |
| | | |
| | | std::vector<short> vecTempBuffer(nSize, 0); |
| | | nRet = ReadData(station, nDevType, nDevNo, nSize, vecTempBuffer); |
| | | std::vector<short> vecTempBuffer(nSize, 0); |
| | | nRet = ReadData(station, nDevType, nDevNo, nSize, vecTempBuffer); |
| | | |
| | | if (nRet == 0) { |
| | | vecData.clear(); |
| | | if (nRet == 0) { |
| | | vecData.clear(); |
| | | |
| | | // å°åæ°æ®è§£æä¸ºä½æ°æ® |
| | | for (short nIdx = 0; nIdx < nSize; ++nIdx) { |
| | | const short nCurrentValue = vecTempBuffer[nIdx]; |
| | | // éåå½å short ä¸çæ¯ä¸ä½ |
| | | for (int bitIdx = 0; bitIdx < 16; ++bitIdx) { |
| | | bool bBit = (nCurrentValue & (1 << bitIdx)) != 0; |
| | | vecData.push_back(bBit); |
| | | if (vecData.size() >= nBitCount) { |
| | | return nRet; // 妿已ç»è¯»å宿éç使°ï¼æåéåº |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // å°åæ°æ®è§£æä¸ºä½æ°æ® |
| | | for (short nIdx = 0; nIdx < nSize; ++nIdx) { |
| | | const short nCurrentValue = vecTempBuffer[nIdx]; |
| | | // éåå½å short ä¸çæ¯ä¸ä½ |
| | | for (int bitIdx = 0; bitIdx < 16; ++bitIdx) { |
| | | bool bBit = (nCurrentValue & (1 << bitIdx)) != 0; |
| | | vecData.push_back(bBit); |
| | | if (vecData.size() >= nBitCount) { |
| | | return nRet; // 妿已ç»è¯»å宿éç使°ï¼æåéåº |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // 读ååæ°æ® |
| | | // 读ååæ°æ® |
| | | int CPerformanceMelsec::ReadWordData(const StationIdentifier& station, const DeviceType enDevType, const short nDevNo, const short nWordCount, WordContainer& vecData) { |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStationAndSize(station, nWordCount); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStationAndSize(station, nWordCount); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | std::vector<short> vecTempBuffer(nWordCount, 0); |
| | | nRet = ReadData(station, nDevType, nDevNo, nWordCount, vecTempBuffer); |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | std::vector<short> vecTempBuffer(nWordCount, 0); |
| | | nRet = ReadData(station, nDevType, nDevNo, nWordCount, vecTempBuffer); |
| | | |
| | | if (nRet == 0) { |
| | | vecData.clear(); |
| | | vecData.assign(vecTempBuffer.begin(), vecTempBuffer.end()); |
| | | } |
| | | if (nRet == 0) { |
| | | vecData.clear(); |
| | | vecData.assign(vecTempBuffer.begin(), vecTempBuffer.end()); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // 读åååæ°æ® |
| | | // 读åååæ°æ® |
| | | int CPerformanceMelsec::ReadDWordData(const StationIdentifier& station, const DeviceType enDevType, const short nDevNo, const short nDWordCount, DWordContainer& vecData) { |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStationAndSize(station, nDWordCount); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStationAndSize(station, nDWordCount); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | const auto nSize = static_cast<short>(nDWordCount * 2); // æ¯ä¸ªååå 两个åï¼æ¯ä¸ªååå 4 åèï¼ |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | std::vector<short> vecTempBuffer(nSize, 0); |
| | | nRet = ReadData(station, nDevType, nDevNo, nSize, vecTempBuffer); |
| | | const auto nSize = static_cast<short>(nDWordCount * 2); // æ¯ä¸ªååå 两个åï¼æ¯ä¸ªååå 4 åèï¼ |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | std::vector<short> vecTempBuffer(nSize, 0); |
| | | nRet = ReadData(station, nDevType, nDevNo, nSize, vecTempBuffer); |
| | | |
| | | if (nRet == 0) { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertShortToUint32(vecTempBuffer, vecData); |
| | | } |
| | | if (nRet == 0) { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertShortToUint32(vecTempBuffer, vecData); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // éç¨åæ°æ® |
| | | // éç¨åæ°æ® |
| | | int CPerformanceMelsec::WriteData(const StationIdentifier& station, const long nDevType, const long nDevNo, long nSize, short* pData) { |
| | | // éªè¯ç«ç¹åæ° |
| | | int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ° |
| | | int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | // æ°æ®æææ§ |
| | | if (nSize < 0 || pData == nullptr) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | // æ°æ®æææ§ |
| | | if (nSize < 0 || pData == nullptr) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | nSize *= sizeof(short); |
| | | nRet = mdSendEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo, &nSize, pData); |
| | | } |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | nSize *= sizeof(short); |
| | | nRet = mdSendEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo, &nSize, pData); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // å使°æ® |
| | | // å使°æ® |
| | | int CPerformanceMelsec::WriteBitData(const StationIdentifier& station, const DeviceType enDevType, const short nDevNo, const BitContainer& vecData) { |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStationAndData(station, vecData); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStationAndData(station, vecData); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | if (nDevNo % 8 != 0) { |
| | | nRet = -2; |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | if (nDevNo % 8 != 0) { |
| | | nRet = -2; |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const auto nSize = static_cast<short>((static_cast<int>(vecData.size()) + 15) / 16); // 计ç®éè¦åå
¥çåæ°éï¼åä¸åæ´ï¼ |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const auto nSize = static_cast<short>((static_cast<int>(vecData.size()) + 15) / 16); // 计ç®éè¦åå
¥çåæ°éï¼åä¸åæ´ï¼ |
| | | |
| | | // åå¤ä¸´æ¶ç¼å²åºæ¥åå¨è½¬æ¢åç 16 使°æ® |
| | | std::vector<short> vecTempBuffer(nSize, 0); |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | // å°ä½æ°æ®æåæå
å°ä¸´æ¶ç¼å²åº |
| | | for (int i = 0; i < vecData.size(); ++i) { |
| | | if (vecData[i]) { |
| | | // ä½¿ç¨ & 0xFFFF ä¿è¯ä¸ä¼è¶
è¿ 16 ä½ï¼é²æ¢æº¢åº |
| | | vecTempBuffer[i / 16] |= static_cast<short>((1 << (i % 16)) & 0xFFFF); |
| | | } |
| | | } |
| | | } |
| | | // åå¤ä¸´æ¶ç¼å²åºæ¥åå¨è½¬æ¢åç 16 使°æ® |
| | | std::vector<short> vecTempBuffer(nSize, 0); |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | // å°ä½æ°æ®æåæå
å°ä¸´æ¶ç¼å²åº |
| | | for (int i = 0; i < vecData.size(); ++i) { |
| | | if (vecData[i]) { |
| | | // ä½¿ç¨ & 0xFFFF ä¿è¯ä¸ä¼è¶
è¿ 16 ä½ï¼é²æ¢æº¢åº |
| | | vecTempBuffer[i / 16] |= static_cast<short>((1 << (i % 16)) & 0xFFFF); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return WriteData(station, nDevType, nDevNo, nSize, vecTempBuffer.data()); |
| | | return WriteData(station, nDevType, nDevNo, nSize, vecTempBuffer.data()); |
| | | } |
| | | |
| | | // ååæ°æ® |
| | | // ååæ°æ® |
| | | int CPerformanceMelsec::WriteWordData(const StationIdentifier& station, const DeviceType enDevType, const short nDevNo, const WordContainer& vecData) { |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | const int nRet = ValidateStationAndData(station, vecData); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | const int nRet = ValidateStationAndData(station, vecData); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | // 计ç®éè¦åå
¥çåèæ°ï¼æ¯ä¸ªåå 2 åèï¼ |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const auto nSize = static_cast<short>(vecData.size()); |
| | | const auto pData = const_cast<short*>(reinterpret_cast<const short*>(vecData.data())); |
| | | // 计ç®éè¦åå
¥çåèæ°ï¼æ¯ä¸ªåå 2 åèï¼ |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const auto nSize = static_cast<short>(vecData.size()); |
| | | const auto pData = const_cast<short*>(reinterpret_cast<const short*>(vecData.data())); |
| | | |
| | | return WriteData(station, nDevType, nDevNo, nSize, pData); |
| | | return WriteData(station, nDevType, nDevNo, nSize, pData); |
| | | } |
| | | |
| | | // åååæ°æ® |
| | | // åååæ°æ® |
| | | int CPerformanceMelsec::WriteDWordData(const StationIdentifier& station, const DeviceType enDevType, const short nDevNo, const DWordContainer& vecData) { |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | const int nRet = ValidateStationAndData(station, vecData); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | const int nRet = ValidateStationAndData(station, vecData); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | // 计ç®éè¦åå
¥çåèæ°ï¼æ¯ä¸ªååå 4 åèï¼ |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const auto nSize = static_cast<short>(vecData.size() * sizeof(short)); |
| | | std::vector<short> vecBuffer(nSize, 0); |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertUint32ToShort(vecData, vecBuffer); |
| | | } |
| | | // 计ç®éè¦åå
¥çåèæ°ï¼æ¯ä¸ªååå 4 åèï¼ |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const auto nSize = static_cast<short>(vecData.size() * sizeof(short)); |
| | | std::vector<short> vecBuffer(nSize, 0); |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertUint32ToShort(vecData, vecBuffer); |
| | | } |
| | | |
| | | return WriteData(station, nDevType, nDevNo, nSize, vecBuffer.data()); |
| | | return WriteData(station, nDevType, nDevNo, nSize, vecBuffer.data()); |
| | | } |
| | | |
| | | // æ©å±è¯»æ°æ® |
| | | // æ©å±è¯»æ°æ® |
| | | long CPerformanceMelsec::ReadDataEx(const StationIdentifier& station, long nDevType, long nDevNo, long nSize, std::vector<char>& vecData) { |
| | | // éªè¯ç«ç¹åæ°å读å大尿¯å¦ææ |
| | | long nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ°å读å大尿¯å¦ææ |
| | | long nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | if (nSize < 0) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | if (nSize < 0) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | nSize = nSize % 2 != 0 ? nSize + 1 : nSize; |
| | | std::vector<short> vecBuffer(nSize / 2, 0); |
| | | nSize = nSize % 2 != 0 ? nSize + 1 : nSize; |
| | | std::vector<short> vecBuffer(nSize / 2, 0); |
| | | |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | nRet = mdReceiveEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo, &nSize, vecBuffer.data()); |
| | | } |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | nRet = mdReceiveEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo, &nSize, vecBuffer.data()); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | else { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | vecData.resize(nSize); |
| | | ConvertShortToChar(vecBuffer, vecData); |
| | | } |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | else { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | vecData.resize(nSize); |
| | | ConvertShortToChar(vecBuffer, vecData); |
| | | } |
| | | |
| | | return 0; |
| | | return 0; |
| | | } |
| | | |
| | | // æ©å±è¯»å使°æ® |
| | | // æ©å±è¯»å使°æ® |
| | | long CPerformanceMelsec::ReadBitDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, long nBitCount, BitContainer& vecData) { |
| | | long nRet = ValidateStationAndSize(station, static_cast<short>(nBitCount)); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | long nRet = ValidateStationAndSize(station, static_cast<short>(nBitCount)); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | |
| | | // === èªå¨å¯¹é½å°èµ·å§å === |
| | | long nWordAlignedStartBit = nDevNo / 16 * 16; |
| | | long nBitOffset = nDevNo - nWordAlignedStartBit; |
| | | long nTotalBits = nBitOffset + nBitCount; |
| | | long nWordCount = (nTotalBits + 15) / 16; |
| | | long nByteSize = nWordCount * sizeof(short); |
| | | // === èªå¨å¯¹é½å°èµ·å§å === |
| | | long nWordAlignedStartBit = nDevNo / 16 * 16; |
| | | long nBitOffset = nDevNo - nWordAlignedStartBit; |
| | | long nTotalBits = nBitOffset + nBitCount; |
| | | long nWordCount = (nTotalBits + 15) / 16; |
| | | long nByteSize = nWordCount * sizeof(short); |
| | | |
| | | std::vector<char> vecRaw; |
| | | nRet = ReadDataEx(station, nDevType, nWordAlignedStartBit, nByteSize, vecRaw); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | std::vector<char> vecRaw; |
| | | nRet = ReadDataEx(station, nDevType, nWordAlignedStartBit, nByteSize, vecRaw); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | vecData.clear(); |
| | | for (long i = 0; i < nWordCount; ++i) { |
| | | short word = static_cast<unsigned char>(vecRaw[i * 2]) | |
| | | (static_cast<unsigned char>(vecRaw[i * 2 + 1]) << 8); |
| | | vecData.clear(); |
| | | for (long i = 0; i < nWordCount; ++i) { |
| | | short word = static_cast<unsigned char>(vecRaw[i * 2]) | |
| | | (static_cast<unsigned char>(vecRaw[i * 2 + 1]) << 8); |
| | | |
| | | for (int j = 0; j < 16; ++j) { |
| | | long bitIndex = i * 16 + j; |
| | | if (bitIndex >= nBitOffset && vecData.size() < static_cast<size_t>(nBitCount)) { |
| | | vecData.push_back((word & (1 << j)) != 0); |
| | | } |
| | | } |
| | | } |
| | | for (int j = 0; j < 16; ++j) { |
| | | long bitIndex = i * 16 + j; |
| | | if (bitIndex >= nBitOffset && vecData.size() < static_cast<size_t>(nBitCount)) { |
| | | vecData.push_back((word & (1 << j)) != 0); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return 0; |
| | | return 0; |
| | | } |
| | | |
| | | // æ©å±è¯»ååæ°æ® |
| | | // æ©å±è¯»ååæ°æ® |
| | | long CPerformanceMelsec::ReadWordDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, long nWordCount, WordContainer& vecData) { |
| | | long nRet = ValidateStationAndSize(station, static_cast<short>(nWordCount)); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | long nRet = ValidateStationAndSize(station, static_cast<short>(nWordCount)); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const long nByteSize = nWordCount * sizeof(short); |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const long nByteSize = nWordCount * sizeof(short); |
| | | |
| | | std::vector<char> vecRaw; |
| | | nRet = ReadDataEx(station, nDevType, nDevNo, nByteSize, vecRaw); |
| | | if (nRet != 0) { |
| | | return nRet; |
| | | } |
| | | std::vector<char> vecRaw; |
| | | nRet = ReadDataEx(station, nDevType, nDevNo, nByteSize, vecRaw); |
| | | if (nRet != 0) { |
| | | return nRet; |
| | | } |
| | | |
| | | vecData.clear(); |
| | | for (long i = 0; i < nWordCount; ++i) { |
| | | short value = static_cast<unsigned char>(vecRaw[i * 2]) | |
| | | (static_cast<unsigned char>(vecRaw[i * 2 + 1]) << 8); |
| | | vecData.push_back(value); |
| | | } |
| | | vecData.clear(); |
| | | for (long i = 0; i < nWordCount; ++i) { |
| | | short value = static_cast<unsigned char>(vecRaw[i * 2]) | |
| | | (static_cast<unsigned char>(vecRaw[i * 2 + 1]) << 8); |
| | | vecData.push_back(value); |
| | | } |
| | | |
| | | return 0; |
| | | return 0; |
| | | } |
| | | |
| | | // æ©å±è¯»åååæ°æ® |
| | | // æ©å±è¯»åååæ°æ® |
| | | long CPerformanceMelsec::ReadDWordDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, long nDWordCount, DWordContainer& vecData) { |
| | | long nRet = ValidateStationAndSize(station, static_cast<short>(nDWordCount)); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | long nRet = ValidateStationAndSize(station, static_cast<short>(nDWordCount)); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const long nByteSize = nDWordCount * sizeof(uint32_t); |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const long nByteSize = nDWordCount * sizeof(uint32_t); |
| | | |
| | | std::vector<char> vecRaw; |
| | | nRet = ReadDataEx(station, nDevType, nDevNo, nByteSize, vecRaw); |
| | | if (nRet != 0) { |
| | | return nRet; |
| | | } |
| | | std::vector<char> vecRaw; |
| | | nRet = ReadDataEx(station, nDevType, nDevNo, nByteSize, vecRaw); |
| | | if (nRet != 0) { |
| | | return nRet; |
| | | } |
| | | |
| | | vecData.clear(); |
| | | for (long i = 0; i < nDWordCount; ++i) { |
| | | uint32_t val = static_cast<unsigned char>(vecRaw[i * 4 + 0]) | |
| | | (static_cast<unsigned char>(vecRaw[i * 4 + 1]) << 8) | |
| | | (static_cast<unsigned char>(vecRaw[i * 4 + 2]) << 16) | |
| | | (static_cast<unsigned char>(vecRaw[i * 4 + 3]) << 24); |
| | | vecData.push_back(val); |
| | | } |
| | | vecData.clear(); |
| | | for (long i = 0; i < nDWordCount; ++i) { |
| | | uint32_t val = static_cast<unsigned char>(vecRaw[i * 4 + 0]) | |
| | | (static_cast<unsigned char>(vecRaw[i * 4 + 1]) << 8) | |
| | | (static_cast<unsigned char>(vecRaw[i * 4 + 2]) << 16) | |
| | | (static_cast<unsigned char>(vecRaw[i * 4 + 3]) << 24); |
| | | vecData.push_back(val); |
| | | } |
| | | |
| | | return 0; |
| | | return 0; |
| | | } |
| | | |
| | | // æ©å±åæ°æ® |
| | | // æ©å±åæ°æ® |
| | | long CPerformanceMelsec::WriteDataEx(const StationIdentifier& station, long nDevType, long nDevNo, const std::vector<char>& vecData) { |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | long nRet = ValidateStationAndData(station, vecData); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | long nRet = ValidateStationAndData(station, vecData); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | // å° vecData 转æ¢ä¸º short ç±»åçç¼å²åº |
| | | long nSize = static_cast<long>(vecData.size()); |
| | | nSize = nSize % 2 != 0 ? nSize + 1 : nSize; |
| | | std::vector<short> vecBuffer(nSize / 2, 0); |
| | | // å° vecData 转æ¢ä¸º short ç±»åçç¼å²åº |
| | | long nSize = static_cast<long>(vecData.size()); |
| | | nSize = nSize % 2 != 0 ? nSize + 1 : nSize; |
| | | std::vector<short> vecBuffer(nSize / 2, 0); |
| | | |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertCharToShort(vecData, vecBuffer); |
| | | nRet = mdSendEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo, &nSize, vecBuffer.data()); |
| | | } |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertCharToShort(vecData, vecBuffer); |
| | | nRet = mdSendEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo, &nSize, vecBuffer.data()); |
| | | } |
| | | |
| | | // é误å¤ç忥å¿è®°å½ |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | // é误å¤ç忥å¿è®°å½ |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // æ©å±å使°æ® |
| | | // æ©å±å使°æ® |
| | | long CPerformanceMelsec::WriteBitDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, const BitContainer& vecData) { |
| | | long nRet = ValidateStationAndData(station, vecData); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | long nRet = ValidateStationAndData(station, vecData); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | |
| | | // === 1. èªå¨å¯¹é½èµ·å§å°å === |
| | | long nWordAlignedStartBit = nDevNo / 16 * 16; |
| | | long nBitOffset = nDevNo - nWordAlignedStartBit; |
| | | long nTotalBits = nBitOffset + static_cast<long>(vecData.size()); |
| | | size_t nWordCount = (nTotalBits + 15) / 16; |
| | | // === 1. èªå¨å¯¹é½èµ·å§å°å === |
| | | long nWordAlignedStartBit = nDevNo / 16 * 16; |
| | | long nBitOffset = nDevNo - nWordAlignedStartBit; |
| | | long nTotalBits = nBitOffset + static_cast<long>(vecData.size()); |
| | | size_t nWordCount = (nTotalBits + 15) / 16; |
| | | |
| | | // === 2. å
读ååå§å¼ä»¥æ¯æé对é½è¦ç === |
| | | std::vector<char> vecRaw; |
| | | nRet = ReadDataEx(station, nDevType, nWordAlignedStartBit, static_cast<long>(nWordCount * sizeof(short)), vecRaw); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // === 2. å
读ååå§å¼ä»¥æ¯æé对é½è¦ç === |
| | | std::vector<char> vecRaw; |
| | | nRet = ReadDataEx(station, nDevType, nWordAlignedStartBit, static_cast<long>(nWordCount * sizeof(short)), vecRaw); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | // === 3. åå¹¶æ°æ°æ® === |
| | | std::vector<short> vecWordBuffer(nWordCount, 0); |
| | | for (size_t i = 0; i < nWordCount; ++i) { |
| | | vecWordBuffer[i] = static_cast<unsigned char>(vecRaw[i * 2]) | (static_cast<unsigned char>(vecRaw[i * 2 + 1]) << 8); |
| | | } |
| | | // === 3. åå¹¶æ°æ°æ® === |
| | | std::vector<short> vecWordBuffer(nWordCount, 0); |
| | | for (size_t i = 0; i < nWordCount; ++i) { |
| | | vecWordBuffer[i] = static_cast<unsigned char>(vecRaw[i * 2]) | (static_cast<unsigned char>(vecRaw[i * 2 + 1]) << 8); |
| | | } |
| | | |
| | | for (size_t i = 0; i < vecData.size(); ++i) { |
| | | size_t bitIndex = nBitOffset + i; |
| | | size_t wordIdx = bitIndex / 16; |
| | | size_t bitPos = bitIndex % 16; |
| | | if (vecData[i]) { |
| | | vecWordBuffer[wordIdx] |= (1 << bitPos); |
| | | } |
| | | else { |
| | | vecWordBuffer[wordIdx] &= ~(1 << bitPos); |
| | | } |
| | | } |
| | | for (size_t i = 0; i < vecData.size(); ++i) { |
| | | size_t bitIndex = nBitOffset + i; |
| | | size_t wordIdx = bitIndex / 16; |
| | | size_t bitPos = bitIndex % 16; |
| | | if (vecData[i]) { |
| | | vecWordBuffer[wordIdx] |= (1 << bitPos); |
| | | } |
| | | else { |
| | | vecWordBuffer[wordIdx] &= ~(1 << bitPos); |
| | | } |
| | | } |
| | | |
| | | // === 4. 转为åèæµåå
¥ === |
| | | std::vector<char> vecByteBuffer(nWordCount * 2); |
| | | for (size_t i = 0; i < nWordCount; ++i) { |
| | | vecByteBuffer[i * 2] = static_cast<char>(vecWordBuffer[i] & 0xFF); |
| | | vecByteBuffer[i * 2 + 1] = static_cast<char>((vecWordBuffer[i] >> 8) & 0xFF); |
| | | } |
| | | // === 4. 转为åèæµåå
¥ === |
| | | std::vector<char> vecByteBuffer(nWordCount * 2); |
| | | for (size_t i = 0; i < nWordCount; ++i) { |
| | | vecByteBuffer[i * 2] = static_cast<char>(vecWordBuffer[i] & 0xFF); |
| | | vecByteBuffer[i * 2 + 1] = static_cast<char>((vecWordBuffer[i] >> 8) & 0xFF); |
| | | } |
| | | |
| | | return WriteDataEx(station, nDevType, nWordAlignedStartBit, vecByteBuffer); |
| | | return WriteDataEx(station, nDevType, nWordAlignedStartBit, vecByteBuffer); |
| | | } |
| | | |
| | | // æ©å±ååæ°æ® |
| | | // æ©å±ååæ°æ® |
| | | long CPerformanceMelsec::WriteWordDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, const WordContainer& vecData) { |
| | | long nRet = ValidateStationAndData(station, vecData); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | long nRet = ValidateStationAndData(station, vecData); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | std::vector<char> vecByteBuffer; |
| | | vecByteBuffer.resize(vecData.size() * sizeof(short)); |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | std::vector<char> vecByteBuffer; |
| | | vecByteBuffer.resize(vecData.size() * sizeof(short)); |
| | | |
| | | for (size_t i = 0; i < vecData.size(); ++i) { |
| | | vecByteBuffer[i * 2] = static_cast<char>(vecData[i] & 0xFF); |
| | | vecByteBuffer[i * 2 + 1] = static_cast<char>((vecData[i] >> 8) & 0xFF); |
| | | } |
| | | for (size_t i = 0; i < vecData.size(); ++i) { |
| | | vecByteBuffer[i * 2] = static_cast<char>(vecData[i] & 0xFF); |
| | | vecByteBuffer[i * 2 + 1] = static_cast<char>((vecData[i] >> 8) & 0xFF); |
| | | } |
| | | |
| | | return WriteDataEx(station, nDevType, nDevNo, vecByteBuffer); |
| | | return WriteDataEx(station, nDevType, nDevNo, vecByteBuffer); |
| | | } |
| | | |
| | | // æ©å±åååæ°æ® |
| | | // æ©å±åååæ°æ® |
| | | long CPerformanceMelsec::WriteDWordDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, const DWordContainer& vecData) { |
| | | long nRet = ValidateStationAndData(station, vecData); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | long nRet = ValidateStationAndData(station, vecData); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | std::vector<char> vecByteBuffer; |
| | | vecByteBuffer.resize(vecData.size() * sizeof(uint32_t)); |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | std::vector<char> vecByteBuffer; |
| | | vecByteBuffer.resize(vecData.size() * sizeof(uint32_t)); |
| | | |
| | | for (size_t i = 0; i < vecData.size(); ++i) { |
| | | vecByteBuffer[i * 4] = static_cast<char>(vecData[i] & 0xFF); |
| | | vecByteBuffer[i * 4 + 1] = static_cast<char>((vecData[i] >> 8) & 0xFF); |
| | | vecByteBuffer[i * 4 + 2] = static_cast<char>((vecData[i] >> 16) & 0xFF); |
| | | vecByteBuffer[i * 4 + 3] = static_cast<char>((vecData[i] >> 24) & 0xFF); |
| | | } |
| | | for (size_t i = 0; i < vecData.size(); ++i) { |
| | | vecByteBuffer[i * 4] = static_cast<char>(vecData[i] & 0xFF); |
| | | vecByteBuffer[i * 4 + 1] = static_cast<char>((vecData[i] >> 8) & 0xFF); |
| | | vecByteBuffer[i * 4 + 2] = static_cast<char>((vecData[i] >> 16) & 0xFF); |
| | | vecByteBuffer[i * 4 + 3] = static_cast<char>((vecData[i] >> 24) & 0xFF); |
| | | } |
| | | |
| | | return WriteDataEx(station, nDevType, nDevNo, vecByteBuffer); |
| | | return WriteDataEx(station, nDevType, nDevNo, vecByteBuffer); |
| | | } |
| | | |
| | | // æ©å±è½¯å
ä»¶éæºè¯»å |
| | | // æ©å±è½¯å
ä»¶éæºè¯»å |
| | | long CPerformanceMelsec::ReadRandomDataEx(const StationIdentifier& station, const std::vector<SoftElement>& vecSoftElements, std::vector<char>& vecData) { |
| | | if (vecSoftElements.empty()) { |
| | | UpdateLastError(ERROR_INVALID_PARAMETER); |
| | | LOG_ERROR("Invalid parameters: soft elements are empty."); |
| | | return ERROR_INVALID_PARAMETER; |
| | | } |
| | | if (vecSoftElements.empty()) { |
| | | UpdateLastError(ERROR_INVALID_PARAMETER); |
| | | LOG_ERROR("Invalid parameters: soft elements are empty."); |
| | | return ERROR_INVALID_PARAMETER; |
| | | } |
| | | |
| | | // åå¤ dev æ°æ® |
| | | std::vector<short> devBuffer(vecSoftElements.size() * 3 + 1, 0); // æ¯ä¸ªè½¯å
ä»¶éè¦ 3 个 shortï¼å¤å ä¸ä¸ªè®¡æ°å¨ |
| | | devBuffer[0] = static_cast<short>(vecSoftElements.size()); // 第ä¸ä¸ªå
ç´ æ¯è½¯å
ä»¶æ°é |
| | | for (size_t i = 0; i < vecSoftElements.size(); ++i) { |
| | | const SoftElement& element = vecSoftElements[i]; |
| | | devBuffer[i * 3 + 1] = element.nType; // 软å
ä»¶ç±»å |
| | | devBuffer[i * 3 + 2] = static_cast<short>(element.nStartNo); // èµ·å§è½¯å
ä»¶ç¼å· |
| | | devBuffer[i * 3 + 3] = element.nElementCount; // ç¹æ° |
| | | } |
| | | // åå¤ dev æ°æ® |
| | | std::vector<short> devBuffer(vecSoftElements.size() * 3 + 1, 0); // æ¯ä¸ªè½¯å
ä»¶éè¦ 3 个 shortï¼å¤å ä¸ä¸ªè®¡æ°å¨ |
| | | devBuffer[0] = static_cast<short>(vecSoftElements.size()); // 第ä¸ä¸ªå
ç´ æ¯è½¯å
ä»¶æ°é |
| | | for (size_t i = 0; i < vecSoftElements.size(); ++i) { |
| | | const SoftElement& element = vecSoftElements[i]; |
| | | devBuffer[i * 3 + 1] = element.nType; // 软å
ä»¶ç±»å |
| | | devBuffer[i * 3 + 2] = static_cast<short>(element.nStartNo); // èµ·å§è½¯å
ä»¶ç¼å· |
| | | devBuffer[i * 3 + 3] = element.nElementCount; // ç¹æ° |
| | | } |
| | | |
| | | // 计ç®è¯»åæ°æ®æéç¼å²åºå¤§å° |
| | | long nBufferSize = 0; |
| | | for (const auto& element : vecSoftElements) { |
| | | nBufferSize += element.nElementCount * 2; // æ¯ä¸ªç¹å ç¨ 2 个åè |
| | | } |
| | | // 计ç®è¯»åæ°æ®æéç¼å²åºå¤§å° |
| | | long nBufferSize = 0; |
| | | for (const auto& element : vecSoftElements) { |
| | | nBufferSize += element.nElementCount * 2; // æ¯ä¸ªç¹å ç¨ 2 个åè |
| | | } |
| | | |
| | | // éä¿æ¤åè°ç¨ mdRandREx |
| | | long nRet = 0; |
| | | std::vector<short> vecBuffer(nBufferSize / 2, 0); |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // ç¡®ä¿çº¿ç¨å®å
¨ |
| | | nRet = mdRandREx(m_nPath, station.nNetNo, station.nStNo, devBuffer.data(), vecBuffer.data(), nBufferSize); |
| | | } |
| | | // éä¿æ¤åè°ç¨ mdRandREx |
| | | long nRet = 0; |
| | | std::vector<short> vecBuffer(nBufferSize / 2, 0); |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // ç¡®ä¿çº¿ç¨å®å
¨ |
| | | nRet = mdRandREx(m_nPath, station.nNetNo, station.nStNo, devBuffer.data(), vecBuffer.data(), nBufferSize); |
| | | } |
| | | |
| | | // é误å¤ç忥å¿è®°å½ |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | return nRet; |
| | | } |
| | | // é误å¤ç忥å¿è®°å½ |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | return nRet; |
| | | } |
| | | |
| | | // å°è¯»åå°ç short æ°æ®è½¬æ¢ä¸º char æ°æ® |
| | | vecData.resize(nBufferSize); |
| | | for (size_t i = 0; i < vecBuffer.size(); ++i) { |
| | | vecData[i * 2] = static_cast<char>(vecBuffer[i] & 0xFF); // ä½åè |
| | | vecData[i * 2 + 1] = static_cast<char>((vecBuffer[i] >> 8) & 0xFF); // é«åè |
| | | } |
| | | // å°è¯»åå°ç short æ°æ®è½¬æ¢ä¸º char æ°æ® |
| | | vecData.resize(nBufferSize); |
| | | for (size_t i = 0; i < vecBuffer.size(); ++i) { |
| | | vecData[i * 2] = static_cast<char>(vecBuffer[i] & 0xFF); // ä½åè |
| | | vecData[i * 2 + 1] = static_cast<char>((vecBuffer[i] >> 8) & 0xFF); // é«åè |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // æ©å±è½¯å
ä»¶éæºåå
¥ï¼æ¯æå¤ä¸ªè½¯å
ä»¶ï¼ |
| | | // æ©å±è½¯å
ä»¶éæºåå
¥ï¼æ¯æå¤ä¸ªè½¯å
ä»¶ï¼ |
| | | long CPerformanceMelsec::WriteRandomDataEx(const StationIdentifier& station, const std::vector<SoftElement>& vecSoftElements, const std::vector<char>& vecData) { |
| | | if (vecSoftElements.empty() || vecData.empty()) { |
| | | UpdateLastError(ERROR_INVALID_PARAMETER); |
| | | LOG_ERROR("Invalid parameters: soft elements or data is empty."); |
| | | return ERROR_INVALID_PARAMETER; |
| | | } |
| | | if (vecSoftElements.empty() || vecData.empty()) { |
| | | UpdateLastError(ERROR_INVALID_PARAMETER); |
| | | LOG_ERROR("Invalid parameters: soft elements or data is empty."); |
| | | return ERROR_INVALID_PARAMETER; |
| | | } |
| | | |
| | | // åå¤ dev æ°æ® |
| | | std::vector<long> devBuffer(vecSoftElements.size() * 3 + 1, 0); // æ¯ä¸ªè½¯å
ä»¶éè¦ 3 个 longï¼å¤å ä¸ä¸ªè®¡æ°å¨ |
| | | devBuffer[0] = static_cast<long>(vecSoftElements.size()); // 第ä¸ä¸ªå
ç´ æ¯è½¯å
ä»¶æ°é |
| | | for (size_t i = 0; i < vecSoftElements.size(); ++i) { |
| | | const SoftElement& element = vecSoftElements[i]; |
| | | devBuffer[i * 3 + 1] = static_cast<long>(element.nType); // 软å
ä»¶ç±»å |
| | | devBuffer[i * 3 + 2] = element.nStartNo; // èµ·å§è½¯å
ä»¶ç¼å·ï¼å·²ç»æ¯ long ç±»åï¼æ é转æ¢ï¼ |
| | | devBuffer[i * 3 + 3] = static_cast<long>(element.nElementCount); // ç¹æ° |
| | | } |
| | | // åå¤ dev æ°æ® |
| | | std::vector<long> devBuffer(vecSoftElements.size() * 3 + 1, 0); // æ¯ä¸ªè½¯å
ä»¶éè¦ 3 个 longï¼å¤å ä¸ä¸ªè®¡æ°å¨ |
| | | devBuffer[0] = static_cast<long>(vecSoftElements.size()); // 第ä¸ä¸ªå
ç´ æ¯è½¯å
ä»¶æ°é |
| | | for (size_t i = 0; i < vecSoftElements.size(); ++i) { |
| | | const SoftElement& element = vecSoftElements[i]; |
| | | devBuffer[i * 3 + 1] = static_cast<long>(element.nType); // 软å
ä»¶ç±»å |
| | | devBuffer[i * 3 + 2] = element.nStartNo; // èµ·å§è½¯å
ä»¶ç¼å·ï¼å·²ç»æ¯ long ç±»åï¼æ é转æ¢ï¼ |
| | | devBuffer[i * 3 + 3] = static_cast<long>(element.nElementCount); // ç¹æ° |
| | | } |
| | | |
| | | // éä¿æ¤åè°ç¨ mdRandWEx |
| | | long nRet = 0; |
| | | std::vector<short> vecBuffer(vecData.size() / 2, 0); |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // ç¡®ä¿çº¿ç¨å®å
¨ |
| | | ConvertCharToShort(vecData, vecBuffer); |
| | | nRet = mdRandWEx(m_nPath, station.nNetNo, station.nStNo, devBuffer.data(), vecBuffer.data(), static_cast<long>(vecBuffer.size())); |
| | | } |
| | | // éä¿æ¤åè°ç¨ mdRandWEx |
| | | long nRet = 0; |
| | | std::vector<short> vecBuffer(vecData.size() / 2, 0); |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // ç¡®ä¿çº¿ç¨å®å
¨ |
| | | ConvertCharToShort(vecData, vecBuffer); |
| | | nRet = mdRandWEx(m_nPath, station.nNetNo, station.nStNo, devBuffer.data(), vecBuffer.data(), static_cast<long>(vecBuffer.size())); |
| | | } |
| | | |
| | | // é误å¤ç忥å¿è®°å½ |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | // é误å¤ç忥å¿è®°å½ |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // è¿ç¨è®¾å¤ç«/è¿ç¨ç«çç¼å²åå¨å¨è¯»å |
| | | // è¿ç¨è®¾å¤ç«/è¿ç¨ç«çç¼å²åå¨å¨è¯»å |
| | | long CPerformanceMelsec::ReadRemoteBuffer(const StationIdentifier& station, long nOffset, long nSize, std::vector<char>& vecData) { |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | if (nSize < 0) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | if (nSize < 0) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | long nActualSize = (nSize + 1) / 2; |
| | | std::vector<short> vecBuffer(nActualSize, 0); |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | nRet = mdRemBufReadEx(m_nPath, station.nNetNo, station.nStNo, nOffset, &nActualSize, vecBuffer.data()); |
| | | } |
| | | long nActualSize = (nSize + 1) / 2; |
| | | std::vector<short> vecBuffer(nActualSize, 0); |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | nRet = mdRemBufReadEx(m_nPath, station.nNetNo, station.nStNo, nOffset, &nActualSize, vecBuffer.data()); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); // æ´æ°é误ç |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | else { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertShortToChar(vecBuffer, vecData); |
| | | } |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); // æ´æ°é误ç |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | else { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertShortToChar(vecBuffer, vecData); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // è¿ç¨è®¾å¤ç«/è¿ç¨ç«çç¼å²åå¨å¨åå
¥ |
| | | // è¿ç¨è®¾å¤ç«/è¿ç¨ç«çç¼å²åå¨å¨åå
¥ |
| | | long CPerformanceMelsec::WriteRemoteBuffer(const StationIdentifier& station, long nOffset, const std::vector<char>& vecData) { |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | long nRet = ValidateStationAndData(station, vecData); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | long nRet = ValidateStationAndData(station, vecData); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | // å° vecData 转æ¢ä¸º short ç±»åçç¼å²åº |
| | | long nSize = static_cast<long>(vecData.size()); |
| | | std::vector<short> vecBuffer((nSize + 1) / 2, 0); |
| | | // å° vecData 转æ¢ä¸º short ç±»åçç¼å²åº |
| | | long nSize = static_cast<long>(vecData.size()); |
| | | std::vector<short> vecBuffer((nSize + 1) / 2, 0); |
| | | |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertCharToShort(vecData, vecBuffer); |
| | | nRet = mdRemBufWriteEx(m_nPath, station.nNetNo, station.nStNo, nOffset, &nSize, vecBuffer.data()); |
| | | } |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertCharToShort(vecData, vecBuffer); |
| | | nRet = mdRemBufWriteEx(m_nPath, station.nNetNo, station.nStNo, nOffset, &nSize, vecBuffer.data()); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // è¿ç¨ç«çç¼å²åå¨å¨è¯»å 对象ç«IPå°åæå® |
| | | // è¿ç¨ç«çç¼å²åå¨å¨è¯»å 对象ç«IPå°åæå® |
| | | long CPerformanceMelsec::ReadRemoteBufferByIp(const std::string& strIP, long nOffset, long nSize, std::vector<char>& vecData) { |
| | | uint32_t nAddress = 0; |
| | | if (nSize < 0 || !ConvertIpStringToUint32(strIP, nAddress)) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | uint32_t nAddress = 0; |
| | | if (nSize < 0 || !ConvertIpStringToUint32(strIP, nAddress)) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | // å°ç¼å²åºå¤§å°è°æ´ä¸º nSize |
| | | vecData.resize(nSize, 0); |
| | | std::vector<short> vecBuffer((nSize + 1) / 2, 0); // 转æ¢ä¸º short ç±»å |
| | | // å°ç¼å²åºå¤§å°è°æ´ä¸º nSize |
| | | vecData.resize(nSize, 0); |
| | | std::vector<short> vecBuffer((nSize + 1) / 2, 0); // 转æ¢ä¸º short ç±»å |
| | | |
| | | // è°ç¨åºå± SDK |
| | | long nRet = 0; |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | nRet = mdRemBufReadIPEx(m_nPath, static_cast<long>(nAddress), nOffset, &nSize, vecBuffer.data()); |
| | | } |
| | | // è°ç¨åºå± SDK |
| | | long nRet = 0; |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | nRet = mdRemBufReadIPEx(m_nPath, static_cast<long>(nAddress), nOffset, &nSize, vecBuffer.data()); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | else { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertShortToChar(vecBuffer, vecData); |
| | | } |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | else { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertShortToChar(vecBuffer, vecData); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // è¿ç¨ç«çç¼å²åå¨å¨åå
¥ 对象ç«IPå°åæå® |
| | | // è¿ç¨ç«çç¼å²åå¨å¨åå
¥ 对象ç«IPå°åæå® |
| | | long CPerformanceMelsec::WriteRemoteBufferByIp(const std::string& strIP, long nOffset, const std::vector<char>& vecData) { |
| | | uint32_t nAddress = 0; |
| | | if (vecData.empty() || !ConvertIpStringToUint32(strIP, nAddress)) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | uint32_t nAddress = 0; |
| | | if (vecData.empty() || !ConvertIpStringToUint32(strIP, nAddress)) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | // è½¬æ¢ vecData 为 short ç±»åçç¼å²åº |
| | | long nSize = static_cast<long>(vecData.size()); |
| | | std::vector<short> vecBuffer((nSize + 1) / 2, 0); |
| | | // è½¬æ¢ vecData 为 short ç±»åçç¼å²åº |
| | | long nSize = static_cast<long>(vecData.size()); |
| | | std::vector<short> vecBuffer((nSize + 1) / 2, 0); |
| | | |
| | | long nRet = 0; |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ |
| | | ConvertCharToShort(vecData, vecBuffer); |
| | | nRet = mdRemBufWriteIPEx(m_nPath, static_cast<long>(nAddress), nOffset, &nSize, vecBuffer.data()); |
| | | } |
| | | long nRet = 0; |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ |
| | | ConvertCharToShort(vecData, vecBuffer); |
| | | nRet = mdRemBufWriteIPEx(m_nPath, static_cast<long>(nAddress), nOffset, &nSize, vecBuffer.data()); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // 设置(ON)对象ç«çæå®ä½è½¯å
ä»¶ |
| | | // 设置(ON)对象ç«çæå®ä½è½¯å
ä»¶ |
| | | int CPerformanceMelsec::SetBitDevice(const StationIdentifier& station, const DeviceType enDevType, const short nDevNo) { |
| | | // éªè¯ç«ç¹åæ° |
| | | int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ° |
| | | int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | nRet = mdDevSet(m_nPath, CombineStation(station), nDevType, nDevNo); |
| | | } |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | nRet = mdDevSet(m_nPath, CombineStation(station), nDevType, nDevNo); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // å¤ä½(OFF)对象ç«çæå®ä½è½¯å
ä»¶ |
| | | // å¤ä½(OFF)对象ç«çæå®ä½è½¯å
ä»¶ |
| | | int CPerformanceMelsec::ResetBitDevice(const StationIdentifier& station, const DeviceType enDevType, const short enDevNo) { |
| | | // éªè¯ç«ç¹åæ° |
| | | int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ° |
| | | int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | nRet = mdDevRst(m_nPath, CombineStation(station), nDevType, enDevNo); |
| | | } |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | nRet = mdDevRst(m_nPath, CombineStation(station), nDevType, enDevNo); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // æ©å±ä½è½¯å
件设置 |
| | | // æ©å±ä½è½¯å
件设置 |
| | | long CPerformanceMelsec::SetBitDeviceEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo) { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | |
| | | // æ£æ¥åæ°æææ§ |
| | | long nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // æ£æ¥åæ°æææ§ |
| | | long nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | long nDevType = static_cast<long>(enDevType); |
| | | nRet = mdDevSetEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | long nDevType = static_cast<long>(enDevType); |
| | | nRet = mdDevSetEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // æ©å±ä½è½¯å
ä»¶å¤ä½ |
| | | // æ©å±ä½è½¯å
ä»¶å¤ä½ |
| | | long CPerformanceMelsec::ResetBitDeviceEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo) { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | |
| | | // æ£æ¥åæ°æææ§ |
| | | long nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // æ£æ¥åæ°æææ§ |
| | | long nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | long nDevType = static_cast<long>(enDevType); |
| | | nRet = mdDevRstEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | long nDevType = static_cast<long>(enDevType); |
| | | nRet = mdDevRstEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // æ§è¡å¯¹è±¡ç«çCPU |
| | | // æ§è¡å¯¹è±¡ç«çCPU |
| | | int CPerformanceMelsec::ControlCPU(const StationIdentifier& station, ControlCode enControlCode) { |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | // éªè¯æ§å¶ç æ¯å¦åæ³ |
| | | const auto nControlCode = static_cast<short>(enControlCode); |
| | | if (nControlCode < 0 || nControlCode > 2) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); // åæ°é误 |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | // éªè¯æ§å¶ç æ¯å¦åæ³ |
| | | const auto nControlCode = static_cast<short>(enControlCode); |
| | | if (nControlCode < 0 || nControlCode > 2) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); // åæ°é误 |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | nRet = mdControl(m_nPath, CombineStation(station), nControlCode); |
| | | } |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | nRet = mdControl(m_nPath, CombineStation(station), nControlCode); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | // äºä»¶çå¾
|
| | | // äºä»¶çå¾
|
| | | int CPerformanceMelsec::WaitForBoardEvent(std::vector<short> vecEventNumbers, const int nTimeoutMs, EventDetails& details) { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | |
| | | if (!m_bConnected.load()) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | if (!m_bConnected.load()) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | |
| | | if (vecEventNumbers.empty() || vecEventNumbers.size() > 64) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | if (vecEventNumbers.empty() || vecEventNumbers.size() > 64) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | // 第 0 个å
ç´ å卿°éï¼æå¤§æ¯æ 64 个äºä»¶ |
| | | std::array<short, 65> eventno = { 0 }; |
| | | eventno[0] = static_cast<short>(vecEventNumbers.size()); |
| | | std::copy(vecEventNumbers.begin(), vecEventNumbers.end(), eventno.begin() + 1); |
| | | // 第 0 个å
ç´ å卿°éï¼æå¤§æ¯æ 64 个äºä»¶ |
| | | std::array<short, 65> eventno = { 0 }; |
| | | eventno[0] = static_cast<short>(vecEventNumbers.size()); |
| | | std::copy(vecEventNumbers.begin(), vecEventNumbers.end(), eventno.begin() + 1); |
| | | |
| | | // åå§åè¾åºåæ° |
| | | details.nEventNo = 0; |
| | | details.details.fill(0); |
| | | // åå§åè¾åºåæ° |
| | | details.nEventNo = 0; |
| | | details.details.fill(0); |
| | | |
| | | const int nRet = mdWaitBdEvent(m_nPath, eventno.data(), nTimeoutMs, &details.nEventNo, details.details.data()); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | const int nRet = mdWaitBdEvent(m_nPath, eventno.data(), nTimeoutMs, &details.nEventNo, details.details.data()); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | return nRet; |
| | | } |
| | | |
| | | //============================================è¾
å©å½æ°======================================================= |
| | | // æ´æ°æè¿çéè¯¯ä¿¡æ¯ |
| | | //============================================è¾
å©å½æ°======================================================= |
| | | // æ´æ°æè¿çéè¯¯ä¿¡æ¯ |
| | | void CPerformanceMelsec::UpdateLastError(const int nCode) { |
| | | if (nCode == 0) { |
| | | return; |
| | | } |
| | | if (nCode == 0) { |
| | | return; |
| | | } |
| | | |
| | | // æ£æ¥éè¯¯ç æ¯å¦åå¨äºæ å°è¡¨ä¸ |
| | | const auto it = m_mapError.find(nCode); |
| | | if (it != m_mapError.end()) { |
| | | // 妿æ¾å°ï¼ç´æ¥è¿å对åºè¯è¨çéè¯¯ä¿¡æ¯ |
| | | m_strLastError = it->second; |
| | | } |
| | | else { |
| | | // å¦ææªæ¾å°ï¼å¤çç¹æ®èå´ |
| | | m_strLastError = "Unknown error."; |
| | | if (nCode == -28611 || nCode == -28612) { |
| | | // ç³»ç»åºé |
| | | m_strLastError = "System error."; |
| | | } |
| | | // æ£æ¥éè¯¯ç æ¯å¦åå¨äºæ å°è¡¨ä¸ |
| | | const auto it = m_mapError.find(nCode); |
| | | if (it != m_mapError.end()) { |
| | | // 妿æ¾å°ï¼ç´æ¥è¿å对åºè¯è¨çéè¯¯ä¿¡æ¯ |
| | | m_strLastError = it->second; |
| | | } |
| | | else { |
| | | // å¦ææªæ¾å°ï¼å¤çç¹æ®èå´ |
| | | m_strLastError = "Unknown error."; |
| | | if (nCode == -28611 || nCode == -28612) { |
| | | // ç³»ç»åºé |
| | | m_strLastError = "System error."; |
| | | } |
| | | |
| | | if (nCode >= -20480 && nCode <= -16384) { |
| | | // CC-Link ç³»ç»æ£æµåºçé误 |
| | | m_strLastError = "Error detected in the CC-Link system."; |
| | | } |
| | | if (nCode >= -20480 && nCode <= -16384) { |
| | | // CC-Link ç³»ç»æ£æµåºçé误 |
| | | m_strLastError = "Error detected in the CC-Link system."; |
| | | } |
| | | |
| | | if (nCode >= -12288 && nCode <= -8193) { |
| | | // CC-Link IE TSN ç³»ç»æ£æµåºçé误 |
| | | m_strLastError = "Error detected in the CC-Link IE TSN system."; |
| | | } |
| | | if (nCode >= -12288 && nCode <= -8193) { |
| | | // CC-Link IE TSN ç³»ç»æ£æµåºçé误 |
| | | m_strLastError = "Error detected in the CC-Link IE TSN system."; |
| | | } |
| | | |
| | | if (nCode >= -8192 && nCode <= -4097) { |
| | | // CC-Link IE æ§å¶ç½ç»ç³»ç»æ£æµåºçé误 |
| | | m_strLastError = "Error detected in the CC-Link IE control network system."; |
| | | } |
| | | if (nCode >= -8192 && nCode <= -4097) { |
| | | // CC-Link IE æ§å¶ç½ç»ç³»ç»æ£æµåºçé误 |
| | | m_strLastError = "Error detected in the CC-Link IE control network system."; |
| | | } |
| | | |
| | | if (nCode >= -4096 && nCode <= -257) { |
| | | // MELSECNET/10 æ MELSECNET/ç½ç»ç³»ç»é误èå´ |
| | | m_strLastError = "Errors detected in MELSECNET/10 or MELSECNET/network system."; |
| | | } |
| | | if (nCode >= -4096 && nCode <= -257) { |
| | | // MELSECNET/10 æ MELSECNET/ç½ç»ç³»ç»é误èå´ |
| | | m_strLastError = "Errors detected in MELSECNET/10 or MELSECNET/network system."; |
| | | } |
| | | |
| | | if (nCode >= 4096 && nCode <= 16383) { |
| | | // MELSEC æ°æ®é¾æ¥åºèå´ |
| | | m_strLastError = "Internal error detected by MELSEC Data Link Library."; |
| | | } |
| | | if (nCode >= 4096 && nCode <= 16383) { |
| | | // MELSEC æ°æ®é¾æ¥åºèå´ |
| | | m_strLastError = "Internal error detected by MELSEC Data Link Library."; |
| | | } |
| | | |
| | | if (nCode == 18944 || nCode == 18945) { |
| | | // 龿¥å
³èåºé |
| | | m_strLastError = "Link association error: Network does not exist, unsupported CPU, or incorrect network No./station number."; |
| | | } |
| | | if (nCode == 18944 || nCode == 18945) { |
| | | // 龿¥å
³èåºé |
| | | m_strLastError = "Link association error: Network does not exist, unsupported CPU, or incorrect network No./station number."; |
| | | } |
| | | |
| | | if (nCode >= 16384 && nCode <= 20479) { |
| | | // PLC CPU æ£æµèå´ |
| | | m_strLastError = "Errors detected by the programmable controller CPU in the target station."; |
| | | } |
| | | if (nCode >= 16384 && nCode <= 20479) { |
| | | // PLC CPU æ£æµèå´ |
| | | m_strLastError = "Errors detected by the programmable controller CPU in the target station."; |
| | | } |
| | | |
| | | if (nCode >= 28416 && nCode <= 28671) { |
| | | // åä½åè½æ¨¡åèå´ |
| | | m_strLastError = "Error detected in the redundancy module of the target station."; |
| | | } |
| | | } |
| | | if (nCode >= 28416 && nCode <= 28671) { |
| | | // åä½åè½æ¨¡åèå´ |
| | | m_strLastError = "Error detected in the redundancy module of the target station."; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // æ£æ¥è¿æ¥ç¶æåç«ç¹åæ°æææ§ |
| | | // æ£æ¥è¿æ¥ç¶æåç«ç¹åæ°æææ§ |
| | | int CPerformanceMelsec::ValidateStation(const StationIdentifier& station) const { |
| | | // æ£æ¥æ¯å¦å·²è¿æ¥ |
| | | if (!m_bConnected.load()) { |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | // æ£æ¥æ¯å¦å·²è¿æ¥ |
| | | if (!m_bConnected.load()) { |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | |
| | | // æ£æ¥ç½ç»å·åç«ç¹å·èå´ |
| | | if (station.nNetNo < 0 || station.nNetNo > 239 || station.nStNo < 0 || station.nStNo > 255) { |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | // æ£æ¥ç½ç»å·åç«ç¹å·èå´ |
| | | if (station.nNetNo < 0 || station.nNetNo > 239 || station.nStNo < 0 || station.nStNo > 255) { |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | return 0; // åæ°ææ |
| | | return 0; // åæ°ææ |
| | | } |
| | | |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int CPerformanceMelsec::ValidateStationAndSize(const StationIdentifier& station, const short nCount) const { |
| | | // éªè¯ç«ç¹åæ° |
| | | const int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | return nRet; // 妿ç«ç¹éªè¯å¤±è´¥ï¼è¿å对åºé误ç |
| | | } |
| | | // éªè¯ç«ç¹åæ° |
| | | const int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | return nRet; // 妿ç«ç¹éªè¯å¤±è´¥ï¼è¿å对åºé误ç |
| | | } |
| | | |
| | | if (nCount <= 0) { |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | if (nCount <= 0) { |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | return 0; // éªè¯éè¿ |
| | | return 0; // éªè¯éè¿ |
| | | } |
| | | |
| | | // IPå符串转uint32_t |
| | | // IPå符串转uint32_t |
| | | bool CPerformanceMelsec::ConvertIpStringToUint32(const std::string& strIP, uint32_t& nIP) { |
| | | nIP = 0; |
| | | std::stringstream ss(strIP); |
| | | std::string strSegment; |
| | | int nShift = 24; |
| | | nIP = 0; |
| | | std::stringstream ss(strIP); |
| | | std::string strSegment; |
| | | int nShift = 24; |
| | | |
| | | while (std::getline(ss, strSegment, '.')) { |
| | | const auto nByte = static_cast<uint32_t>(std::stoi(strSegment)); |
| | | if (nByte > 255) { |
| | | return false; |
| | | } |
| | | nIP |= (nByte << nShift); |
| | | nShift -= 8; |
| | | } |
| | | while (std::getline(ss, strSegment, '.')) { |
| | | const auto nByte = static_cast<uint32_t>(std::stoi(strSegment)); |
| | | if (nByte > 255) { |
| | | return false; |
| | | } |
| | | nIP |= (nByte << nShift); |
| | | nShift -= 8; |
| | | } |
| | | |
| | | return true; |
| | | return true; |
| | | } |
| | | |
| | | //============================================éæè¾
å©å½æ°==================================================== |
| | | // å»¶æ¶ï¼å¹¶ä¸è½¬åçªå£æ¶æ¯ |
| | | //============================================éæè¾
å©å½æ°==================================================== |
| | | // å»¶æ¶ï¼å¹¶ä¸è½¬åçªå£æ¶æ¯ |
| | | void CPerformanceMelsec::Delay(const unsigned int nDelayMs) { |
| | | MSG message; |
| | | // å¦æå»¶è¿æ¶é´ä¸º 0ï¼ä»
å¤ç䏿¬¡æ¶æ¯éå |
| | | if (nDelayMs == 0) { |
| | | // éé»å¡çæ£æ¥æ¶æ¯éå |
| | | if (PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { |
| | | TranslateMessage(&message); // å°æ¶æ¯è½¬å为ææççªå£æ¶æ¯ |
| | | DispatchMessage(&message); // æ´¾åæ¶æ¯ç»ç¸åºççªå£è¿ç¨ |
| | | } |
| | | return; |
| | | } |
| | | MSG message; |
| | | // å¦æå»¶è¿æ¶é´ä¸º 0ï¼ä»
å¤ç䏿¬¡æ¶æ¯éå |
| | | if (nDelayMs == 0) { |
| | | // éé»å¡çæ£æ¥æ¶æ¯éå |
| | | if (PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { |
| | | TranslateMessage(&message); // å°æ¶æ¯è½¬å为ææççªå£æ¶æ¯ |
| | | DispatchMessage(&message); // æ´¾åæ¶æ¯ç»ç¸åºççªå£è¿ç¨ |
| | | } |
| | | return; |
| | | } |
| | | |
| | | DWORD finish; |
| | | const DWORD start = GetTickCount(); // è·åå½åçæ¶é´æ³ï¼ä»ç³»ç»å¯å¨ä»¥æ¥çæ¯«ç§æ°ï¼ |
| | | do { |
| | | if (PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { |
| | | TranslateMessage(&message); // è½¬æ¢æ¶æ¯ |
| | | DispatchMessage(&message); // å¤çæ¶æ¯ |
| | | } |
| | | Sleep(1); // æå 1 毫ç§ï¼é²æ¢è¿åº¦å ç¨ CPU |
| | | finish = GetTickCount(); // è·åå½åçæ¶é´æ³ |
| | | } while ((finish - start) < nDelayMs); // 循ç¯ç´å°ç»è¿çæ¶é´å¤§äºæå®çå»¶è¿æ¶é´ |
| | | DWORD finish; |
| | | const DWORD start = GetTickCount(); // è·åå½åçæ¶é´æ³ï¼ä»ç³»ç»å¯å¨ä»¥æ¥çæ¯«ç§æ°ï¼ |
| | | do { |
| | | if (PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { |
| | | TranslateMessage(&message); // è½¬æ¢æ¶æ¯ |
| | | DispatchMessage(&message); // å¤çæ¶æ¯ |
| | | } |
| | | Sleep(1); // æå 1 毫ç§ï¼é²æ¢è¿åº¦å ç¨ CPU |
| | | finish = GetTickCount(); // è·åå½åçæ¶é´æ³ |
| | | } while ((finish - start) < nDelayMs); // 循ç¯ç´å°ç»è¿çæ¶é´å¤§äºæå®çå»¶è¿æ¶é´ |
| | | } |
| | | |
| | | BoardType CPerformanceMelsec::FindBoardTypeByChannel(const int nChannel) { |
| | | if (nChannel >= MELSECNET_CHANNEL(1) && nChannel <= MELSECNET_CHANNEL(4)) { |
| | | return BoardType::MELSECNET_H; |
| | | } |
| | | else if (nChannel >= CC_LINK_CHANNEL(1) && nChannel <= CC_LINK_CHANNEL(4)) { |
| | | return BoardType::CC_LINK_VER_2; |
| | | } |
| | | else if (nChannel >= CC_LINK_IE_CONTROL_CHANNEL(1) && nChannel <= CC_LINK_IE_CONTROL_CHANNEL(4)) { |
| | | return BoardType::CC_LINK_IE_CONTROL; |
| | | } |
| | | else if (nChannel >= CC_LINK_IE_FIELD_CHANNEL(1) && nChannel <= CC_LINK_IE_FIELD_CHANNEL(4)) { |
| | | return BoardType::CC_LINK_IE_FIELD; |
| | | } |
| | | else if (nChannel >= CC_LINK_IE_TSN_CHANNEL(1) && nChannel <= CC_LINK_IE_TSN_CHANNEL(4)) { |
| | | return BoardType::CC_LINK_IE_TSN; |
| | | } |
| | | return BoardType::UNKNOWN; |
| | | if (nChannel >= MELSECNET_CHANNEL(1) && nChannel <= MELSECNET_CHANNEL(4)) { |
| | | return BoardType::MELSECNET_H; |
| | | } |
| | | else if (nChannel >= CC_LINK_CHANNEL(1) && nChannel <= CC_LINK_CHANNEL(4)) { |
| | | return BoardType::CC_LINK_VER_2; |
| | | } |
| | | else if (nChannel >= CC_LINK_IE_CONTROL_CHANNEL(1) && nChannel <= CC_LINK_IE_CONTROL_CHANNEL(4)) { |
| | | return BoardType::CC_LINK_IE_CONTROL; |
| | | } |
| | | else if (nChannel >= CC_LINK_IE_FIELD_CHANNEL(1) && nChannel <= CC_LINK_IE_FIELD_CHANNEL(4)) { |
| | | return BoardType::CC_LINK_IE_FIELD; |
| | | } |
| | | else if (nChannel >= CC_LINK_IE_TSN_CHANNEL(1) && nChannel <= CC_LINK_IE_TSN_CHANNEL(4)) { |
| | | return BoardType::CC_LINK_IE_TSN; |
| | | } |
| | | return BoardType::UNKNOWN; |
| | | } |
| | | |
| | | // åå¹¶ç½ç»å·åç«ç¹å· |
| | | // åå¹¶ç½ç»å·åç«ç¹å· |
| | | short CPerformanceMelsec::CombineStation(const StationIdentifier& station) { |
| | | return static_cast<short>(station.nStNo | ((station.nNetNo << 8) & 0xFF00)); |
| | | return static_cast<short>(station.nStNo | ((station.nNetNo << 8) & 0xFF00)); |
| | | } |
| | | |
| | | // 计ç®è½¯å
ä»¶ç±»å |
| | | // 计ç®è½¯å
ä»¶ç±»å |
| | | short CPerformanceMelsec::CalculateDeviceType(const StationIdentifier& station, DeviceType enDevType) { |
| | | int nDevType = static_cast<int>(enDevType); |
| | | int nDevType = static_cast<int>(enDevType); |
| | | |
| | | // æ ¹æ®è½¯å
ä»¶ç±»åçç¹å®è§åè¿è¡è®¡ç® |
| | | if (enDevType == DeviceType::LX || enDevType == DeviceType::LY || |
| | | enDevType == DeviceType::LB || enDevType == DeviceType::LW || |
| | | enDevType == DeviceType::LSB || enDevType == DeviceType::LSW) { |
| | | // ç½ç»å·å åç§» |
| | | nDevType += station.nNetNo; |
| | | } |
| | | else if (enDevType == DeviceType::ER) { |
| | | // æä»¶å¯åå¨çåå·å åç§» |
| | | nDevType += 0; |
| | | } |
| | | else if (enDevType == DeviceType::SPG) { |
| | | // èµ·å§ I/O No. ÷ 16 çå¼ |
| | | nDevType += 0 / 16; |
| | | } |
| | | // æ ¹æ®è½¯å
ä»¶ç±»åçç¹å®è§åè¿è¡è®¡ç® |
| | | if (enDevType == DeviceType::LX || enDevType == DeviceType::LY || |
| | | enDevType == DeviceType::LB || enDevType == DeviceType::LW || |
| | | enDevType == DeviceType::LSB || enDevType == DeviceType::LSW) { |
| | | // ç½ç»å·å åç§» |
| | | nDevType += station.nNetNo; |
| | | } |
| | | else if (enDevType == DeviceType::ER) { |
| | | // æä»¶å¯åå¨çåå·å åç§» |
| | | nDevType += 0; |
| | | } |
| | | else if (enDevType == DeviceType::SPG) { |
| | | // èµ·å§ I/O No. ÷ 16 çå¼ |
| | | nDevType += 0 / 16; |
| | | } |
| | | |
| | | return static_cast<short>(nDevType); |
| | | return static_cast<short>(nDevType); |
| | | } |
| | | |
| | | // std::vector<char>转æ¢ä¸ºstd::vector<short> |
| | | // std::vector<char>转æ¢ä¸ºstd::vector<short> |
| | | void CPerformanceMelsec::ConvertCharToShort(const std::vector<char>& vecChar, std::vector<short>& vecShort) { |
| | | vecShort.resize((vecChar.size() + 1) / 2, 0); // è°æ´ short 容å¨å¤§å° |
| | | for (size_t i = 0; i < vecChar.size(); i++) { |
| | | if (i % 2 == 0) { |
| | | vecShort[i / 2] = static_cast<unsigned char>(vecChar[i]); // ä½åè |
| | | } |
| | | else { |
| | | vecShort[i / 2] |= static_cast<unsigned char>(vecChar[i]) << 8; // é«åè |
| | | } |
| | | } |
| | | vecShort.resize((vecChar.size() + 1) / 2, 0); // è°æ´ short 容å¨å¤§å° |
| | | for (size_t i = 0; i < vecChar.size(); i++) { |
| | | if (i % 2 == 0) { |
| | | vecShort[i / 2] = static_cast<unsigned char>(vecChar[i]); // ä½åè |
| | | } |
| | | else { |
| | | vecShort[i / 2] |= static_cast<unsigned char>(vecChar[i]) << 8; // é«åè |
| | | } |
| | | } |
| | | } |
| | | |
| | | // std::vector<short>转æ¢ä¸ºstd::vector<char> |
| | | // std::vector<short>转æ¢ä¸ºstd::vector<char> |
| | | void CPerformanceMelsec::ConvertShortToChar(const std::vector<short>& vecShort, std::vector<char>& vecChar) { |
| | | vecChar.resize(vecShort.size() * 2); // è°æ´ char 容å¨å¤§å° |
| | | for (size_t i = 0; i < vecShort.size(); i++) { |
| | | vecChar[i * 2] = static_cast<char>(vecShort[i] & 0xFF); // ä½åè |
| | | vecChar[i * 2 + 1] = static_cast<char>((vecShort[i] >> 8) & 0xFF); // é«åè |
| | | } |
| | | vecChar.resize(vecShort.size() * 2); // è°æ´ char 容å¨å¤§å° |
| | | for (size_t i = 0; i < vecShort.size(); i++) { |
| | | vecChar[i * 2] = static_cast<char>(vecShort[i] & 0xFF); // ä½åè |
| | | vecChar[i * 2 + 1] = static_cast<char>((vecShort[i] >> 8) & 0xFF); // é«åè |
| | | } |
| | | } |
| | | |
| | | // std::vector<uint8_t>转æ¢ä¸ºstd::vector<short> |
| | | // std::vector<uint8_t>转æ¢ä¸ºstd::vector<short> |
| | | void CPerformanceMelsec::ConvertUint8ToShort(const std::vector<uint8_t>& vecUint8, std::vector<short>& vecShort) { |
| | | vecShort.resize((vecUint8.size() + 1) / 2, 0); // è°æ´ short 容å¨å¤§å° |
| | | for (size_t i = 0; i < vecUint8.size(); i++) { |
| | | if (i % 2 == 0) { |
| | | vecShort[i / 2] = static_cast<short>(vecUint8[i]); // ä½åè |
| | | } |
| | | else { |
| | | vecShort[i / 2] |= static_cast<short>(vecUint8[i] << 8); // é«åè |
| | | } |
| | | } |
| | | vecShort.resize((vecUint8.size() + 1) / 2, 0); // è°æ´ short 容å¨å¤§å° |
| | | for (size_t i = 0; i < vecUint8.size(); i++) { |
| | | if (i % 2 == 0) { |
| | | vecShort[i / 2] = static_cast<short>(vecUint8[i]); // ä½åè |
| | | } |
| | | else { |
| | | vecShort[i / 2] |= static_cast<short>(vecUint8[i] << 8); // é«åè |
| | | } |
| | | } |
| | | } |
| | | |
| | | // std::vector<short>转æ¢ä¸ºstd::vector<uint8_t> |
| | | // std::vector<short>转æ¢ä¸ºstd::vector<uint8_t> |
| | | void CPerformanceMelsec::ConvertShortToUint8(const std::vector<short>& vecShort, std::vector<uint8_t>& vecUint8) { |
| | | vecUint8.resize(vecShort.size() * 2); // è°æ´ uint8_t 容å¨å¤§å° |
| | | for (size_t i = 0; i < vecShort.size(); i++) { |
| | | vecUint8[i * 2] = static_cast<uint8_t>(vecShort[i] & 0xFF); // ä½åè |
| | | vecUint8[i * 2 + 1] = static_cast<uint8_t>((vecShort[i] >> 8) & 0xFF); // é«åè |
| | | } |
| | | vecUint8.resize(vecShort.size() * 2); // è°æ´ uint8_t 容å¨å¤§å° |
| | | for (size_t i = 0; i < vecShort.size(); i++) { |
| | | vecUint8[i * 2] = static_cast<uint8_t>(vecShort[i] & 0xFF); // ä½åè |
| | | vecUint8[i * 2 + 1] = static_cast<uint8_t>((vecShort[i] >> 8) & 0xFF); // é«åè |
| | | } |
| | | } |
| | | |
| | | // std::vector<uint32_t>转æ¢ä¸ºstd::vector<short> |
| | | // std::vector<uint32_t>转æ¢ä¸ºstd::vector<short> |
| | | void CPerformanceMelsec::ConvertUint32ToShort(const std::vector<uint32_t>& vecUint32, std::vector<short>& vecShort) { |
| | | vecShort.resize(vecUint32.size() * 2); // æ¯ä¸ª uint32_t 转æ¢ä¸ºä¸¤ä¸ª short |
| | | for (size_t i = 0; i < vecUint32.size(); i++) { |
| | | vecShort[i * 2] = static_cast<short>(vecUint32[i] & 0xFFFF); // ä½16ä½ |
| | | vecShort[i * 2 + 1] = static_cast<short>((vecUint32[i] >> 16) & 0xFFFF); // é«16ä½ |
| | | } |
| | | vecShort.resize(vecUint32.size() * 2); // æ¯ä¸ª uint32_t 转æ¢ä¸ºä¸¤ä¸ª short |
| | | for (size_t i = 0; i < vecUint32.size(); i++) { |
| | | vecShort[i * 2] = static_cast<short>(vecUint32[i] & 0xFFFF); // ä½16ä½ |
| | | vecShort[i * 2 + 1] = static_cast<short>((vecUint32[i] >> 16) & 0xFFFF); // é«16ä½ |
| | | } |
| | | } |
| | | |
| | | // std::vector<short>转æ¢ä¸ºstd::vector<uint32_t> |
| | | // std::vector<short>转æ¢ä¸ºstd::vector<uint32_t> |
| | | void CPerformanceMelsec::ConvertShortToUint32(const std::vector<short>& vecShort, std::vector<uint32_t>& vecUint32) { |
| | | vecUint32.resize((vecShort.size() + 1) / 2, 0); // æ¯ä¸¤ä¸ª short å并为ä¸ä¸ª uint32_t |
| | | for (size_t i = 0; i < vecUint32.size(); i++) { |
| | | vecUint32[i] = (static_cast<uint32_t>(static_cast<uint16_t>(vecShort[i * 2 + 1])) << 16) | // é«16ä½ |
| | | static_cast<uint32_t>(static_cast<uint16_t>(vecShort[i * 2])); // ä½16ä½ |
| | | } |
| | | vecUint32.resize((vecShort.size() + 1) / 2, 0); // æ¯ä¸¤ä¸ª short å并为ä¸ä¸ª uint32_t |
| | | for (size_t i = 0; i < vecUint32.size(); i++) { |
| | | vecUint32[i] = (static_cast<uint32_t>(static_cast<uint16_t>(vecShort[i * 2 + 1])) << 16) | // é«16ä½ |
| | | static_cast<uint32_t>(static_cast<uint16_t>(vecShort[i * 2])); // ä½16ä½ |
| | | } |
| | | } |
| | | |
| | | //============================================模æ¿è¾
å©å½æ°==================================================== |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | //============================================模æ¿è¾
å©å½æ°==================================================== |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | template <typename T> |
| | | int CPerformanceMelsec::ValidateStationAndData(const StationIdentifier& station, const std::vector<T>& vecData) { |
| | | // éªè¯ç«ç¹åæ° |
| | | const int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | return nRet; // 妿ç«ç¹éªè¯å¤±è´¥ï¼è¿å对åºé误ç |
| | | } |
| | | // éªè¯ç«ç¹åæ° |
| | | const int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | return nRet; // 妿ç«ç¹éªè¯å¤±è´¥ï¼è¿å对åºé误ç |
| | | } |
| | | |
| | | // éªè¯æ°æ®æ¯å¦ä¸ºç©º |
| | | if (vecData.empty()) { |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | // éªè¯æ°æ®æ¯å¦ä¸ºç©º |
| | | if (vecData.empty()) { |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | return 0; // éªè¯éè¿ |
| | | return 0; // éªè¯éè¿ |
| | | } |
| | | |
| | | // ç±ä½è½¬é«å®¹å¨ç模æ¿ï¼æ´åï¼ |
| | | // ç±ä½è½¬é«å®¹å¨ç模æ¿ï¼æ´åï¼ |
| | | template <typename T, typename U> |
| | | void CPerformanceMelsec::ConvertLowToHigh(const std::vector<T>& vecLow, std::vector<U>& vecHigh) { |
| | | static_assert(std::is_integral<T>::value && std::is_integral<U>::value, "T and U must be integral types"); |
| | | static_assert(std::is_integral<T>::value && std::is_integral<U>::value, "T and U must be integral types"); |
| | | |
| | | // èªå¨è®¡ç® nGroupSize |
| | | constexpr size_t nGroupSize = sizeof(U) / sizeof(T); |
| | | // èªå¨è®¡ç® nGroupSize |
| | | constexpr size_t nGroupSize = sizeof(U) / sizeof(T); |
| | | |
| | | // 妿 T å U ç大å°ç¸çï¼ç´æ¥è½¬æ¢ |
| | | if (sizeof(T) == sizeof(U)) { |
| | | vecHigh.assign(vecLow.begin(), vecLow.end()); |
| | | return; |
| | | } |
| | | // 妿 T å U ç大å°ç¸çï¼ç´æ¥è½¬æ¢ |
| | | if (sizeof(T) == sizeof(U)) { |
| | | vecHigh.assign(vecLow.begin(), vecLow.end()); |
| | | return; |
| | | } |
| | | |
| | | // 妿 U ç大尿¯ T çåæ°ï¼æ£å¸¸ç»å |
| | | static_assert(sizeof(U) > sizeof(T), "Size of U must be greater than or equal to size of T"); |
| | | // 妿 U ç大尿¯ T çåæ°ï¼æ£å¸¸ç»å |
| | | static_assert(sizeof(U) > sizeof(T), "Size of U must be greater than or equal to size of T"); |
| | | |
| | | // 计ç®å®æ´ç»çæ°é |
| | | size_t nHighSize = (vecLow.size() + nGroupSize - 1) / nGroupSize; // åä¸åæ´ |
| | | vecHigh.resize(nHighSize, 0); |
| | | // 计ç®å®æ´ç»çæ°é |
| | | size_t nHighSize = (vecLow.size() + nGroupSize - 1) / nGroupSize; // åä¸åæ´ |
| | | vecHigh.resize(nHighSize, 0); |
| | | |
| | | // åå¹¶ä½ä½æ°æ®å°é«ä½æ°æ® |
| | | for (size_t i = 0; i < vecLow.size(); i++) { |
| | | vecHigh[i / nGroupSize] |= (static_cast<U>(vecLow[i]) << ((i % nGroupSize) * CHAR_BIT * sizeof(T))); |
| | | } |
| | | // åå¹¶ä½ä½æ°æ®å°é«ä½æ°æ® |
| | | for (size_t i = 0; i < vecLow.size(); i++) { |
| | | vecHigh[i / nGroupSize] |= (static_cast<U>(vecLow[i]) << ((i % nGroupSize) * CHAR_BIT * sizeof(T))); |
| | | } |
| | | |
| | | return vecHigh; |
| | | return vecHigh; |
| | | } |
| | | |
| | | // ç±é«è½¬ä½å®¹å¨ç模æ¿ï¼æ´åï¼ |
| | | // ç±é«è½¬ä½å®¹å¨ç模æ¿ï¼æ´åï¼ |
| | | template <typename T, typename U> |
| | | void CPerformanceMelsec::ConvertHighToLow(const std::vector<T>& vecHigh, std::vector<U>& vecLow) { |
| | | static_assert(std::is_integral<T>::value && std::is_integral<U>::value, "T and U must be integral types"); |
| | | static_assert(std::is_integral<T>::value && std::is_integral<U>::value, "T and U must be integral types"); |
| | | |
| | | // èªå¨è®¡ç® nGroupSize |
| | | constexpr size_t nGroupSize = sizeof(T) / sizeof(U); |
| | | // èªå¨è®¡ç® nGroupSize |
| | | constexpr size_t nGroupSize = sizeof(T) / sizeof(U); |
| | | |
| | | // 妿 T å U ç大å°ç¸çï¼ç´æ¥è½¬æ¢ |
| | | if (sizeof(T) == sizeof(U)) { |
| | | vecLow.assign(vecHigh.begin(), vecHigh.end()); |
| | | return; |
| | | } |
| | | // 妿 T å U ç大å°ç¸çï¼ç´æ¥è½¬æ¢ |
| | | if (sizeof(T) == sizeof(U)) { |
| | | vecLow.assign(vecHigh.begin(), vecHigh.end()); |
| | | return; |
| | | } |
| | | |
| | | // 妿 T ç大尿¯ U çåæ°ï¼æ£å¸¸åè§£ |
| | | static_assert(sizeof(T) > sizeof(U), "Size of T must be greater than or equal to size of U"); |
| | | // 妿 T ç大尿¯ U çåæ°ï¼æ£å¸¸åè§£ |
| | | static_assert(sizeof(T) > sizeof(U), "Size of T must be greater than or equal to size of U"); |
| | | |
| | | size_t nLowSize = vecHigh.size() * nGroupSize; // ä½å®¹å¨çå¤§å° |
| | | vecLow.resize(nLowSize, 0); |
| | | size_t nLowSize = vecHigh.size() * nGroupSize; // ä½å®¹å¨çå¤§å° |
| | | vecLow.resize(nLowSize, 0); |
| | | |
| | | // åè§£é«ä½æ°æ®å°ä½ä½æ°æ® |
| | | for (size_t i = 0; i < vecHigh.size(); i++) { |
| | | for (size_t j = 0; j < nGroupSize; j++) { |
| | | vecLow[i * nGroupSize + j] = static_cast<U>((vecHigh[i] >> (j * CHAR_BIT * sizeof(U))) & ((1ULL << (CHAR_BIT * sizeof(U))) - 1)); |
| | | } |
| | | } |
| | | // åè§£é«ä½æ°æ®å°ä½ä½æ°æ® |
| | | for (size_t i = 0; i < vecHigh.size(); i++) { |
| | | for (size_t j = 0; j < nGroupSize; j++) { |
| | | vecLow[i * nGroupSize + j] = static_cast<U>((vecHigh[i] >> (j * CHAR_BIT * sizeof(U))) & ((1ULL << (CHAR_BIT * sizeof(U))) - 1)); |
| | | } |
| | | } |
| | | |
| | | return vecLow; |
| | | return vecLow; |
| | | } |
| | |
| | | #include <sstream> |
| | | #include <unordered_map> |
| | | |
| | | // è¿æ¥åæ° |
| | | #define PLC_MAX_RETRY 3 // æå¤§éè¯æ¬¡æ°ï¼å¨ä¸PLCéä¿¡æ¶ï¼å¦æåçéä¿¡é误ï¼å°æå¤éè¯3次 |
| | | #define PLC_TIMEOUT 500 // è¶
æ¶æ¶é´ï¼æ¯«ç§ï¼ï¼æ¯æ¬¡éä¿¡æä½çè¶
æ¶çå¾
æ¶é´ä¸º500æ¯«ç§ |
| | | // è¿æ¥åæ° |
| | | #define PLC_MAX_RETRY 3 // æå¤§éè¯æ¬¡æ°ï¼å¨ä¸PLCéä¿¡æ¶ï¼å¦æåçéä¿¡é误ï¼å°æå¤éè¯3次 |
| | | #define PLC_TIMEOUT 500 // è¶
æ¶æ¶é´ï¼æ¯«ç§ï¼ï¼æ¯æ¬¡éä¿¡æä½çè¶
æ¶çå¾
æ¶é´ä¸º500æ¯«ç§ |
| | | |
| | | /* |
| | | * ç½ç»ééï¼æå®éä¿¡æä½¿ç¨çç½ç»ééå·ï¼é常å¨å¤éééä¿¡ä¸è®¾ç½® |
| | | * 51 å° 54 æ¯ MELSECNET/H ç 1-4 éé |
| | | * 81 å° 84 æ¯ CC-Link ç 1-4 éé |
| | | * 151 å° 154 æ¯ CC-Link IE æ§å¶å¨ç½ç»ç 1-4 éé |
| | | * 181 å° 184 æ¯ CC-Link IE ç°åºç½ç»ç 1-4 éé |
| | | * 281 å° 284 æ¯ CC-Link IE TSN ç½ç»ç 1-4 éé |
| | | * ç½ç»ééï¼æå®éä¿¡æä½¿ç¨çç½ç»ééå·ï¼é常å¨å¤éééä¿¡ä¸è®¾ç½® |
| | | * 51 å° 54 æ¯ MELSECNET/H ç 1-4 éé |
| | | * 81 å° 84 æ¯ CC-Link ç 1-4 éé |
| | | * 151 å° 154 æ¯ CC-Link IE æ§å¶å¨ç½ç»ç 1-4 éé |
| | | * 181 å° 184 æ¯ CC-Link IE ç°åºç½ç»ç 1-4 éé |
| | | * 281 å° 284 æ¯ CC-Link IE TSN ç½ç»ç 1-4 éé |
| | | **/ |
| | | #define MELSECNET_CHANNEL(x) (50 + (x)) // x èå´ï¼1~4 |
| | | #define CC_LINK_CHANNEL(x) (80 + (x)) // x èå´ï¼1~4 |
| | | #define CC_LINK_IE_CONTROL_CHANNEL(x) (150 + (x)) // x èå´ï¼1~4 |
| | | #define CC_LINK_IE_FIELD_CHANNEL(x) (180 + (x)) // x èå´ï¼1~4 |
| | | #define CC_LINK_IE_TSN_CHANNEL(x) (280 + (x)) // x èå´ï¼1~4 |
| | | #define MELSECNET_CHANNEL(x) (50 + (x)) // x èå´ï¼1~4 |
| | | #define CC_LINK_CHANNEL(x) (80 + (x)) // x èå´ï¼1~4 |
| | | #define CC_LINK_IE_CONTROL_CHANNEL(x) (150 + (x)) // x èå´ï¼1~4 |
| | | #define CC_LINK_IE_FIELD_CHANNEL(x) (180 + (x)) // x èå´ï¼1~4 |
| | | #define CC_LINK_IE_TSN_CHANNEL(x) (280 + (x)) // x èå´ï¼1~4 |
| | | |
| | | // èªå®ä¹é误ç |
| | | #define ERROR_CODE_UNKNOWN 0x00010000 // δ֪ |
| | | #define ERROR_CODE_NOT_CONNECTED 0x00020000 // æªè¿æ¥ |
| | | #define ERROR_CODE_INVALID_PARAM 0x00030000 // åæ°æ æ |
| | | #define ERROR_CODE_INVALID_DATA 0x00040000 // æ°æ®æ æ |
| | | #define ERROR_CODE_STATION_OUT_OF_RANGE 0x00050000 // ç«å·è¶
åºèå´ |
| | | #define ERROR_CODE_GROUP_OUT_OF_RANGE 0x00060000 // ç»å·è¶
åºèå´ |
| | | #define ERROR_CODE_NETWORK_OUT_OF_RANGE 0x00070000 // ç½ç»å·è¶
åºèå´ |
| | | // èªå®ä¹é误ç |
| | | #define ERROR_CODE_UNKNOWN 0x00010000 // æªç¥ |
| | | #define ERROR_CODE_NOT_CONNECTED 0x00020000 // æªè¿æ¥ |
| | | #define ERROR_CODE_INVALID_PARAM 0x00030000 // åæ°æ æ |
| | | #define ERROR_CODE_INVALID_DATA 0x00040000 // æ°æ®æ æ |
| | | #define ERROR_CODE_STATION_OUT_OF_RANGE 0x00050000 // ç«å·è¶
åºèå´ |
| | | #define ERROR_CODE_GROUP_OUT_OF_RANGE 0x00060000 // ç»å·è¶
åºèå´ |
| | | #define ERROR_CODE_NETWORK_OUT_OF_RANGE 0x00070000 // ç½ç»å·è¶
åºèå´ |
| | | |
| | | // æ¿åç±»å |
| | | // æ¿åç±»å |
| | | enum class BoardType { |
| | | UNKNOWN = -1, // æªç¥ç±»å |
| | | UNKNOWN = -1, // æªç¥ç±»å |
| | | MELSECNET_H = MELSECNET_CHANNEL(1), // MELSECNET/H |
| | | CC_LINK_VER_2 = CC_LINK_CHANNEL(1), // CC-Link Ver. 2 |
| | | CC_LINK_IE_CONTROL = CC_LINK_IE_CONTROL_CHANNEL(1), // CC-Link IE æ§å¶ç½ç» |
| | | CC_LINK_IE_FIELD = CC_LINK_IE_FIELD_CHANNEL(1), // CC-Link IE ç°åºç½ç» |
| | | CC_LINK_IE_CONTROL = CC_LINK_IE_CONTROL_CHANNEL(1), // CC-Link IE æ§å¶ç½ç» |
| | | CC_LINK_IE_FIELD = CC_LINK_IE_FIELD_CHANNEL(1), // CC-Link IE ç°åºç½ç» |
| | | CC_LINK_IE_TSN = CC_LINK_IE_TSN_CHANNEL(1) // CC-Link IE TSN |
| | | }; |
| | | |
| | | // 软å
ä»¶ç±»åæä¸¾ |
| | | // 软å
ä»¶ç±»åæä¸¾ |
| | | enum class DeviceType { |
| | | /* |
| | | * ERãLXãLYãLBãLWãLSBãLSWåSPG软å
件齿¯èå´å |
| | | * ERï¼DevER0ï½256 |
| | | * LXï¼DevLX1ï½255ï¼DevLX(x) (DevX*1000+(x)) |
| | | * LYï¼DevLY1ï½255ï¼DevLY(x) (DevY*1000+(x)) |
| | | * LBï¼DevLB1ï½255ï¼DevLB(x) (DevB*1000+(x)) |
| | | * LWï¼DevLW1ï½255ï¼DevLW(x) (DevW*1000+(x)) |
| | | * LSBï¼DevLSB1ï½255ï¼DevLSB(x) (DevQSB*1000+(x)) |
| | | * LSWï¼DevLSW1ï½255ï¼DevLSW(x) (DevQSW*1000+(x)) |
| | | * SPGï¼DevSPG0ï½255ï¼DevSPG(x) (29*1000+(x)) |
| | | * æ©å±æä»¶å¯åå¨ä»£ç æå®(10è¿å¶æ°)çå3使°å软å
ä»¶åæå®çæ°å¼ä¸ï¼åºæå®åNo.(0ï½256) |
| | | * 龿¥ç´æ¥è½¯å
ä»¶ä»£ç æå®(10è¿å¶æ°)çå3使°å软å
ä»¶åæå®çæ°å¼ä¸ï¼åºæå®ç½ç»No.(1ï½255) |
| | | * æºè½åè½æ¨¡å软å
ä»¶ä»£ç æå®(10è¿å¶æ°)çå3使°å软å
ä»¶åæå®çæ°å¼ä¸ï¼åºæå®(èµ·å§I/ONo.÷16)çå¼ |
| | | * æ©å±æä»¶å¯åå¨å龿¥ç´æ¥è½¯å
ä»¶å¨éæºè¯»å(mdRandRãmdRandREx)彿°ä¸ï¼å³ä½¿æå®å®é
ä¸åå¨ç软å
件乿å¯è½æ£å¸¸ç»æ |
| | | * MAILåMAILMCå¨SENDåè½åRECVåè½ä¸ï¼ä¸è½¯å
件访é®ä¸æ ·ï¼æå®ååè½å¯¹åºç软å
ä»¶ç±»åï¼è¿è¡æ°æ®çåé(mdSendãmdSendEx)ææ°æ®ç读å(mdReceiveãmdReceiveEx) |
| | | * ERãLXãLYãLBãLWãLSBãLSWåSPG软å
件齿¯èå´å |
| | | * ERï¼DevER0ï½256 |
| | | * LXï¼DevLX1ï½255ï¼DevLX(x) (DevX*1000+(x)) |
| | | * LYï¼DevLY1ï½255ï¼DevLY(x) (DevY*1000+(x)) |
| | | * LBï¼DevLB1ï½255ï¼DevLB(x) (DevB*1000+(x)) |
| | | * LWï¼DevLW1ï½255ï¼DevLW(x) (DevW*1000+(x)) |
| | | * LSBï¼DevLSB1ï½255ï¼DevLSB(x) (DevQSB*1000+(x)) |
| | | * LSWï¼DevLSW1ï½255ï¼DevLSW(x) (DevQSW*1000+(x)) |
| | | * SPGï¼DevSPG0ï½255ï¼DevSPG(x) (29*1000+(x)) |
| | | * æ©å±æä»¶å¯åå¨ä»£ç æå®(10è¿å¶æ°)çå3使°å软å
ä»¶åæå®çæ°å¼ä¸ï¼åºæå®åNo.(0ï½256) |
| | | * 龿¥ç´æ¥è½¯å
ä»¶ä»£ç æå®(10è¿å¶æ°)çå3使°å软å
ä»¶åæå®çæ°å¼ä¸ï¼åºæå®ç½ç»No.(1ï½255) |
| | | * æºè½åè½æ¨¡å软å
ä»¶ä»£ç æå®(10è¿å¶æ°)çå3使°å软å
ä»¶åæå®çæ°å¼ä¸ï¼åºæå®(èµ·å§I/ONo.÷16)çå¼ |
| | | * æ©å±æä»¶å¯åå¨å龿¥ç´æ¥è½¯å
ä»¶å¨éæºè¯»å(mdRandRãmdRandREx)彿°ä¸ï¼å³ä½¿æå®å®é
ä¸åå¨ç软å
件乿å¯è½æ£å¸¸ç»æ |
| | | * MAILåMAILMCå¨SENDåè½åRECVåè½ä¸ï¼ä¸è½¯å
件访é®ä¸æ ·ï¼æå®ååè½å¯¹åºç软å
ä»¶ç±»åï¼è¿è¡æ°æ®çåé(mdSendãmdSendEx)ææ°æ®ç读å(mdReceiveãmdReceiveEx) |
| | | **/ |
| | | |
| | | X = 0x0001, // è¾å
¥ (ä½) |
| | | Y = 0x0002, // è¾åº (ä½) |
| | | L = 0x0003, // éåç»§çµå¨ (ä½) |
| | | M = 0x0004, // å
é¨ç»§çµå¨ (ä½) |
| | | SM = 0x0005, // ç¹æ®ç»§çµå¨ (ä½) |
| | | F = 0x0006, // æ¥è¦å¨ (ä½) |
| | | TT = 0x0007, // 宿¶å¨ (触ç¹) (ä½) |
| | | TC = 0x0008, // 计æ°å¨ (线å) (ä½) |
| | | CT = 0x0009, // 计æ°å¨ (触ç¹) (ä½) |
| | | CC = 0x000A, // 计æ°å¨ (线å) (å) |
| | | TN = 0x000B, // 宿¶å¨ (å½åå¼) (å) |
| | | CN = 0x000C, // 计æ°å¨ (å½åå¼) (å) |
| | | D = 0x000D, // æ°æ®å¯åå¨ (å) |
| | | SD = 0x000E, // ç¹æ®å¯åå¨ (å) |
| | | TM = 0x000F, // 宿¶å¨ (设置å¼ä¸») (å) |
| | | TS = 0x0010, // 宿¶å¨ (设置å¼ä¸»1) (å) |
| | | TS2 = 0x3E82, // 宿¶å¨ (设置å¼ä¸»2) (å) |
| | | TS3 = 0x3E83, // 宿¶å¨ (设置å¼ä¸»3) (å) |
| | | CM = 0x0011, // 计æ°å¨ (设置å¼ä¸») (å) |
| | | CS = 0x0012, // 计æ°å¨ (设置å¼ä¸»1) (å) |
| | | CS2 = 0x4652, // 计æ°å¨ (设置å¼ä¸»2) (å) |
| | | CS3 = 0x4653, // 计æ°å¨ (设置å¼ä¸»3) (å) |
| | | A = 0x0013, // ç´¯å å¨ (å) |
| | | Z = 0x0014, // ååå¯åå¨ (å) |
| | | V = 0x0015, // ååå¯åå¨ (å) |
| | | R = 0x0016, // æä»¶å¯åå¨ (å忢æ¹å¼) (å) |
| | | ER = 0x55F0, // æ©å±æä»¶å¯åå¨ (å忢æ¹å¼) (0x55F0ï½0x56F0) (å) (å¨éæºè¯»å(mdRandRãmdRandREx)彿°ä¸ï¼å³ä½¿æå®å®é
ä¸åå¨ç软å
件乿å¯è½æ£å¸¸ç»æã(è¯»åæ°æ®ä¸æ£ç¡®ã)) |
| | | ZR = 0x00DC, // æä»¶å¯åå¨ (è¿å·è®¿é®æ¹å¼) (å) |
| | | B = 0x0017, // 龿¥ç»§çµå¨ (ä½) |
| | | W = 0x0018, // 龿¥å¯åå¨ (å) |
| | | QSB = 0x0019, // 龿¥ç¹æ®ç»§çµå¨ (ä½) |
| | | STT = 0x001A, // ç´¯è®¡å®æ¶å¨ (触ç¹) (ä½) |
| | | STC = 0x001B, // ç´¯è®¡å®æ¶å¨ (线å) (ä½) |
| | | QSW = 0x001C, // 龿¥ç¹æ®å¯åå¨ (å) |
| | | QV = 0x001E, // ååç»§çµå¨ (ä½) |
| | | MRB = 0x0021, // éæºè®¿é®ç¼å² (å) |
| | | STN = 0x0023, // ç´¯è®¡å®æ¶å¨ (å½åå¼) (å) |
| | | LZ = 0x0026, // è¶
é¿ååå¯åå¨ (åå) |
| | | RD = 0x0027, // å·æ°æ°æ®å¯åå¨ (å) |
| | | LTT = 0x0029, // è¶
é¿å®æ¶å¨ (触ç¹) (ä½) |
| | | LTC = 0x002A, // è¶
é¿å®æ¶å¨ (线å) (ä½) |
| | | LTN = 0x002B, // è¶
é¿å®æ¶å¨ (å½åå¼) (åå) |
| | | LCT = 0x002C, // è¶
é¿è®¡æ°å¨ (触ç¹) (ä½) |
| | | LCC = 0x002D, // è¶
é¿è®¡æ°å¨ (线å) (ä½) |
| | | LCN = 0x002E, // è¶
é¿è®¡æ°å¨ (å½åå¼) (åå) |
| | | LSTT = 0x002F, // è¶
é¿ç´¯è®¡å®æ¶å¨ (触ç¹) (ä½) |
| | | LSTC = 0x0030, // è¶
é¿ç´¯è®¡å®æ¶å¨ (线å) (ä½) |
| | | LSTN = 0x0031, // è¶
é¿ç´¯è®¡å®æ¶å¨ (å½åå¼) (åå) |
| | | SPB = 0x0032, // ç¼å²åå¨å¨ (å) |
| | | MAIL = 0x0065, // ç¹æ®è½¯å
ä»¶ç±»åï¼é®ä»¶ç±»å (10è¿å¶ 101) |
| | | MAILMC = 0x0066, // ç¹æ®è½¯å
ä»¶ç±»åï¼æ 确认é®ä»¶ (10è¿å¶ 102) |
| | | LX = 0x03E8, // 龿¥ç´æ¥è½¯å
ä»¶ (龿¥è¾å
¥) (0x03E9ï½0x04E7) (ä½) |
| | | LY = 0x07D0, // 龿¥ç´æ¥è½¯å
ä»¶ (龿¥è¾åº) (0x07D1ï½0x08CF) (ä½) |
| | | LB = 0x59D8, // 龿¥ç´æ¥è½¯å
ä»¶ (龿¥ç»§çµå¨) (0x59D9ï½0x5AD7) (ä½) |
| | | LW = 0x5DC0, // 龿¥ç´æ¥è½¯å
ä»¶ (龿¥å¯åå¨) (0x5DC1ï½0x5EBF) (å) |
| | | LSB = 0x61A8, // 龿¥ç´æ¥è½¯å
ä»¶ (龿¥ç¹æ®ç»§çµå¨) (0x61A9ï½0x62A7) (ä½) |
| | | LSW = 0x6D60, // 龿¥ç´æ¥è½¯å
ä»¶ (龿¥ç¹æ®å¯åå¨) (0x6D61ï½0x6E5F) (å) |
| | | SPG = 0x7147, // æºè½åè½æ¨¡å软å
ä»¶ (0x7148ï½0x7247) (å) |
| | | X = 0x0001, // è¾å
¥ (ä½) |
| | | Y = 0x0002, // è¾åº (ä½) |
| | | L = 0x0003, // éåç»§çµå¨ (ä½) |
| | | M = 0x0004, // å
é¨ç»§çµå¨ (ä½) |
| | | SM = 0x0005, // ç¹æ®ç»§çµå¨ (ä½) |
| | | F = 0x0006, // æ¥è¦å¨ (ä½) |
| | | TT = 0x0007, // 宿¶å¨ (触ç¹) (ä½) |
| | | TC = 0x0008, // 计æ°å¨ (线å) (ä½) |
| | | CT = 0x0009, // 计æ°å¨ (触ç¹) (ä½) |
| | | CC = 0x000A, // 计æ°å¨ (线å) (å) |
| | | TN = 0x000B, // 宿¶å¨ (å½åå¼) (å) |
| | | CN = 0x000C, // 计æ°å¨ (å½åå¼) (å) |
| | | D = 0x000D, // æ°æ®å¯åå¨ (å) |
| | | SD = 0x000E, // ç¹æ®å¯åå¨ (å) |
| | | TM = 0x000F, // 宿¶å¨ (设置å¼ä¸») (å) |
| | | TS = 0x0010, // 宿¶å¨ (设置å¼ä¸»1) (å) |
| | | TS2 = 0x3E82, // 宿¶å¨ (设置å¼ä¸»2) (å) |
| | | TS3 = 0x3E83, // 宿¶å¨ (设置å¼ä¸»3) (å) |
| | | CM = 0x0011, // 计æ°å¨ (设置å¼ä¸») (å) |
| | | CS = 0x0012, // 计æ°å¨ (设置å¼ä¸»1) (å) |
| | | CS2 = 0x4652, // 计æ°å¨ (设置å¼ä¸»2) (å) |
| | | CS3 = 0x4653, // 计æ°å¨ (设置å¼ä¸»3) (å) |
| | | A = 0x0013, // ç´¯å å¨ (å) |
| | | Z = 0x0014, // ååå¯åå¨ (å) |
| | | V = 0x0015, // ååå¯åå¨ (å) |
| | | R = 0x0016, // æä»¶å¯åå¨ (å忢æ¹å¼) (å) |
| | | ER = 0x55F0, // æ©å±æä»¶å¯åå¨ (å忢æ¹å¼) (0x55F0ï½0x56F0) (å) (å¨éæºè¯»å(mdRandRãmdRandREx)彿°ä¸ï¼å³ä½¿æå®å®é
ä¸åå¨ç软å
件乿å¯è½æ£å¸¸ç»æã(è¯»åæ°æ®ä¸æ£ç¡®ã)) |
| | | ZR = 0x00DC, // æä»¶å¯åå¨ (è¿å·è®¿é®æ¹å¼) (å) |
| | | B = 0x0017, // 龿¥ç»§çµå¨ (ä½) |
| | | W = 0x0018, // 龿¥å¯åå¨ (å) |
| | | QSB = 0x0019, // 龿¥ç¹æ®ç»§çµå¨ (ä½) |
| | | STT = 0x001A, // ç´¯è®¡å®æ¶å¨ (触ç¹) (ä½) |
| | | STC = 0x001B, // ç´¯è®¡å®æ¶å¨ (线å) (ä½) |
| | | QSW = 0x001C, // 龿¥ç¹æ®å¯åå¨ (å) |
| | | QV = 0x001E, // ååç»§çµå¨ (ä½) |
| | | MRB = 0x0021, // éæºè®¿é®ç¼å² (å) |
| | | STN = 0x0023, // ç´¯è®¡å®æ¶å¨ (å½åå¼) (å) |
| | | LZ = 0x0026, // è¶
é¿ååå¯åå¨ (åå) |
| | | RD = 0x0027, // å·æ°æ°æ®å¯åå¨ (å) |
| | | LTT = 0x0029, // è¶
é¿å®æ¶å¨ (触ç¹) (ä½) |
| | | LTC = 0x002A, // è¶
é¿å®æ¶å¨ (线å) (ä½) |
| | | LTN = 0x002B, // è¶
é¿å®æ¶å¨ (å½åå¼) (åå) |
| | | LCT = 0x002C, // è¶
é¿è®¡æ°å¨ (触ç¹) (ä½) |
| | | LCC = 0x002D, // è¶
é¿è®¡æ°å¨ (线å) (ä½) |
| | | LCN = 0x002E, // è¶
é¿è®¡æ°å¨ (å½åå¼) (åå) |
| | | LSTT = 0x002F, // è¶
é¿ç´¯è®¡å®æ¶å¨ (触ç¹) (ä½) |
| | | LSTC = 0x0030, // è¶
é¿ç´¯è®¡å®æ¶å¨ (线å) (ä½) |
| | | LSTN = 0x0031, // è¶
é¿ç´¯è®¡å®æ¶å¨ (å½åå¼) (åå) |
| | | SPB = 0x0032, // ç¼å²åå¨å¨ (å) |
| | | MAIL = 0x0065, // ç¹æ®è½¯å
ä»¶ç±»åï¼é®ä»¶ç±»å (10è¿å¶ 101) |
| | | MAILMC = 0x0066, // ç¹æ®è½¯å
ä»¶ç±»åï¼æ 确认é®ä»¶ (10è¿å¶ 102) |
| | | LX = 0x03E8, // 龿¥ç´æ¥è½¯å
ä»¶ (龿¥è¾å
¥) (0x03E9ï½0x04E7) (ä½) |
| | | LY = 0x07D0, // 龿¥ç´æ¥è½¯å
ä»¶ (龿¥è¾åº) (0x07D1ï½0x08CF) (ä½) |
| | | LB = 0x59D8, // 龿¥ç´æ¥è½¯å
ä»¶ (龿¥ç»§çµå¨) (0x59D9ï½0x5AD7) (ä½) |
| | | LW = 0x5DC0, // 龿¥ç´æ¥è½¯å
ä»¶ (龿¥å¯åå¨) (0x5DC1ï½0x5EBF) (å) |
| | | LSB = 0x61A8, // 龿¥ç´æ¥è½¯å
ä»¶ (龿¥ç¹æ®ç»§çµå¨) (0x61A9ï½0x62A7) (ä½) |
| | | LSW = 0x6D60, // 龿¥ç´æ¥è½¯å
ä»¶ (龿¥ç¹æ®å¯åå¨) (0x6D61ï½0x6E5F) (å) |
| | | SPG = 0x7147, // æºè½åè½æ¨¡å软å
ä»¶ (0x7148ï½0x7247) (å) |
| | | }; |
| | | |
| | | // æ°æ®ç±»å |
| | | // æ°æ®ç±»å |
| | | enum class DataType { |
| | | BIT = 1, // λ (1λ) |
| | | WORD = 2, // å (16ä½) |
| | | DWORD = 4 // åå (32ä½) |
| | | BIT = 1, // ä½ (1ä½) |
| | | WORD = 2, // å (16ä½) |
| | | DWORD = 4 // åå (32ä½) |
| | | }; |
| | | |
| | | // æ§å¶ä»£ç |
| | | // æ§å¶ä»£ç |
| | | enum class ControlCode { |
| | | RUN = 0, // è¿ç¨ RUN |
| | | STOP = 1, // è¿ç¨ STOP |
| | | PAUSE = 2 // è¿ç¨ PAUSE |
| | | RUN = 0, // è¿ç¨ RUN |
| | | STOP = 1, // è¿ç¨ STOP |
| | | PAUSE = 2 // è¿ç¨ PAUSE |
| | | }; |
| | | |
| | | // çæ¬ä¿¡æ¯ |
| | | // çæ¬ä¿¡æ¯ |
| | | struct BoardVersion { |
| | | char fixedValue[2]; // åºå®å¼ |
| | | char checksum[2]; // æ ¡éªå |
| | | char swVersion[2]; // è½¯ä»¶çæ¬ |
| | | char date[6]; // æ¥æ (æ ¼å¼ YYMMDD) |
| | | uint32_t reserved; // ä¿çåºå (4 åè) |
| | | char swModel[16]; // 软件åå· |
| | | char hwModel[16]; // 硬件åå· |
| | | char twoPortMemory[2]; // 两端å£åå¨å¨å ç¨å®¹é |
| | | char twoPortAttribute[2]; // 两端å£å±æ§ |
| | | char availableBias[2]; // å¯ä½¿ç¨åç½® |
| | | char moduleType[10]; // æºåç±»å |
| | | char fixedValue[2]; // åºå®å¼ |
| | | char checksum[2]; // æ ¡éªå |
| | | char swVersion[2]; // è½¯ä»¶çæ¬ |
| | | char date[6]; // æ¥æ (æ ¼å¼ YYMMDD) |
| | | uint32_t reserved; // ä¿çåºå (4 åè) |
| | | char swModel[16]; // 软件åå· |
| | | char hwModel[16]; // 硬件åå· |
| | | char twoPortMemory[2]; // 两端å£åå¨å¨å ç¨å®¹é |
| | | char twoPortAttribute[2]; // 两端å£å±æ§ |
| | | char availableBias[2]; // å¯ä½¿ç¨åç½® |
| | | char moduleType[10]; // æºåç±»å |
| | | |
| | | // è¾åºç»æä½å
容为å符串 (便äºè°è¯) |
| | | // è¾åºç»æä½å
容为å符串 (便äºè°è¯) |
| | | std::string toString() const { |
| | | std::ostringstream oss; |
| | | oss << "Fixed Value: " << fixedValue[0] << fixedValue[1] << "\n" |
| | |
| | | } |
| | | }; |
| | | |
| | | // ç«ç¹æ è¯ç¬¦ï¼é»è®¤ä½¿ç¨æ¬ç« |
| | | // ç«ç¹æ è¯ç¬¦ï¼é»è®¤ä½¿ç¨æ¬ç« |
| | | struct StationIdentifier { |
| | | /* |
| | | * [Network No.] |
| | | * 0 表示æ¬ç« |
| | | * 1~239 表示æ®éç½ç»å· |
| | | * 0 表示æ¬ç« |
| | | * 1~239 表示æ®éç½ç»å· |
| | | **/ |
| | | |
| | | /* |
| | | * [Station No.] |
| | | * MELSECNET/Hï¼1~64 表示å
¶ä»ç«ç¹ï¼255 表示æ¬ç« |
| | | * CC-Link ç³»åç½ç»çèå´ç±»ä¼¼ï¼åºå«å¨äºç«å·çåå¼èå´ |
| | | * MELSECNET/Hï¼1~64 表示å
¶ä»ç«ç¹ï¼255 表示æ¬ç« |
| | | * CC-Link ç³»åç½ç»çèå´ç±»ä¼¼ï¼åºå«å¨äºç«å·çåå¼èå´ |
| | | * MELSECNET/H : 1~64(Other stations),255(Own station) |
| | | * CC-Link : 0~63(Other stations),255(Own station) |
| | | * CC-Link IE Controller : 1~120(Other stations),255(Own station) |
| | |
| | | **/ |
| | | |
| | | /* |
| | | * é« 8 ä½ï¼ç½ç»å·ï¼ï¼ æå®è®¾å¤æå±çç½ç» |
| | | * ä½ 8 ä½ï¼ç«ç¹å·ï¼ï¼ æå®è®¾å¤å¨ç½ç»ä¸çç¼å· |
| | | * ç¨ä¸ä¸ªåæ°ä¼ é设å¤çç½ç»å·åç«ç¹å·æ¶: nSt = station.nStNo | ((station.nNetNo << 8) & 0xFF00); |
| | | * é« 8 ä½ï¼ç½ç»å·ï¼ï¼ æå®è®¾å¤æå±çç½ç» |
| | | * ä½ 8 ä½ï¼ç«ç¹å·ï¼ï¼ æå®è®¾å¤å¨ç½ç»ä¸çç¼å· |
| | | * ç¨ä¸ä¸ªåæ°ä¼ é设å¤çç½ç»å·åç«ç¹å·æ¶: nSt = station.nStNo | ((station.nNetNo << 8) & 0xFF00); |
| | | **/ |
| | | |
| | | short nNetNo = 0; // ç½ç»ç¼å·ï¼PLCæè¿æ¥çç½ç»ç¼å·ï¼0表示é»è®¤ç½ç» |
| | | short nStNo = 255; // ç«ç¹ç¼å·ï¼æå®ä¸PLCè¿æ¥çç«ç¹ç¼å·ï¼255éå¸¸è¡¨ç¤ºå¹¿ææææç«ç¹ |
| | | short nNetNo = 0; // ç½ç»ç¼å·ï¼PLCæè¿æ¥çç½ç»ç¼å·ï¼0表示é»è®¤ç½ç» |
| | | short nStNo = 255; // ç«ç¹ç¼å·ï¼æå®ä¸PLCè¿æ¥çç«ç¹ç¼å·ï¼255éå¸¸è¡¨ç¤ºå¹¿ææææç«ç¹ |
| | | |
| | | // èªå®ä¹æé 彿°ï¼è¦çé»è®¤å¼ |
| | | // èªå®ä¹æé 彿°ï¼è¦çé»è®¤å¼ |
| | | explicit StationIdentifier(const short net, const short st) : nNetNo(net), nStNo(st) {} |
| | | |
| | | StationIdentifier() |
| | |
| | | nStNo = 255; |
| | | } |
| | | |
| | | // å°âç½ç»å·âåâç«ç¹å·âç»åæä¸ä¸ªæç»ç¼ç |
| | | // å°âç½ç»å·âåâç«ç¹å·âç»åæä¸ä¸ªæç»ç¼ç |
| | | short StationIdentifier::toNetworkStationCode() const { |
| | | return static_cast<short>(nStNo | ((nNetNo << 8) & 0xFF00)); |
| | | } |
| | | |
| | | // éè½½ < è¿ç®ç¬¦ï¼ç¨äºæåºææ¯è¾ï¼é常ç¨äº map æ set ä¸ä½ä¸º keyï¼ |
| | | // éè½½ < è¿ç®ç¬¦ï¼ç¨äºæåºææ¯è¾ï¼é常ç¨äº map æ set ä¸ä½ä¸º keyï¼ |
| | | bool operator<(const StationIdentifier& other) const { |
| | | return std::tie(nNetNo, nStNo) < |
| | | std::tie(other.nNetNo, other.nStNo); |
| | | } |
| | | |
| | | // éè½½ == è¿ç®ç¬¦ï¼ç¨äºç¸çæ¯è¾ï¼ |
| | | // éè½½ == è¿ç®ç¬¦ï¼ç¨äºç¸çæ¯è¾ï¼ |
| | | bool operator==(const StationIdentifier& other) const { |
| | | return std::tie(nNetNo, nStNo) == |
| | | std::tie(other.nNetNo, other.nStNo); |
| | | } |
| | | |
| | | // éè½½ = è¿ç®ç¬¦ï¼ç¨äºèµå¼ï¼ |
| | | // éè½½ = è¿ç®ç¬¦ï¼ç¨äºèµå¼ï¼ |
| | | StationIdentifier& operator=(const StationIdentifier& other) { |
| | | if (this != &other) { |
| | | nNetNo = other.nNetNo; |
| | |
| | | } |
| | | }; |
| | | |
| | | // æ¿ç¶æ |
| | | // æ¿ç¶æ |
| | | struct BoardStatus { |
| | | short nStationValue = 0; // ç«å·ç设å¤å¼ (buf[0]) |
| | | short nGroupValue = 0; // ç» No. ç设å¤å¼ (buf[1]) |
| | | short nNetworkValue = 0; // ç½ç» No. ç设å¤å¼ (buf[2]) |
| | | short nReserved1 = 0; // ä¿çåæ®µ (buf[3]) |
| | | short nReserved2 = 0; // ä¿çåæ®µ (buf[4]) |
| | | short nReserved3 = 0; // ä¿çåæ®µ (buf[5]) |
| | | short nStationValue = 0; // ç«å·ç设å¤å¼ (buf[0]) |
| | | short nGroupValue = 0; // ç» No. ç设å¤å¼ (buf[1]) |
| | | short nNetworkValue = 0; // ç½ç» No. ç设å¤å¼ (buf[2]) |
| | | short nReserved1 = 0; // ä¿çåæ®µ (buf[3]) |
| | | short nReserved2 = 0; // ä¿çåæ®µ (buf[4]) |
| | | short nReserved3 = 0; // ä¿çåæ®µ (buf[5]) |
| | | |
| | | // å°æ°ç»æ å°å°ç»æä½ |
| | | // å°æ°ç»æ å°å°ç»æä½ |
| | | static BoardStatus fromBuffer(const short buf[6]) { |
| | | return { |
| | | buf[0], |
| | |
| | | }; |
| | | } |
| | | |
| | | // å°ç»æä½å
容æ å°å°æ°ç» |
| | | // å°ç»æä½å
容æ å°å°æ°ç» |
| | | void toBuffer(short buf[6]) const { |
| | | buf[0] = nStationValue; |
| | | buf[1] = nGroupValue; |
| | |
| | | buf[5] = nReserved3; |
| | | } |
| | | |
| | | // è°è¯è¾åº |
| | | // è°è¯è¾åº |
| | | std::string toString() const { |
| | | std::ostringstream oss; |
| | | oss << "Station Value: " << nStationValue << "\n" |
| | |
| | | } |
| | | }; |
| | | |
| | | // äºä»¶è¯¦æ
|
| | | // äºä»¶è¯¦æ
|
| | | struct EventDetails { |
| | | short nEventNo; // åççäºä»¶å· |
| | | std::array<short, 4> details; // åå¨äºä»¶è¯¦æ
ä¿¡æ¯ |
| | | short nEventNo; // åççäºä»¶å· |
| | | std::array<short, 4> details; // åå¨äºä»¶è¯¦æ
ä¿¡æ¯ |
| | | |
| | | // è§£æäºä»¶è¯¦æ
ï¼è¿åæ ¼å¼åå符串 |
| | | // è§£æäºä»¶è¯¦æ
ï¼è¿åæ ¼å¼åå符串 |
| | | std::string toString() const { |
| | | std::ostringstream oss; |
| | | oss << "Details[0]: " << details[0] << ", " |
| | |
| | | } |
| | | }; |
| | | |
| | | // SoftElement ç»æä½å®ä¹ |
| | | // SoftElement ç»æä½å®ä¹ |
| | | struct SoftElement { |
| | | short nType; // 软å
ä»¶ç±»å |
| | | short nElementCount; // ç¹æ° |
| | | long nStartNo; // èµ·å§è½¯å
ä»¶ç¼å· |
| | | short nType; // 软å
ä»¶ç±»å |
| | | short nElementCount; // ç¹æ° |
| | | long nStartNo; // èµ·å§è½¯å
ä»¶ç¼å· |
| | | }; |
| | | |
| | | // éè¯¯ä¿¡æ¯ |
| | | // éè¯¯ä¿¡æ¯ |
| | | struct ErrorInfo { |
| | | int nErrorCode = 0; // é误ç |
| | | std::string strErrorMessageCn; // 䏿æè¿° |
| | | std::string strErrorMessageEn; // è±ææè¿° |
| | | int nErrorCode = 0; // é误ç |
| | | std::string strErrorMessageCn; // 䏿æè¿° |
| | | std::string strErrorMessageEn; // è±ææè¿° |
| | | |
| | | // å°ç»æä½åºåå为å符串 |
| | | // å°ç»æä½åºåå为å符串 |
| | | std::string toString() const { |
| | | std::ostringstream oss; |
| | | oss << nErrorCode << "|" << strErrorMessageCn << "|" << strErrorMessageEn; |
| | | return oss.str(); |
| | | } |
| | | |
| | | // ä»å符串ååºååä¸ºç»æä½ |
| | | // ä»å符串ååºååä¸ºç»æä½ |
| | | static ErrorInfo fromString(const std::string& line) { |
| | | ErrorInfo info; |
| | | std::istringstream iss(line); |
| | | std::string token; |
| | | |
| | | // 使ç¨åé符 "|" è§£æå符串 |
| | | // 使ç¨åé符 "|" è§£æå符串 |
| | | std::getline(iss, token, '|'); |
| | | info.nErrorCode = std::stoi(token); |
| | | |
| | |
| | | } |
| | | }; |
| | | |
| | | using BitContainer = std::vector<bool>; // æ¯ä¸ªå
ç´ åå¨ 1 ä½ |
| | | using WordContainer = std::vector<uint16_t>; // æ¯ä¸ªå
ç´ åå¨ 16 ä½ |
| | | using DWordContainer = std::vector<uint32_t>; // æ¯ä¸ªå
ç´ åå¨ 32 ä½ |
| | | using BitContainer = std::vector<bool>; // æ¯ä¸ªå
ç´ åå¨ 1 ä½ |
| | | using WordContainer = std::vector<uint16_t>; // æ¯ä¸ªå
ç´ åå¨ 16 ä½ |
| | | using DWordContainer = std::vector<uint32_t>; // æ¯ä¸ªå
ç´ åå¨ 32 ä½ |
| | | |
| | | // CPerformanceMelsec 类声æ |
| | | // CPerformanceMelsec 类声æ |
| | | class CPerformanceMelsec { |
| | | public: |
| | | // è·åæè¿çéè¯¯ä¿¡æ¯ |
| | | // è·åæè¿çéè¯¯ä¿¡æ¯ |
| | | std::string GetLastError() const; |
| | | |
| | | // é误信æ¯å è½½ä¸ä¿åæ¥å£ |
| | | static bool LoadErrorInfoFromFile(const std::string& filename); // 仿件å è½½éè¯¯ä¿¡æ¯ |
| | | static bool SaveErrorInfoToFile(const std::string& filename); // ä¿åé误信æ¯å°æä»¶ |
| | | // é误信æ¯å è½½ä¸ä¿åæ¥å£ |
| | | static bool LoadErrorInfoFromFile(const std::string& filename); // 仿件å è½½éè¯¯ä¿¡æ¯ |
| | | static bool SaveErrorInfoToFile(const std::string& filename); // ä¿åé误信æ¯å°æä»¶ |
| | | |
| | | // è¿æ¥/æå¼ |
| | | // è¿æ¥/æå¼ |
| | | int Connect(short nChannel, short nMode = -1); |
| | | int Disconnect(); |
| | | |
| | | // åå§åå¯ç¼ç¨æ§å¶å¨è½¯å
ä»¶ä¿¡æ¯è¡¨ |
| | | // åå§åå¯ç¼ç¨æ§å¶å¨è½¯å
ä»¶ä¿¡æ¯è¡¨ |
| | | int InitializeController(); |
| | | |
| | | // è·åçæ¬ä¿¡æ¯ |
| | | // è·åçæ¬ä¿¡æ¯ |
| | | int GetBoardVersion(BoardVersion& version); |
| | | |
| | | // æ¿å¤ä½ |
| | | // æ¿å¤ä½ |
| | | int BoardReset(); |
| | | |
| | | // æ¿LED读å |
| | | // æ¿LED读å |
| | | int ReadBoardLed(std::vector<short>& vecLedBuffer); |
| | | |
| | | // 读åç®æ ç«ç¹CPUç±»å |
| | | // 读åç®æ ç«ç¹CPUç±»å |
| | | int ReadCPUCode(const StationIdentifier& station, short& nCPUCode); |
| | | |
| | | // æ¿æ¨¡å¼è·å/设置 |
| | | // æ¿æ¨¡å¼è·å/设置 |
| | | int SetBoardMode(short nMode); |
| | | int GetBoardMode(short& nMode); |
| | | |
| | | // è·åæ¿ç¶æ |
| | | // è·åæ¿ç¶æ |
| | | int GetBoardStatus(BoardStatus& status); |
| | | |
| | | // è¯»åæ°æ® |
| | | // è¯»åæ°æ® |
| | | int ReadData(const StationIdentifier& station, long nDevType, long nDevNo, long nSize, std::vector<short>& vecData); |
| | | int ReadBitData(const StationIdentifier& station, DeviceType enDevType, short nDevNo, short nBitCount, BitContainer& vecData); |
| | | int ReadWordData(const StationIdentifier& station, DeviceType enDevType, short nDevNo, short nWordCount, WordContainer& vecData); |
| | |
| | | int WriteWordData(const StationIdentifier& station, DeviceType enDevType, short nDevNo, const WordContainer& vecData); |
| | | int WriteDWordData(const StationIdentifier& station, DeviceType enDevType, short nDevNo, const DWordContainer& vecData); |
| | | |
| | | // æ©å±è¯»åæ°æ® |
| | | // æ©å±è¯»åæ°æ® |
| | | long ReadDataEx(const StationIdentifier& station, long nDevType, long nDevNo, long nSize, std::vector<char>& vecData); |
| | | long ReadBitDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, long nBitCount, BitContainer& vecData); |
| | | long ReadWordDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, long nWordCount, WordContainer& vecData); |
| | |
| | | long WriteWordDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, const WordContainer& vecData); |
| | | long WriteDWordDataEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo, const DWordContainer& vecData); |
| | | |
| | | // æ©å±è½¯å
ä»¶éæºè¯»åï¼æ¯æå¤ä¸ªè½¯å
ä»¶ï¼ |
| | | // æ©å±è½¯å
ä»¶éæºè¯»åï¼æ¯æå¤ä¸ªè½¯å
ä»¶ï¼ |
| | | long ReadRandomDataEx(const StationIdentifier& station, const std::vector<SoftElement>& vecSoftElements, std::vector<char>& vecData); |
| | | long WriteRandomDataEx(const StationIdentifier& station, const std::vector<SoftElement>& vecSoftElements, const std::vector<char>& vecData); |
| | | |
| | | // è¿ç¨è®¾å¤ç«/è¿ç¨ç«çç¼å²åå¨å¨è¯»å |
| | | // è¿ç¨è®¾å¤ç«/è¿ç¨ç«çç¼å²åå¨å¨è¯»å |
| | | long ReadRemoteBuffer(const StationIdentifier& station, long nOffset, long nSize, std::vector<char>& vecData); |
| | | long WriteRemoteBuffer(const StationIdentifier& station, long nOffset, const std::vector<char>& vecData); |
| | | long ReadRemoteBufferByIp(const std::string& strIP, long nOffset, long nSize, std::vector<char>& vecData); |
| | | long WriteRemoteBufferByIp(const std::string& strIP, long nOffset, const std::vector<char>& vecData); |
| | | |
| | | // 设置/å¤ä½å¯¹è±¡ç«çæå®ä½è½¯å
ä»¶ |
| | | // 设置/å¤ä½å¯¹è±¡ç«çæå®ä½è½¯å
ä»¶ |
| | | int SetBitDevice(const StationIdentifier& station, DeviceType enDevType, short nDevNo); |
| | | int ResetBitDevice(const StationIdentifier& station, DeviceType enDevType, short enDevNo); |
| | | |
| | | // æ©å±è®¾ç½®/å¤ä½å¯¹è±¡ç«çæå®ä½è½¯å
ä»¶ |
| | | // æ©å±è®¾ç½®/å¤ä½å¯¹è±¡ç«çæå®ä½è½¯å
ä»¶ |
| | | long SetBitDeviceEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo); |
| | | long ResetBitDeviceEx(const StationIdentifier& station, DeviceType enDevType, long nDevNo); |
| | | |
| | | // æ§è¡å¯¹è±¡ç«çCPU |
| | | // æ§è¡å¯¹è±¡ç«çCPU |
| | | int ControlCPU(const StationIdentifier& station, ControlCode enControlCode); |
| | | |
| | | // äºä»¶çå¾
ï¼vecEventNumbers[0, 64]ï¼nTimeoutMs[-1, 2147483647] |
| | | // åæ¶åçäºå¤ä¸ªäºä»¶çæ
åµä¸ï¼é¦å
æ£æµåºå
¶ä¸ä¸ä¸ªäºä»¶ã 忬¡æ§è¡äºæ¬å½æ°çæ
åµä¸æ£æµåºå
¶å®äºä»¶ã |
| | | // äºä»¶çå¾
ï¼vecEventNumbers[0, 64]ï¼nTimeoutMs[-1, 2147483647] |
| | | // åæ¶åçäºå¤ä¸ªäºä»¶çæ
åµä¸ï¼é¦å
æ£æµåºå
¶ä¸ä¸ä¸ªäºä»¶ã 忬¡æ§è¡äºæ¬å½æ°çæ
åµä¸æ£æµåºå
¶å®äºä»¶ã |
| | | int WaitForBoardEvent(std::vector<short> vecEventNumbers, int nTimeoutMs, EventDetails& details); |
| | | |
| | | private: |
| | | // éå®ä¸è§£éï¼å¤çº¿ç¨åæ¥ä¿æ¤ï¼ |
| | | // éå®ä¸è§£éï¼å¤çº¿ç¨åæ¥ä¿æ¤ï¼ |
| | | void Lock() { m_mtx.lock(); } |
| | | void Unlock() { m_mtx.unlock(); } |
| | | |
| | | protected: |
| | | // æé 彿°/ææå½æ° |
| | | // æé 彿°/ææå½æ° |
| | | explicit CPerformanceMelsec(BoardType enBoardType); |
| | | virtual ~CPerformanceMelsec(); |
| | | |
| | | // è¾
å©å½æ° |
| | | void UpdateLastError(int nCode); // æ´æ°æè¿çéè¯¯ä¿¡æ¯ |
| | | int ValidateStation(const StationIdentifier& station) const; // æ£æ¥è¿æ¥ç¶æåç«ç¹åæ°æææ§ |
| | | // è¾
å©å½æ° |
| | | void UpdateLastError(int nCode); // æ´æ°æè¿çéè¯¯ä¿¡æ¯ |
| | | int ValidateStation(const StationIdentifier& station) const; // æ£æ¥è¿æ¥ç¶æåç«ç¹åæ°æææ§ |
| | | int ValidateStationAndSize(const StationIdentifier& station, short nCount) const; |
| | | |
| | | // éæè¾
å©å½æ° |
| | | static void Delay(unsigned int nDelayMs); // å»¶æ¶ï¼å¹¶ä¸è½¬åçªå£æ¶æ¯ |
| | | static BoardType FindBoardTypeByChannel(int nChannel); // æ¥æ¾æ¿åç±»å |
| | | static short CombineStation(const StationIdentifier& station); // åå¹¶ç½ç»å·åç«ç¹å· |
| | | static short CalculateDeviceType(const StationIdentifier& station, DeviceType enDevType); // 计ç®è½¯å
ä»¶ç±»å |
| | | // éæè¾
å©å½æ° |
| | | static void Delay(unsigned int nDelayMs); // å»¶æ¶ï¼å¹¶ä¸è½¬åçªå£æ¶æ¯ |
| | | static BoardType FindBoardTypeByChannel(int nChannel); // æ¥æ¾æ¿åç±»å |
| | | static short CombineStation(const StationIdentifier& station); // åå¹¶ç½ç»å·åç«ç¹å· |
| | | static short CalculateDeviceType(const StationIdentifier& station, DeviceType enDevType); // 计ç®è½¯å
ä»¶ç±»å |
| | | |
| | | // IPè½¬æ¢ |
| | | // IPè½¬æ¢ |
| | | static bool ConvertIpStringToUint32(const std::string& strIP, uint32_t& nIP); |
| | | |
| | | // 容å¨è½¬æ¢ |
| | | // 容å¨è½¬æ¢ |
| | | static void ConvertCharToShort(const std::vector<char>& vecChar, std::vector<short>& vecShort); |
| | | static void ConvertShortToChar(const std::vector<short>& vecShort, std::vector<char>& vecChar); |
| | | static void ConvertUint8ToShort(const std::vector<uint8_t>& vecUint8, std::vector<short>& vecShort); |
| | |
| | | static void ConvertUint32ToShort(const std::vector<uint32_t>& vecUint32, std::vector<short>& vecShort); |
| | | static void ConvertShortToUint32(const std::vector<short>& vecShort, std::vector<uint32_t>& vecUint32); |
| | | |
| | | // 模æ¿è¾
å©å½æ° |
| | | // 模æ¿è¾
å©å½æ° |
| | | template <typename T> |
| | | int ValidateStationAndData(const StationIdentifier& station, const std::vector<T>& vecData); |
| | | |
| | |
| | | template <typename T, typename U> |
| | | void ConvertHighToLow(const std::vector<T>& vecHigh, std::vector<U>& vecLow); |
| | | |
| | | // æååé |
| | | std::mutex m_mtx; // äºæ¥éä¿æ¤ |
| | | BoardType m_enBoardType; // æ¿åç±»å |
| | | long m_nPath; // éä¿¡è·¯å¾ |
| | | std::atomic<bool> m_bConnected; // æ¯å¦å·²è¿æ¥ |
| | | std::string m_strLastError; // æè¿ä¸æ¬¡éè¯¯ä¿¡æ¯ |
| | | // æååé |
| | | std::mutex m_mtx; // äºæ¥éä¿æ¤ |
| | | BoardType m_enBoardType; // æ¿åç±»å |
| | | long m_nPath; // éä¿¡è·¯å¾ |
| | | std::atomic<bool> m_bConnected; // æ¯å¦å·²è¿æ¥ |
| | | std::string m_strLastError; // æè¿ä¸æ¬¡éè¯¯ä¿¡æ¯ |
| | | |
| | | // éææååé |
| | | static std::unordered_map<int, std::string> m_mapError; // éè¯¯ç æ å°è¡¨ |
| | | // éææååé |
| | | static std::unordered_map<int, std::string> m_mapError; // éè¯¯ç æ å°è¡¨ |
| | | }; |
| | | |
| | | #endif // PERFORMANCE_MELSEC_H |
| | |
| | | |
| | | CLogger& CLogger::Instance() |
| | | { |
| | | static CLogger instance; |
| | | return instance; |
| | | static CLogger instance; |
| | | return instance; |
| | | } |
| | | |
| | | CLogger::CLogger() |
| | |
| | | |
| | | CLogger::~CLogger() |
| | | { |
| | | CloseLogFile(); |
| | | CloseLogFile(); |
| | | } |
| | | |
| | | void CLogger::OpenLogFile() |
| | | { |
| | | CSingleLock lock(&m_csLogLock, TRUE); |
| | | CSingleLock lock(&m_csLogLock, TRUE); |
| | | |
| | | CTime now = CTime::GetCurrentTime(); |
| | | CString strLogDir = _T("Log"); |
| | | CTime now = CTime::GetCurrentTime(); |
| | | CString strLogDir = _T("Log"); |
| | | |
| | | if (!PathFileExists(strLogDir)) { |
| | | CreateDirectory(strLogDir, NULL); |
| | | } |
| | | if (!PathFileExists(strLogDir)) { |
| | | CreateDirectory(strLogDir, NULL); |
| | | } |
| | | |
| | | CString strNewPath; |
| | | strNewPath.Format(_T("%s\\SG_%04d%02d%02d.log"), strLogDir, now.GetYear(), now.GetMonth(), now.GetDay()); |
| | | CString strNewPath; |
| | | strNewPath.Format(_T("%s\\SG_%04d%02d%02d.log"), strLogDir, now.GetYear(), now.GetMonth(), now.GetDay()); |
| | | |
| | | if (m_strCurrentLogPath.CompareNoCase(strNewPath) != 0 || m_logFile.m_pStream == nullptr) { |
| | | if (m_logFile.m_pStream) { |
| | | m_logFile.Flush(); |
| | | m_logFile.Close(); |
| | | } |
| | | if (m_strCurrentLogPath.CompareNoCase(strNewPath) != 0 || m_logFile.m_pStream == nullptr) { |
| | | if (m_logFile.m_pStream) { |
| | | m_logFile.Flush(); |
| | | m_logFile.Close(); |
| | | } |
| | | |
| | | if (m_logFile.Open(strNewPath, |
| | | CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite | CFile::typeBinary)) { |
| | | if (m_logFile.Open(strNewPath, |
| | | CFile::modeCreate | CFile::modeNoTruncate | CFile::modeWrite | CFile::typeBinary)) { |
| | | |
| | | if (m_logFile.GetLength() == 0) { |
| | | WCHAR bom = 0xFEFF; |
| | | m_logFile.Write(&bom, sizeof(WCHAR)); |
| | | } |
| | | if (m_logFile.GetLength() == 0) { |
| | | WCHAR bom = 0xFEFF; |
| | | m_logFile.Write(&bom, sizeof(WCHAR)); |
| | | } |
| | | |
| | | m_logFile.SeekToEnd(); |
| | | m_strCurrentLogPath = strNewPath; |
| | | } |
| | | } |
| | | m_logFile.SeekToEnd(); |
| | | m_strCurrentLogPath = strNewPath; |
| | | } |
| | | } |
| | | } |
| | | |
| | | void CLogger::WriteLine(CString str) |
| | | { |
| | | CSingleLock lock(&m_csLogLock, TRUE); |
| | | CSingleLock lock(&m_csLogLock, TRUE); |
| | | |
| | | OpenLogFile(); |
| | | OpenLogFile(); |
| | | |
| | | if (m_logFile.m_pStream) { |
| | | CTime now = CTime::GetCurrentTime(); |
| | | CString strTime; |
| | | strTime.Format(_T("[%02d:%02d:%02d]"), now.GetHour(), now.GetMinute(), now.GetSecond()); |
| | | if (m_logFile.m_pStream) { |
| | | CTime now = CTime::GetCurrentTime(); |
| | | CString strTime; |
| | | strTime.Format(_T("[%02d:%02d:%02d]"), now.GetHour(), now.GetMinute(), now.GetSecond()); |
| | | |
| | | CString strLine = strTime + str + _T("\r\n"); |
| | | m_logFile.Write((LPCTSTR)strLine, strLine.GetLength() * sizeof(WCHAR)); |
| | | } |
| | | CString strLine = strTime + str + _T("\r\n"); |
| | | m_logFile.Write((LPCTSTR)strLine, strLine.GetLength() * sizeof(WCHAR)); |
| | | } |
| | | } |
| | | |
| | | void CLogger::CloseLogFile() |
| | | { |
| | | CSingleLock lock(&m_csLogLock, TRUE); |
| | | CSingleLock lock(&m_csLogLock, TRUE); |
| | | |
| | | if (m_logFile.m_pStream) { |
| | | m_logFile.Flush(); |
| | | m_logFile.Close(); |
| | | m_strCurrentLogPath.Empty(); |
| | | } |
| | | if (m_logFile.m_pStream) { |
| | | m_logFile.Flush(); |
| | | m_logFile.Close(); |
| | | m_strCurrentLogPath.Empty(); |
| | | } |
| | | } |
| | |
| | | class CLogger |
| | | { |
| | | public: |
| | | static CLogger& Instance(); // è·ååä¾ |
| | | void WriteLine(CString str); // åä¸è¡æ¥å¿ |
| | | void CloseLogFile(); // å
³éæ¥å¿æä»¶ |
| | | static CLogger& Instance(); // è·ååä¾ |
| | | void WriteLine(CString str); // åä¸è¡æ¥å¿ |
| | | void CloseLogFile(); // å
³éæ¥å¿æä»¶ |
| | | |
| | | private: |
| | | CLogger(); |
| | | ~CLogger(); |
| | | void OpenLogFile(); // å
鍿弿件 |
| | | CLogger(); |
| | | ~CLogger(); |
| | | void OpenLogFile(); // å
鍿弿件 |
| | | |
| | | CCriticalSection m_csLogLock; |
| | | CString m_strCurrentLogPath; |
| | | CStdioFile m_logFile; |
| | | CCriticalSection m_csLogLock; |
| | | CString m_strCurrentLogPath; |
| | | CStdioFile m_logFile; |
| | | }; |
| | | |
| | | #define LOG_LINE(x) CLogger::Instance().WriteLine(x) |
| | | |
| | | #define LOG_LINEF(fmt, ...) \ |
| | | do { \ |
| | | CString __log__; \ |
| | | __log__.Format(fmt, __VA_ARGS__); \ |
| | | CLogger::Instance().WriteLine(__log__); \ |
| | | } while (0) |
| | | do { \ |
| | | CString __log__; \ |
| | | __log__.Format(fmt, __VA_ARGS__); \ |
| | | CLogger::Instance().WriteLine(__log__); \ |
| | | } while (0) |
| | |
| | | #include "pch.h" |
| | | #include "PLCSignalListener.h" |
| | | |
| | | // === æ¥å¿æå°ç±»å === |
| | | // === æ¥å¿æå°ç±»å === |
| | | #define LOG_TYPE_ERROR -1 |
| | | #define LOG_TYPE_SUCCESS 0 |
| | | #define LOG_TYPE_WARNING 1 |
| | | #define LOG_TYPE_NORMAL 2 |
| | | |
| | | // === æ¥å¿æå°å®å®ä¹ === |
| | | // === æ¥å¿æå°å®å®ä¹ === |
| | | #define LOG_MSG(msg, type) LogInfo(msg, type) |
| | | |
| | | // === PLC å¿è·³ç¸å
³é
ç½® === |
| | | #define PLC_HEARTBEAT_PC_TO_PLC_ADDR 0x107F // PC -> PLCï¼PC åå
¥å¿è·³ |
| | | #define PLC_HEARTBEAT_PLC_TO_PC_ADDR 0x6C40 // PLC -> PCï¼PC 读å PLC åå
¥çå¿è·³ |
| | | #define MAX_MISSED_HEARTBEAT 5 // å
许è¿ç»ä¸¢å¤±å¿è·³çæå¤§æ¬¡æ°ï¼è¶
è¿åå¤å® PLC æçº¿ |
| | | // === PLC å¿è·³ç¸å
³é
ç½® === |
| | | #define PLC_HEARTBEAT_PC_TO_PLC_ADDR 0x107F // PC -> PLCï¼PC åå
¥å¿è·³ |
| | | #define PLC_HEARTBEAT_PLC_TO_PC_ADDR 0x6C40 // PLC -> PCï¼PC 读å PLC åå
¥çå¿è·³ |
| | | #define MAX_MISSED_HEARTBEAT 5 // å
许è¿ç»ä¸¢å¤±å¿è·³çæå¤§æ¬¡æ°ï¼è¶
è¿åå¤å® PLC æçº¿ |
| | | |
| | | // === PLC å½ä»¤è¾å
¥é
ç½®ï¼PLC -> PCï¼ === |
| | | #define PLC_CMD_BIT_START 0x6CD3 // PLCå½ä»¤èµ·å§ä½ï¼é常为B6CD3ï¼ |
| | | #define PLC_CMD_BIT_COUNT 2 // æ»å
±å 个å½ä»¤ä½ï¼B6CD3=Start, B6CD4=Stopï¼ |
| | | // === PLC å½ä»¤è¾å
¥é
ç½®ï¼PLC -> PCï¼ === |
| | | #define PLC_CMD_BIT_START 0x6CD3 // PLCå½ä»¤èµ·å§ä½ï¼é常为B6CD3ï¼ |
| | | #define PLC_CMD_BIT_COUNT 2 // æ»å
±å 个å½ä»¤ä½ï¼B6CD3=Start, B6CD4=Stopï¼ |
| | | |
| | | // === PLC åºçè¾åºé
ç½®ï¼PC -> PLCï¼ === |
| | | #define PLC_ACK_MAX_LIFE 25 // PLCååºä¿¡å·æå¤§ä¿ç卿æ°ï¼æ¯å¨æä¸º m_nIntervalMs 毫ç§ï¼ |
| | | #define PLC_ACK_BASE_BIT 0x1060 // PLCåºçèµ·å§å°åï¼B1060表示B6CD3çåºçï¼B1061表示B6CD4çåºçï¼ |
| | | // === PLC åºçè¾åºé
ç½®ï¼PC -> PLCï¼ === |
| | | #define PLC_ACK_MAX_LIFE 25 // PLCååºä¿¡å·æå¤§ä¿ç卿æ°ï¼æ¯å¨æä¸º m_nIntervalMs 毫ç§ï¼ |
| | | #define PLC_ACK_BASE_BIT 0x1060 // PLCåºçèµ·å§å°åï¼B1060表示B6CD3çåºçï¼B1061表示B6CD4çåºçï¼ |
| | | |
| | | // === PLC软å
ä»¶ç±»åå®ï¼ç¨äºåºçãæ°æ®åå
¥ï¼=== |
| | | #define PLC_BIT_DEVICE_TYPE DeviceType::B // 使ä½è®¾å¤ç±»åï¼å¦MãBï¼ |
| | | #define PLC_WORD_DEVICE_TYPE DeviceType::W // åæä½è®¾å¤ç±»åï¼å¦DãWï¼ |
| | | // === PLC软å
ä»¶ç±»åå®ï¼ç¨äºåºçãæ°æ®åå
¥ï¼=== |
| | | #define PLC_BIT_DEVICE_TYPE DeviceType::B // 使ä½è®¾å¤ç±»åï¼å¦MãBï¼ |
| | | #define PLC_WORD_DEVICE_TYPE DeviceType::W // åæä½è®¾å¤ç±»åï¼å¦DãWï¼ |
| | | |
| | | // === PLCç»æå¯åå¨å°åé
ç½® === |
| | | #define PLC_RESULT_ADDR_START 0x37B0 // PLCç»æå¯åå¨èµ·å§å°åï¼å¦W37B0ï¼ |
| | | #define PLC_RESULT_ADDR_COUNT 4 // ç»æå¯å卿°éï¼å¦W37B0, W37B2, W37B4, W37B6ï¼ |
| | | // === PLCç»æå¯åå¨å°åé
ç½® === |
| | | #define PLC_RESULT_ADDR_START 0x37B0 // PLCç»æå¯åå¨èµ·å§å°åï¼å¦W37B0ï¼ |
| | | #define PLC_RESULT_ADDR_COUNT 4 // ç»æå¯å卿°éï¼å¦W37B0, W37B2, W37B4, W37B6ï¼ |
| | | |
| | | // === PLC 产åIDé
ç½®ï¼PLC -> PCï¼=== |
| | | #define PLC_PRODUCT_ID_ADDR 0x1B160 // 产åIDèµ·å§å°å (W1B160) |
| | | #define PLC_PRODUCT_ID_WORDS 10 // 产åIDé¿åº¦ï¼10个Wordï¼ |
| | | |
| | | #define IS_RISING_EDGE(prev, curr) (!(prev) && (curr)) |
| | | |
| | | CPLCSignalListener::CPLCSignalListener() = default; |
| | | |
| | | CPLCSignalListener::~CPLCSignalListener() { |
| | | Stop(); |
| | | Stop(); |
| | | } |
| | | |
| | | bool CPLCSignalListener::Initialize(StationIdentifier station, int nIntervalMs/* = 200*/) |
| | | { |
| | | m_pPlc = std::make_unique<CCCLinkIEControl>(); |
| | | if (!m_pPlc) { |
| | | LOG_MSG(_T("PLCæ§å¶å¨åå§åå¤±è´¥ï¼æ æ³å建 CCCLinkIEControl å®ä¾ã"), LOG_TYPE_ERROR); |
| | | return false; |
| | | } |
| | | m_pPlc = std::make_unique<CCCLinkIEControl>(); |
| | | if (!m_pPlc) { |
| | | LOG_MSG(_T("PLCæ§å¶å¨åå§åå¤±è´¥ï¼æ æ³å建 CCCLinkIEControl å®ä¾ã"), LOG_TYPE_ERROR); |
| | | return false; |
| | | } |
| | | |
| | | int ret = m_pPlc->Connect(CC_LINK_IE_CONTROL_CHANNEL(1)); |
| | | if (ret != 0) { |
| | | m_bConnected = false; |
| | | int ret = m_pPlc->Connect(CC_LINK_IE_CONTROL_CHANNEL(1)); |
| | | if (ret != 0) { |
| | | m_bConnected = false; |
| | | |
| | | CString strError; |
| | | strError.Format(_T("PLCæ§å¶å¨è¿æ¥å¤±è´¥ï¼é误ç ï¼%d"), ret); |
| | | LOG_MSG(strError, LOG_TYPE_ERROR); |
| | | CString strError; |
| | | strError.Format(_T("PLCæ§å¶å¨è¿æ¥å¤±è´¥ï¼é误ç ï¼%d"), ret); |
| | | LOG_MSG(strError, LOG_TYPE_ERROR); |
| | | |
| | | return false; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | m_bConnected = true; |
| | | m_station = station; |
| | | m_nIntervalMs = nIntervalMs; |
| | | m_bConnected = true; |
| | | m_station = station; |
| | | m_nIntervalMs = nIntervalMs; |
| | | |
| | | m_vecPrevBits.assign(PLC_CMD_BIT_COUNT, false); |
| | | m_vecPrevBits.assign(PLC_CMD_BIT_COUNT, false); |
| | | |
| | | return true; |
| | | return true; |
| | | } |
| | | |
| | | void CPLCSignalListener::SetStartCallback(Callback cb) |
| | | { |
| | | m_cbStart = std::move(cb); |
| | | m_cbStart = std::move(cb); |
| | | } |
| | | |
| | | void CPLCSignalListener::SetStopCallback(Callback cb) |
| | | { |
| | | m_cbStop = std::move(cb); |
| | | m_cbStop = std::move(cb); |
| | | } |
| | | |
| | | void CPLCSignalListener::SetAnalyzeCallback(AnalyzeCallback cb) |
| | | { |
| | | m_cbAnalyze = std::move(cb); |
| | | m_cbAnalyze = std::move(cb); |
| | | } |
| | | |
| | | void CPLCSignalListener::SetLogCallback(LogCallback cb) |
| | | { |
| | | m_cbLog = std::move(cb); |
| | | m_cbLog = std::move(cb); |
| | | } |
| | | |
| | | bool CPLCSignalListener::Start() |
| | | { |
| | | if (m_bRunning || !m_pPlc) { |
| | | LOG_MSG(_T("PLCä¿¡å·çå¬å¨å·²å¨è¿è¡æPLCæ§å¶å¨æªåå§åã"), LOG_TYPE_ERROR); |
| | | return false; |
| | | } |
| | | if (m_bRunning || !m_pPlc) { |
| | | LOG_MSG(_T("PLCä¿¡å·çå¬å¨å·²å¨è¿è¡æPLCæ§å¶å¨æªåå§åã"), LOG_TYPE_ERROR); |
| | | return false; |
| | | } |
| | | |
| | | m_bRunning = true; |
| | | m_thread = std::thread(&CPLCSignalListener::ThreadProc, this); |
| | | m_bRunning = true; |
| | | m_thread = std::thread(&CPLCSignalListener::ThreadProc, this); |
| | | |
| | | StartHeartbeatMonitor(); |
| | | return true; |
| | | StartHeartbeatMonitor(); |
| | | return true; |
| | | } |
| | | |
| | | void CPLCSignalListener::Stop() |
| | | { |
| | | m_bRunning = false; |
| | | if (m_thread.joinable()) { |
| | | m_thread.join(); |
| | | } |
| | | m_bRunning = false; |
| | | if (m_thread.joinable()) { |
| | | m_thread.join(); |
| | | } |
| | | |
| | | StopHeartbeatMonitor(); |
| | | StopHeartbeatMonitor(); |
| | | } |
| | | |
| | | void CPLCSignalListener::LogInfo(const CString& strText, int nType) |
| | | { |
| | | if (m_cbLog) { |
| | | m_cbLog(strText, nType); |
| | | } |
| | | if (m_cbLog) { |
| | | m_cbLog(strText, nType); |
| | | } |
| | | } |
| | | |
| | | bool CPLCSignalListener::SendHeartbeat() |
| | | { |
| | | if (!m_pPlc || !m_bConnected) { |
| | | return false; |
| | | } |
| | | if (!m_pPlc || !m_bConnected) { |
| | | return false; |
| | | } |
| | | |
| | | static bool bToggle = false; |
| | | bToggle = !bToggle; |
| | | static bool bToggle = false; |
| | | bToggle = !bToggle; |
| | | |
| | | int ret = m_pPlc->WriteBitDataEx(m_station, PLC_BIT_DEVICE_TYPE, PLC_HEARTBEAT_PC_TO_PLC_ADDR, BitContainer{ bToggle }); |
| | | int ret = m_pPlc->WriteBitDataEx(m_station, PLC_BIT_DEVICE_TYPE, PLC_HEARTBEAT_PC_TO_PLC_ADDR, BitContainer{ bToggle }); |
| | | |
| | | return (ret == 0); |
| | | return (ret == 0); |
| | | } |
| | | |
| | | bool CPLCSignalListener::CheckHeartbeat() |
| | | { |
| | | static bool bLastHeartbeat = false; |
| | | static bool bLastHeartbeat = false; |
| | | |
| | | if (!m_pPlc || !m_bConnected) { |
| | | return false; |
| | | } |
| | | if (!m_pPlc || !m_bConnected) { |
| | | return false; |
| | | } |
| | | |
| | | BitContainer vec; |
| | | int ret = m_pPlc->ReadBitDataEx(m_station, PLC_BIT_DEVICE_TYPE, PLC_HEARTBEAT_PLC_TO_PC_ADDR, 1, vec); |
| | | if (ret != 0 || vec.empty()) { |
| | | return false; |
| | | } |
| | | BitContainer vec; |
| | | int ret = m_pPlc->ReadBitDataEx(m_station, PLC_BIT_DEVICE_TYPE, PLC_HEARTBEAT_PLC_TO_PC_ADDR, 1, vec); |
| | | if (ret != 0 || vec.empty()) { |
| | | return false; |
| | | } |
| | | |
| | | bool bCurrent = vec[0]; |
| | | bool bChanged = (bCurrent != bLastHeartbeat); |
| | | bLastHeartbeat = bCurrent; |
| | | bool bCurrent = vec[0]; |
| | | bool bChanged = (bCurrent != bLastHeartbeat); |
| | | bLastHeartbeat = bCurrent; |
| | | |
| | | return bChanged; |
| | | return bChanged; |
| | | } |
| | | |
| | | bool CPLCSignalListener::MonitorHeartbeat() |
| | | { |
| | | if (CheckHeartbeat()) { |
| | | m_nMissedHeartbeatCount = 0; |
| | | if (CheckHeartbeat()) { |
| | | m_nMissedHeartbeatCount = 0; |
| | | |
| | | if (m_bHeartbeatLost) { |
| | | m_bHeartbeatLost = false; |
| | | LOG_MSG(_T("PLCå¿è·³æ¢å¤ï¼"), LOG_TYPE_SUCCESS); |
| | | } |
| | | if (m_bHeartbeatLost) { |
| | | m_bHeartbeatLost = false; |
| | | LOG_MSG(_T("PLCå¿è·³æ¢å¤ï¼"), LOG_TYPE_SUCCESS); |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | else { |
| | | m_nMissedHeartbeatCount++; |
| | | return true; |
| | | } |
| | | else { |
| | | m_nMissedHeartbeatCount++; |
| | | |
| | | if (m_nMissedHeartbeatCount > MAX_MISSED_HEARTBEAT) { |
| | | if (!m_bHeartbeatLost) { |
| | | m_bHeartbeatLost = true; |
| | | if (m_nMissedHeartbeatCount > MAX_MISSED_HEARTBEAT) { |
| | | if (!m_bHeartbeatLost) { |
| | | m_bHeartbeatLost = true; |
| | | m_nMissedHeartbeatCount = 0; |
| | | LOG_MSG(_T("PLCå¿è·³ä¿¡å·ä¸æï¼"), LOG_TYPE_ERROR); |
| | | } |
| | | return false; |
| | | } |
| | | } |
| | | LOG_MSG(_T("PLCå¿è·³ä¿¡å·ä¸æï¼"), LOG_TYPE_ERROR); |
| | | } |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | return true; |
| | | } |
| | | |
| | | void CPLCSignalListener::StartHeartbeatMonitor() |
| | | { |
| | | m_bHeartbeatRunning = true; |
| | | m_heartbeatThread = std::thread([this]() { |
| | | while (m_bHeartbeatRunning) { |
| | | SendHeartbeat(); |
| | | MonitorHeartbeat(); |
| | | std::this_thread::sleep_for(std::chrono::milliseconds(m_nIntervalMs * 5)); |
| | | } |
| | | }); |
| | | m_bHeartbeatRunning = true; |
| | | m_heartbeatThread = std::thread([this]() { |
| | | while (m_bHeartbeatRunning) { |
| | | SendHeartbeat(); |
| | | MonitorHeartbeat(); |
| | | std::this_thread::sleep_for(std::chrono::milliseconds(m_nIntervalMs * 5)); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | void CPLCSignalListener::StopHeartbeatMonitor() |
| | | { |
| | | m_bHeartbeatRunning = false; |
| | | if (m_heartbeatThread.joinable()) { |
| | | m_heartbeatThread.join(); |
| | | } |
| | | m_bHeartbeatRunning = false; |
| | | if (m_heartbeatThread.joinable()) { |
| | | m_heartbeatThread.join(); |
| | | } |
| | | } |
| | | |
| | | void CPLCSignalListener::PulseBitDevice(DeviceType eDevType, long nBitNo, int nDelayMs/* = 50*/) |
| | | { |
| | | m_pPlc->SetBitDeviceEx(m_station, eDevType, nBitNo); |
| | | ::Sleep(nDelayMs); |
| | | m_pPlc->ResetBitDeviceEx(m_station, eDevType, nBitNo); |
| | | m_pPlc->SetBitDeviceEx(m_station, eDevType, nBitNo); |
| | | ::Sleep(nDelayMs); |
| | | m_pPlc->ResetBitDeviceEx(m_station, eDevType, nBitNo); |
| | | } |
| | | |
| | | void CPLCSignalListener::HandleAckLife(int i, bool bCurrTriggerBit) |
| | | { |
| | | if (m_vecAckSent[i] && !bCurrTriggerBit) { |
| | | m_pPlc->ResetBitDeviceEx(m_station, PLC_BIT_DEVICE_TYPE, long(PLC_ACK_BASE_BIT + i)); |
| | | m_vecAckSent[i] = false; |
| | | } |
| | | if (m_vecAckSent[i] && !bCurrTriggerBit) { |
| | | m_pPlc->ResetBitDeviceEx(m_station, PLC_BIT_DEVICE_TYPE, long(PLC_ACK_BASE_BIT + i)); |
| | | m_vecAckSent[i] = false; |
| | | } |
| | | |
| | | if (m_vecAckSent[i]) { |
| | | if (++m_vecAckCounter[i] > PLC_ACK_MAX_LIFE) { |
| | | m_pPlc->ResetBitDeviceEx(m_station, PLC_BIT_DEVICE_TYPE, long(PLC_ACK_BASE_BIT + i)); |
| | | m_vecAckSent[i] = false; |
| | | } |
| | | } |
| | | if (m_vecAckSent[i]) { |
| | | if (++m_vecAckCounter[i] > PLC_ACK_MAX_LIFE) { |
| | | m_pPlc->ResetBitDeviceEx(m_station, PLC_BIT_DEVICE_TYPE, long(PLC_ACK_BASE_BIT + i)); |
| | | m_vecAckSent[i] = false; |
| | | } |
| | | } |
| | | } |
| | | |
| | | void CPLCSignalListener::ThreadProc() |
| | | { |
| | | while (m_bRunning && m_bConnected) { |
| | | BitContainer vecBits; |
| | | int ret = m_pPlc->ReadBitDataEx(m_station, PLC_BIT_DEVICE_TYPE, PLC_CMD_BIT_START, PLC_CMD_BIT_COUNT, vecBits); |
| | | if (ret != 0 && vecBits.size() != PLC_CMD_BIT_COUNT) { |
| | | ::Sleep(m_nIntervalMs); |
| | | while (m_bRunning && m_bConnected) { |
| | | BitContainer vecBits; |
| | | int ret = m_pPlc->ReadBitDataEx(m_station, PLC_BIT_DEVICE_TYPE, PLC_CMD_BIT_START, PLC_CMD_BIT_COUNT, vecBits); |
| | | if (ret != 0 && vecBits.size() != PLC_CMD_BIT_COUNT) { |
| | | ::Sleep(m_nIntervalMs); |
| | | |
| | | CString strError; |
| | | strError.Format(_T("PLC读å使°æ®å¤±è´¥ï¼é误ç ï¼%d"), ret); |
| | | LOG_MSG(strError, LOG_TYPE_ERROR); |
| | | CString strError; |
| | | strError.Format(_T("PLC读å使°æ®å¤±è´¥ï¼é误ç ï¼%d"), ret); |
| | | LOG_MSG(strError, LOG_TYPE_ERROR); |
| | | |
| | | continue; |
| | | } |
| | | continue; |
| | | } |
| | | |
| | | for (int i = 0; i < PLC_CMD_BIT_COUNT; ++i) { |
| | | if (IS_RISING_EDGE(m_vecPrevBits[i], vecBits[i])) { |
| | | // ä¸å沿触å |
| | | switch (i) { |
| | | case 0: |
| | | if (m_cbStart) { |
| | | m_cbStart(); |
| | | WriteOutValues(OutValuesArray{ 0.0, 0.0, 0.0, 0.0 }); |
| | | if (m_pPlc->SetBitDeviceEx(m_station, PLC_BIT_DEVICE_TYPE, PLC_ACK_BASE_BIT + i) == 0) { |
| | | m_vecAckSent[i] = true; |
| | | m_vecAckCounter[i] = 0; |
| | | } |
| | | } |
| | | break; |
| | | for (int i = 0; i < PLC_CMD_BIT_COUNT; ++i) { |
| | | if (IS_RISING_EDGE(m_vecPrevBits[i], vecBits[i])) { |
| | | // ä¸å沿触å |
| | | switch (i) { |
| | | case 0: |
| | | if (m_cbStart) { |
| | | m_cbStart(); |
| | | WriteOutValues(OutValuesArray{ 0.0, 0.0, 0.0, 0.0 }); |
| | | if (m_pPlc->SetBitDeviceEx(m_station, PLC_BIT_DEVICE_TYPE, PLC_ACK_BASE_BIT + i) == 0) { |
| | | m_vecAckSent[i] = true; |
| | | m_vecAckCounter[i] = 0; |
| | | } |
| | | |
| | | case 1: |
| | | if (m_cbStop) { |
| | | m_cbStop(); |
| | | if (m_pPlc->SetBitDeviceEx(m_station, PLC_BIT_DEVICE_TYPE, PLC_ACK_BASE_BIT + i) == 0) { |
| | | m_vecAckSent[i] = true; |
| | | m_vecAckCounter[i] = 0; |
| | | } |
| | | } |
| | | std::string strProductID; |
| | | if (ReadProductID(strProductID)) { |
| | | CString msg; |
| | | msg.Format(_T("读åå°äº§åIDï¼%s"), strProductID); |
| | | LOG_MSG(msg, LOG_TYPE_SUCCESS); |
| | | } |
| | | } |
| | | break; |
| | | |
| | | if (m_cbAnalyze) { |
| | | auto results = m_cbAnalyze(); |
| | | WriteOutValues(results); |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | case 1: |
| | | if (m_cbStop) { |
| | | m_cbStop(); |
| | | if (m_pPlc->SetBitDeviceEx(m_station, PLC_BIT_DEVICE_TYPE, PLC_ACK_BASE_BIT + i) == 0) { |
| | | m_vecAckSent[i] = true; |
| | | m_vecAckCounter[i] = 0; |
| | | } |
| | | } |
| | | |
| | | HandleAckLife(i, vecBits[i]); |
| | | m_vecPrevBits[i] = vecBits[i]; |
| | | } |
| | | if (m_cbAnalyze) { |
| | | auto results = m_cbAnalyze(); |
| | | WriteOutValues(results); |
| | | } |
| | | break; |
| | | } |
| | | } |
| | | |
| | | ::Sleep(m_nIntervalMs); |
| | | } |
| | | HandleAckLife(i, vecBits[i]); |
| | | m_vecPrevBits[i] = vecBits[i]; |
| | | } |
| | | |
| | | ::Sleep(m_nIntervalMs); |
| | | } |
| | | } |
| | | |
| | | bool CPLCSignalListener::WriteOutValues(const OutValuesArray& values) |
| | | { |
| | | if (!m_pPlc || !m_bConnected) { |
| | | LOG_MSG(_T("PLCæªè¿æ¥ææªåå§åï¼æ æ³åå
¥è¾åºå¼ã"), LOG_TYPE_ERROR); |
| | | return false; |
| | | } |
| | | if (!m_pPlc || !m_bConnected) { |
| | | LOG_MSG(_T("PLCæªè¿æ¥ææªåå§åï¼æ æ³åå
¥è¾åºå¼ã"), LOG_TYPE_ERROR); |
| | | return false; |
| | | } |
| | | |
| | | if (PLC_RESULT_ADDR_COUNT != 4) { |
| | | LOG_MSG(_T("PLCç»æå¯å卿°éé
ç½®é误ï¼å¿
须为4个ã"), LOG_TYPE_ERROR); |
| | | return false; |
| | | } |
| | | if (PLC_RESULT_ADDR_COUNT != 4) { |
| | | LOG_MSG(_T("PLCç»æå¯å卿°éé
ç½®é误ï¼å¿
须为4个ã"), LOG_TYPE_ERROR); |
| | | return false; |
| | | } |
| | | |
| | | for (int i = 0; i < PLC_RESULT_ADDR_COUNT; ++i) { |
| | | // æ¾å¤§100åå¹¶åèäºå
¥ï¼è½¬ä¸ºPLCæ´æ° |
| | | uint16_t nScaled = static_cast<uint16_t>(std::round(values[i] * 100.0)); |
| | | WordContainer vec = { nScaled }; |
| | | for (int i = 0; i < PLC_RESULT_ADDR_COUNT; ++i) { |
| | | // æ¾å¤§1000åå¹¶åèäºå
¥ï¼è½¬ä¸ºPLCæ´æ° |
| | | int32_t nScaled = static_cast<int32_t>(std::round(values[i] * 1000.0)); |
| | | DWordContainer vec = { static_cast<uint32_t>(nScaled) }; |
| | | |
| | | short nTargetAddr = PLC_RESULT_ADDR_START + i * 2; |
| | | int ret = m_pPlc->WriteWordDataEx(m_station, PLC_WORD_DEVICE_TYPE, nTargetAddr, vec); |
| | | if (ret != 0) { |
| | | CString msg; |
| | | msg.Format(_T("åå
¥OUT%då°å°å%d失败ï¼å¼=%.2f"), i + 1, nTargetAddr, values[i]); |
| | | LOG_MSG(msg, LOG_TYPE_ERROR); |
| | | return false; |
| | | } |
| | | } |
| | | short nTargetAddr = PLC_RESULT_ADDR_START + i * 2; |
| | | int ret = m_pPlc->WriteDWordDataEx(m_station, PLC_WORD_DEVICE_TYPE, nTargetAddr, vec); |
| | | if (ret != 0) { |
| | | CString msg; |
| | | msg.Format(_T("åå
¥OUT%då°å°å%d失败ï¼å¼=%.2f"), i + 1, nTargetAddr, values[i]); |
| | | LOG_MSG(msg, LOG_TYPE_ERROR); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | return true; |
| | | } |
| | | |
| | | bool CPLCSignalListener::ReadProductID(std::string& strProductID) |
| | | { |
| | | if (!m_pPlc || !m_bConnected) { |
| | | LOG_MSG(_T("PLCæªè¿æ¥ææªåå§åï¼æ æ³è¯»å产åIDã"), LOG_TYPE_ERROR); |
| | | return false; |
| | | } |
| | | |
| | | WordContainer vec; |
| | | int ret = m_pPlc->ReadWordDataEx(m_station, PLC_WORD_DEVICE_TYPE, PLC_PRODUCT_ID_ADDR, PLC_PRODUCT_ID_WORDS, vec); |
| | | if (ret != 0 || vec.size() != PLC_PRODUCT_ID_WORDS) { |
| | | CString msg; |
| | | msg.Format(_T("读å产åID失败ï¼é误ç =%d"), ret); |
| | | LOG_MSG(msg, LOG_TYPE_ERROR); |
| | | return false; |
| | | } |
| | | |
| | | strProductID.clear(); |
| | | strProductID.reserve(PLC_PRODUCT_ID_WORDS * 2); |
| | | for (auto w : vec) { |
| | | char c1 = static_cast<char>(w & 0xFF); // ä½åè |
| | | char c2 = static_cast<char>((w >> 8) & 0xFF); // é«åè |
| | | |
| | | if (c1 == '\0') { |
| | | break; |
| | | } |
| | | strProductID.push_back(c1); |
| | | |
| | | if (c2 == '\0') { |
| | | break; |
| | | } |
| | | strProductID.push_back(c2); |
| | | } |
| | | |
| | | return true; |
| | | } |
| | |
| | | class CPLCSignalListener |
| | | { |
| | | public: |
| | | CPLCSignalListener(); |
| | | ~CPLCSignalListener(); |
| | | CPLCSignalListener(); |
| | | ~CPLCSignalListener(); |
| | | |
| | | /** |
| | | * @brief åå§å PLC ä¿¡å·çå¬å¨ã |
| | | * |
| | | * @param station ç®æ PLC çç«å·æ è¯ç¬¦ã |
| | | * @param nIntervalMs è½®è¯¢å¨æï¼åä½ï¼æ¯«ç§ï¼ï¼é»è®¤ 200msã |
| | | * @return true åå§åæåã |
| | | * @return false åå§å失败ã |
| | | */ |
| | | bool Initialize(StationIdentifier station, int nIntervalMs = 200); |
| | | /** |
| | | * @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 ç Start ä¿¡å·ï¼ã |
| | | * |
| | | * @param cb ç¨æ·èªå®ä¹çå¼å§åè°å½æ°ã |
| | | */ |
| | | void SetStartCallback(Callback cb); |
| | | |
| | | /** |
| | | * @brief è®¾ç½®åæ¢å½ä»¤çåè°å½æ°ï¼å¯¹åº PLC ç Stop ä¿¡å·ï¼ã |
| | | * |
| | | * @param cb ç¨æ·èªå®ä¹ç忢åè°å½æ°ã |
| | | */ |
| | | void SetStopCallback(Callback cb); |
| | | /** |
| | | * @brief è®¾ç½®åæ¢å½ä»¤çåè°å½æ°ï¼å¯¹åº PLC ç Stop ä¿¡å·ï¼ã |
| | | * |
| | | * @param cb ç¨æ·èªå®ä¹ç忢åè°å½æ°ã |
| | | */ |
| | | void SetStopCallback(Callback cb); |
| | | |
| | | /** |
| | | * @brief 设置åæè®¡ç®åè°å½æ°ï¼å¨æ¥æ¶å°åæ¢å½ä»¤åè°ç¨ã |
| | | * |
| | | * @param cb è¿å计ç®ç»ææ°ç»ï¼OUT1~OUT4ï¼ç彿°ã |
| | | */ |
| | | void SetAnalyzeCallback(AnalyzeCallback cb); |
| | | /** |
| | | * @brief 设置åæè®¡ç®åè°å½æ°ï¼å¨æ¥æ¶å°åæ¢å½ä»¤åè°ç¨ã |
| | | * |
| | | * @param cb è¿å计ç®ç»ææ°ç»ï¼OUT1~OUT4ï¼ç彿°ã |
| | | */ |
| | | void SetAnalyzeCallback(AnalyzeCallback cb); |
| | | |
| | | /** |
| | | * @brief 设置æ¥å¿è¾åºåè°å½æ°ã |
| | | * |
| | | * @param cb ç¨æ·æä¾çæ¥å¿è¾åºæ¥å£ï¼å
嫿¥å¿å
容忥å¿ç±»åï¼ã |
| | | */ |
| | | void SetLogCallback(LogCallback cb); |
| | | /** |
| | | * @brief 设置æ¥å¿è¾åºåè°å½æ°ã |
| | | * |
| | | * @param cb ç¨æ·æä¾çæ¥å¿è¾åºæ¥å£ï¼å
嫿¥å¿å
容忥å¿ç±»åï¼ã |
| | | */ |
| | | void SetLogCallback(LogCallback cb); |
| | | |
| | | /** |
| | | * @brief å¯å¨ä¿¡å·çå¬çº¿ç¨ã |
| | | * |
| | | * @return true å¯å¨æåã |
| | | * @return false å¯å¨å¤±è´¥ï¼å¯è½å·²è¿è¡ææªåå§åï¼ã |
| | | */ |
| | | bool Start(); |
| | | /** |
| | | * @brief å¯å¨ä¿¡å·çå¬çº¿ç¨ã |
| | | * |
| | | * @return true å¯å¨æåã |
| | | * @return false å¯å¨å¤±è´¥ï¼å¯è½å·²è¿è¡ææªåå§åï¼ã |
| | | */ |
| | | bool Start(); |
| | | |
| | | /** |
| | | * @brief åæ¢ä¿¡å·çå¬çº¿ç¨ã |
| | | */ |
| | | void Stop(); |
| | | /** |
| | | * @brief åæ¢ä¿¡å·çå¬çº¿ç¨ã |
| | | */ |
| | | void Stop(); |
| | | |
| | | /** |
| | | * @brief å PLC åå
¥åæç»æå¼ï¼é常为 OUT1 ~ OUT4ï¼ã |
| | | * |
| | | * @param values å
å«å个 double ç±»åçç»æå¼ï¼å°è½¬æ¢ä¸ºæ´æ°ååå
¥ PLCã |
| | | * @return true åå
¥æåã |
| | | * @return false åå
¥å¤±è´¥ã |
| | | */ |
| | | bool WriteOutValues(const OutValuesArray& values); |
| | | /** |
| | | * @brief å PLC åå
¥åæç»æå¼ï¼é常为 OUT1 ~ OUT4ï¼ã |
| | | * |
| | | * @param values å
å«å个 double ç±»åçç»æå¼ï¼å°è½¬æ¢ä¸ºæ´æ°ååå
¥ PLCã |
| | | * @return true åå
¥æåã |
| | | * @return false åå
¥å¤±è´¥ã |
| | | */ |
| | | bool WriteOutValues(const OutValuesArray& values); |
| | | |
| | | /** |
| | | * @brief 读å PLC å
é¨ç产å IDï¼å符串形å¼ï¼ã |
| | | * |
| | | * @param strProductID è¾åºåæ°ï¼åå¨è¯»åå°ç产å IDã |
| | | * @return true 读åæåã |
| | | * @return false 读å失败ã |
| | | */ |
| | | bool ReadProductID(std::string& strProductID); |
| | | |
| | | private: |
| | | /** |
| | | * @brief è¾åºæ¥å¿ä¿¡æ¯ï¼å°è£
æ¥å¿åè°ï¼ã |
| | | * |
| | | * @param strText æ¥å¿å
å®¹ææ¬ã |
| | | * @param nType æ¥å¿ç±»åï¼LOG_TYPE_NORMAL / ERROR / WARNING çï¼ã |
| | | */ |
| | | void LogInfo(const CString& strText, int nType); |
| | | /** |
| | | * @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 åå
¥æåã |
| | | * @return false åå
¥å¤±è´¥ï¼å¦æªè¿æ¥ï¼ã |
| | | */ |
| | | bool SendHeartbeat(); |
| | | |
| | | /** |
| | | * @brief æ£æ¥ä» PLC 读åå°çå¿è·³ä¿¡å·æ¯å¦åçååã |
| | | * |
| | | * @return true å¿è·³æååï¼PLC æ£å¸¸å¨çº¿ï¼ã |
| | | * @return false å¿è·³æ ååï¼å¯è½ç¦»çº¿ï¼ã |
| | | */ |
| | | bool CheckHeartbeat(); |
| | | /** |
| | | * @brief æ£æ¥ä» PLC 读åå°çå¿è·³ä¿¡å·æ¯å¦åçååã |
| | | * |
| | | * @return true å¿è·³æååï¼PLC æ£å¸¸å¨çº¿ï¼ã |
| | | * @return false å¿è·³æ ååï¼å¯è½ç¦»çº¿ï¼ã |
| | | */ |
| | | bool CheckHeartbeat(); |
| | | |
| | | /** |
| | | * @brief çæ§ PLC å¿è·³æ¯å¦ä¸æï¼å¹¶èªå¨è®°å½ç¶æã |
| | | * |
| | | * @return true PLC å¨çº¿æå¨å
è®¸çæªååºæ¬¡æ°å
ã |
| | | * @return false PLC å¿è·³ä¸æï¼è¶
è¿å
许éå¼ã |
| | | */ |
| | | bool MonitorHeartbeat(); |
| | | /** |
| | | * @brief çæ§ PLC å¿è·³æ¯å¦ä¸æï¼å¹¶èªå¨è®°å½ç¶æã |
| | | * |
| | | * @return true PLC å¨çº¿æå¨å
è®¸çæªååºæ¬¡æ°å
ã |
| | | * @return false PLC å¿è·³ä¸æï¼è¶
è¿å
许éå¼ã |
| | | */ |
| | | bool MonitorHeartbeat(); |
| | | |
| | | /** |
| | | * @brief å¯å¨å¿è·³çæ§çº¿ç¨ï¼ç¬ç«äºä¿¡å·çå¬çº¿ç¨ï¼ã |
| | | */ |
| | | void StartHeartbeatMonitor(); |
| | | /** |
| | | * @brief å¯å¨å¿è·³çæ§çº¿ç¨ï¼ç¬ç«äºä¿¡å·çå¬çº¿ç¨ï¼ã |
| | | */ |
| | | void StartHeartbeatMonitor(); |
| | | |
| | | /** |
| | | * @brief 忢å¿è·³çæ§çº¿ç¨ã |
| | | */ |
| | | void StopHeartbeatMonitor(); |
| | | /** |
| | | * @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 åæå®è½¯å
ä»¶ä½åå
¥ä¸ä¸ªèå²ï¼å
å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 管ç ACK ååºççå½å¨æï¼è¶
æ¶èªå¨æ¸
é¤ã |
| | | * |
| | | * @param i æ§å¶ä½ç´¢å¼ï¼0=Startï¼1=Stopï¼ã |
| | | * @param bCurrTriggerBit å½åä» PLC 读åå°ç触åä½ç¶æã |
| | | */ |
| | | void HandleAckLife(int i, bool bCurrTriggerBit); |
| | | |
| | | /** |
| | | * @brief 主çå¬çº¿ç¨é»è¾ï¼å¾ªç¯è¯»å PLC æ§å¶ä¿¡å·å¹¶å¤ç触åã |
| | | */ |
| | | void ThreadProc(); |
| | | /** |
| | | * @brief 主çå¬çº¿ç¨é»è¾ï¼å¾ªç¯è¯»å PLC æ§å¶ä¿¡å·å¹¶å¤ç触åã |
| | | */ |
| | | void ThreadProc(); |
| | | |
| | | private: |
| | | // === PLC éä¿¡æ ¸å¿å¯¹è±¡ === |
| | | std::unique_ptr<CCCLinkIEControl> m_pPlc; // PLC éä¿¡æ§å¶å¨ |
| | | StationIdentifier m_station; // PLC ç«å· |
| | | std::atomic<bool> m_bConnected{ false }; // æ¯å¦æåè¿æ¥ |
| | | // === PLC éä¿¡æ ¸å¿å¯¹è±¡ === |
| | | std::unique_ptr<CCCLinkIEControl> m_pPlc; // PLC éä¿¡æ§å¶å¨ |
| | | StationIdentifier m_station; // PLC ç«å· |
| | | std::atomic<bool> m_bConnected{ false }; // æ¯å¦æåè¿æ¥ |
| | | |
| | | // === æ§å¶åæ° === |
| | | int m_nIntervalMs = 200; // è½®è¯¢å¨æï¼msï¼ |
| | | // === æ§å¶åæ° === |
| | | int m_nIntervalMs = 200; // è½®è¯¢å¨æï¼msï¼ |
| | | |
| | | // === å½ä»¤è§¦åç¶æç¼å === |
| | | std::vector<bool> m_vecPrevBits; // ä¸ä¸å¨æçå½ä»¤ä½ç¶æï¼ç¨äºæ£æµä¸åæ²¿ï¼ |
| | | // === å½ä»¤è§¦åç¶æç¼å === |
| | | std::vector<bool> m_vecPrevBits; // ä¸ä¸å¨æçå½ä»¤ä½ç¶æï¼ç¨äºæ£æµä¸åæ²¿ï¼ |
| | | |
| | | // === åè°å½æ°ï¼æ§å¶/计ç®/æ¥å¿ï¼=== |
| | | Callback m_cbStart; // Start å½ä»¤åè° |
| | | Callback m_cbStop; // Stop å½ä»¤åè° |
| | | AnalyzeCallback m_cbAnalyze; // Analyze 计ç®åè°ï¼è¿å OUT1~OUT4ï¼ |
| | | LogCallback m_cbLog; // æ¥å¿è¾åºåè° |
| | | // === åè°å½æ°ï¼æ§å¶/计ç®/æ¥å¿ï¼=== |
| | | 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; // 主çå¬çº¿ç¨å¯¹è±¡ |
| | | // === ä¸»çº¿ç¨æ§å¶ === |
| | | 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 }; // 对åºåºçä¿¡å·ççå½å¨æè®¡æ°å¨ |
| | | // === 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 æçº¿ï¼ |
| | | // === å¿è·³æ£æµç¸å
³ === |
| | | std::thread m_heartbeatThread; // å¿è·³æ£æµçº¿ç¨å¯¹è±¡ |
| | | std::atomic<bool> m_bHeartbeatRunning = false; // å¿è·³çº¿ç¨è¿è¡æ å¿ |
| | | std::atomic<bool> m_bHeartbeatLost = false; // å¿è·³ä¸¢å¤±æ å¿ |
| | | int m_nMissedHeartbeatCount = 0; // å¿è·³æªå忬¡æ°ï¼ç¨äºæ£æµ PLC æçº¿ï¼ |
| | | }; |
| | | |
| | |
| | |  |
| | | |
| | | // SGMeasurement.cpp: å®ä¹åºç¨ç¨åºçç±»è¡ä¸ºã |
| | | // |
| | | |
| | |
| | |  |
| | | |
| | | // SGMeasurement.h: PROJECT_NAME åºç¨ç¨åºç主头æä»¶ |
| | | // |
| | | |
| | |
| | | <PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| | | <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile> |
| | | <AdditionalIncludeDirectories>.;..;.\DLL\64bit;.\CCLinkPerformance;..\MELSECSDK\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| | | <Optimization>MaxSpeed</Optimization> |
| | | <Optimization>Disabled</Optimization> |
| | | </ClCompile> |
| | | <Link> |
| | | <SubSystem>Windows</SubSystem> |
| | |
| | | <RESOURCE_FILE>SGMeasurement.rc</RESOURCE_FILE> |
| | | </PropertyGroup> |
| | | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> |
| | | <DebuggerFlavor>WindowsRemoteDebugger</DebuggerFlavor> |
| | | <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor> |
| | | </PropertyGroup> |
| | | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> |
| | | <RemoteDebuggerCommand>\\DESKTOP-IODBVIQ\SGMeasurement\$(ProjectName).exe</RemoteDebuggerCommand> |
| | |
| | |  |
| | | |
| | | // SGMeasurementDlg.cpp: å®ç°æä»¶ |
| | | // |
| | | |
| | |
| | | strFullLogLine.Format(_T("%s %s"), strLevel, strContent); |
| | | |
| | | // åå
¥æ¥å¿æä»¶ |
| | | // LOG_LINE(strFullLogLine); |
| | | LOG_LINE(strFullLogLine); |
| | | } |
| | | |
| | | void CSGMeasurementDlg::HighlightAllMatches(const CString& strSearch, COLORREF clrHighlight/* = RGB(255, 165, 0)*/) |
| | |
| | | |
| | | fAvg1 = CalcAverage(vecGlass1); |
| | | fAvg2 = CalcAverage(vecGlass2); |
| | | fOffset = std::fabs(fAvg2 - fAvg1); // 第äºç - 第ä¸ç |
| | | fOffset = fAvg2 - fAvg1; // 第äºç - 第ä¸ç |
| | | //fOffset = std::fabs(fAvg2 - fAvg1); // 第äºç - 第ä¸ç |
| | | |
| | | CString strLog; |
| | | strLog.Format(_T("第ä¸çç»çå¹³åå¼: %.3fï¼ç¬¬äºçç»çå¹³åå¼: %.3fï¼åç§»é: %.3f"), fAvg1, fAvg2, fOffset); |
| | |
| | | if (m_nUseTrigger) { |
| | | UpdateControlStatus(m_bConnected, m_bSaving); |
| | | AfxMessageBox(_T("å½åæ¯ç¡¬è§¦å模å¼ï¼è¯·æ£æ¥è§¦åå¨ç¶æã"), MB_ICONINFORMATION); |
| | | return -1.0f; |
| | | return 0xFF; |
| | | } |
| | | |
| | | if (!m_bConnected) { |
| | | AppendLogLineRichStyled(_T("è®¾å¤æªè¿æ¥ï¼è¯·å
è¿æ¥è®¾å¤ã"), LOG_COLOR_WARNING); |
| | | return -1.0f; |
| | | return 0xFF; |
| | | } |
| | | |
| | | if (m_bSaving) { |
| | | AppendLogLineRichStyled(_T("æ°æ®å卿£å¨è¿è¡ä¸ï¼è¯·å
忢åå¨ã"), LOG_COLOR_WARNING); |
| | | return -1.0f; |
| | | return 0xFF; |
| | | } |
| | | |
| | | if (nOutNo < 1 || nOutNo > 4) { |
| | | AppendLogLineRichStyled(_T("è¾åºç«¯å£ç¼å·æ æï¼å¿
é¡»å¨ 1 å° 4 ä¹é´ã"), LOG_COLOR_ERROR); |
| | | return -1.0f; |
| | | return 0xFF; |
| | | } |
| | | |
| | | if (m_nSavePointCount < 0) { |
| | | AppendLogLineRichStyled(_T("æ°æ®ç¹æ°å¿
é¡»å¤§äº 0ã"), LOG_COLOR_ERROR); |
| | | return -1.0f; |
| | | return 0xFF; |
| | | } |
| | | |
| | | std::vector<float> vecBuffer(m_nSavePointCount, 0.0f); |
| | |
| | | CString strError; |
| | | strError.Format(_T("读å OUT%d æ°æ®å¤±è´¥ï¼é误ç ï¼%#X"), nOutNo, nRet); |
| | | AppendLogLineRichStyled(strError, LOG_COLOR_ERROR); |
| | | return -1.0f; |
| | | return 0xFF; |
| | | } |
| | | |
| | | vecBuffer.resize(nReceived); |
| | |
| | | std::vector<float> vecGlass1, vecGlass2; |
| | | if (!SplitGlassSegments(nOutNo, vecBuffer, vecGlass1, vecGlass2, m_fJumpThreshold, m_nJumpWindow, m_nValleyMargin, m_nMinGlass1Count)) { |
| | | AppendLogLineRichStyled(_T("æªè½è¯å«åºä¸¤çç»ççæ°æ®ã"), LOG_COLOR_WARNING); |
| | | return -1.0f; |
| | | return 0xFF; |
| | | } |
| | | |
| | | std::vector<float> vecGlass1Filtered, vecGlass2Filtered; |
| | |
| | | m_plcListener.SetAnalyzeCallback([this]() { |
| | | if (!m_bConnected) { |
| | | AppendLogLineRichStyled(_T("è®¾å¤æªè¿æ¥ï¼è¯·å
è¿æ¥è®¾å¤ã"), LOG_COLOR_WARNING); |
| | | return std::array<double, 4>{ -1.0, -1.0, -1.0, -1.0 }; |
| | | return std::array<double, 4>{ 0xFF, 0xFF, 0xFF, 0xFF }; |
| | | } |
| | | |
| | | std::array<double, 4> result; |
| | | for (int i = 0; i < 4; ++i) { |
| | | result[i] = AnalyzeStoredData(i + 1); // OUT1 ~ OUT4 |
| | | } |
| | | |
| | | if (std::any_of(result.begin(), result.end(), [](double v) { return v < 0; })) { |
| | | AppendLogLineRichStyled(_T("åæå¤±è´¥ï¼æäºè¾åºç«¯å£æ°æ®æ æã"), LOG_COLOR_ERROR); |
| | | return std::array<double, 4>{ -1.0, -1.0, -1.0, -1.0 }; |
| | | } |
| | | |
| | | CString strLog; |
| | |
| | | RC nRet = SGIF_GetCalcDataALL(DeviceID, value); |
| | | if (nRet == RC_OK) { |
| | | for (int i = 0; i < 4; ++i) { |
| | | m_dOutValues[i] = value[i].Value; |
| | | } |
| | | double dNew = value[i].Value; |
| | | if (fabs(m_dOutValues[i] - dNew) > 1e-6) { |
| | | m_dOutValues[i] = dNew; |
| | | |
| | | // æ´æ°ç»å®æ§ä»¶ |
| | | UpdateData(FALSE); |
| | | CString str; |
| | | str.Format(_T("%.3f"), dNew); |
| | | |
| | | switch (i) { |
| | | case 0: GetDlgItem(IDC_EDIT_OUT1)->SetWindowText(str); break; |
| | | case 1: GetDlgItem(IDC_EDIT_OUT2)->SetWindowText(str); break; |
| | | case 2: GetDlgItem(IDC_EDIT_OUT3)->SetWindowText(str); break; |
| | | case 3: GetDlgItem(IDC_EDIT_OUT4)->SetWindowText(str); break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | else { |
| | | CString strError; |
| | |
| | |  |
| | | |
| | | // SGMeasurementDlg.h: 头æä»¶ |
| | | // |
| | | |
| | |
| | | #pragma once |
| | | #pragma once |
| | | |
| | | #ifndef VC_EXTRALEAN |
| | | #define VC_EXTRALEAN // ä» Windows 头䏿餿å°ä½¿ç¨çèµæ |
| | |
| | | // pch.cpp: ä¸é¢ç¼è¯æ 头对åºçæºæä»¶ |
| | | // pch.cpp: ä¸é¢ç¼è¯æ 头对åºçæºæä»¶ |
| | | |
| | | #include "pch.h" |
| | | |
| | |
| | | // pch.h: è¿æ¯é¢ç¼è¯æ 头æä»¶ã |
| | | // pch.h: è¿æ¯é¢ç¼è¯æ 头æä»¶ã |
| | | // 䏿¹ååºçæä»¶ä»
ç¼è¯ä¸æ¬¡ï¼æé«äºå°æ¥çæççææ§è½ã |
| | | // è¿è¿å°å½±å IntelliSense æ§è½ï¼å
æ¬ä»£ç 宿å许å¤ä»£ç æµè§åè½ã |
| | | // 使¯ï¼å¦ææ¤å¤ååºçæä»¶ä¸çä»»ä½ä¸ä¸ªå¨çæä¹é´ææ´æ°ï¼å®ä»¬å
¨é¨é½å°è¢«éæ°ç¼è¯ã |
| | |
| | | //{{NO_DEPENDENCIES}} |
| | | //{{NO_DEPENDENCIES}} |
| | | // Microsoft Visual C++ çæçå
嫿件ã |
| | | // ä¾ SGMeasurement.rc ä½¿ç¨ |
| | | // |
| | |
| | | #pragma once |
| | | #pragma once |
| | | |
| | | // å
æ¬ SDKDDKVer.h å°å®ä¹å¯ç¨çæé«çæ¬ç Windows å¹³å°ã |
| | | |
| | |
| | | #include "stdafx.h" |
| | | #include "Common.h" |
| | | #include "AlarmManager.h" |
| | | #include <sstream> |
| | | #include <fstream> |
| | |
| | | FOREIGN KEY (unit_id) REFERENCES units(unit_id) |
| | | ) |
| | | )"; |
| | | return m_pDB->executeQuery(createAlarmsTableQuery); |
| | | if (!m_pDB->executeQuery(createAlarmsTableQuery)) { |
| | | return false; |
| | | } |
| | | |
| | | // 设å¤å表 (ID -> åç§°) |
| | | std::vector<std::pair<int, std::string>> devices = { |
| | | {EQ_ID_LOADPORT1, EQ_NAME_LOADPORT1}, |
| | | {EQ_ID_LOADPORT2, EQ_NAME_LOADPORT2}, |
| | | {EQ_ID_LOADPORT3, EQ_NAME_LOADPORT3}, |
| | | {EQ_ID_LOADPORT4, EQ_NAME_LOADPORT4}, |
| | | {EQ_ID_ARM_TRAY1, EQ_NAME_ARM_TRAY1}, |
| | | {EQ_ID_ARM_TRAY2, EQ_NAME_ARM_TRAY2}, |
| | | {EQ_ID_ALIGNER, EQ_NAME_ALIGNER}, |
| | | {EQ_ID_FLIPER, EQ_NAME_FLIPER}, |
| | | {EQ_ID_VACUUMBAKE, EQ_NAME_VACUUMBAKE}, |
| | | {EQ_ID_Bonder1, EQ_NAME_BONDER1}, |
| | | {EQ_ID_Bonder2, EQ_NAME_BONDER2}, |
| | | {EQ_ID_BAKE_COOLING, EQ_NAME_BAKE_COOLING}, |
| | | {EQ_ID_MEASUREMENT, EQ_NAME_MEASUREMENT}, |
| | | {EQ_ID_EFEM, EQ_NAME_EFEM}, |
| | | {EQ_ID_ARM, EQ_NAME_ARM}, |
| | | {EQ_ID_OPERATOR_REMOVE, EQ_NAME_OPERATOR_REMOVE} |
| | | }; |
| | | |
| | | // æå
¥ devices å对åºçé»è®¤ unit |
| | | for (const auto& dev : devices) { |
| | | int nDeviceId = dev.first; |
| | | const std::string& strDeviceName = dev.second; |
| | | |
| | | // æå
¥è®¾å¤ |
| | | std::ostringstream ossDev; |
| | | ossDev << "INSERT OR IGNORE INTO devices (device_id, device_name) VALUES(" |
| | | << nDeviceId << ", '" << strDeviceName << "')"; |
| | | if (!m_pDB->executeQuery(ossDev.str())) { |
| | | return false; |
| | | } |
| | | |
| | | // æå
¥é»è®¤åå
(unit_id = 0, unit_name = device_name) |
| | | std::ostringstream ossUnit; |
| | | ossUnit << "INSERT OR IGNORE INTO units (device_id, unit_id, unit_name) VALUES(" |
| | | << nDeviceId << ", 0, '" << strDeviceName << "')"; |
| | | if (!m_pDB->executeQuery(ossUnit.str())) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | // 鿝æ¥è¦è¡¨ |
| | |
| | | } |
| | | |
| | | // çéæ¥è¦æ°æ® |
| | | std::vector<AlarmData> AlarmManager::getFilteredAlarms( |
| | | const std::string& id, |
| | | const std::string& severityLevel, |
| | | const std::string& deviceName, |
| | | const std::string& unitName, |
| | | const std::string& description, |
| | | const std::string& startTime, |
| | | const std::string& endTime, |
| | | int pageNumber, |
| | | int pageSize) { |
| | | |
| | | std::vector<AlarmData> AlarmManager::getFilteredAlarms(const std::string& keyword, const std::string& startTime, const std::string& endTime, int pageNumber, int pageSize) { |
| | | if (!m_pDB) { |
| | | return {}; |
| | | } |
| | |
| | | SELECT a.id, a.severity_level, a.device_id, a.unit_id, d.device_name, u.unit_name, a.description, a.start_time, a.end_time |
| | | FROM alarms a |
| | | JOIN devices d ON a.device_id = d.device_id |
| | | JOIN units u ON a.device_id = u.device_id AND a.unit_id = u.unit_id |
| | | JOIN units u ON a.device_id = u.device_id AND a.unit_id = u.unit_id |
| | | WHERE 1=1)"; |
| | | |
| | | // ä¼ å
¥çè¿æ»¤æ¡ä»¶ |
| | | if (!id.empty()) { |
| | | query << " AND a.id = '" << id << "'"; |
| | | // ç»ä¸å
³é®åæ¨¡ç³æ¥è¯¢ |
| | | if (!keyword.empty()) { |
| | | query << " AND (" |
| | | << "a.id LIKE '%" << keyword << "%' OR " |
| | | << "a.severity_level LIKE '%" << keyword << "%' OR " |
| | | << "d.device_name LIKE '%" << keyword << "%' OR " |
| | | << "u.unit_name LIKE '%" << keyword << "%' OR " |
| | | << "a.description LIKE '%" << keyword << "%')"; |
| | | } |
| | | if (!severityLevel.empty()) { |
| | | query << " AND a.severity_level = '" << severityLevel << "'"; |
| | | } |
| | | if (!deviceName.empty()) { |
| | | query << " AND d.device_name LIKE '%" << deviceName << "%'"; |
| | | } |
| | | if (!unitName.empty()) { |
| | | query << " AND u.unit_name LIKE '%" << unitName << "%'"; |
| | | } |
| | | if (!description.empty()) { |
| | | query << " AND a.description LIKE '%" << description << "%'"; |
| | | } |
| | | |
| | | // æ¶é´æ¡ä»¶ |
| | | if (!startTime.empty()) { |
| | | query << " AND a.start_time >= '" << startTime << "'"; |
| | | } |
| | |
| | | } |
| | | |
| | | // å页设置 |
| | | int offset = (pageNumber - 1) * pageSize; |
| | | query << " ORDER BY a.start_time DESC LIMIT " << pageSize << " OFFSET " << offset; |
| | | int nOffset = (pageNumber - 1) * pageSize; |
| | | query << " ORDER BY a.start_time DESC LIMIT " << pageSize << " OFFSET " << nOffset; |
| | | |
| | | // æ¥è¯¢ |
| | | auto results = m_pDB->fetchResults(query.str()); |
| | | |
| | | // éåæ¥è¯¢ç»æï¼å¡«å
AlarmData ç»æä½ |
| | |
| | | } |
| | | |
| | | // è·åç¬¦åæ¡ä»¶çæ¥è¦æ»æ° |
| | | int AlarmManager::getTotalAlarmCount( |
| | | const std::string& id, |
| | | const std::string& severityLevel, |
| | | const std::string& deviceName, |
| | | const std::string& unitName, |
| | | const std::string& description, |
| | | const std::string& startTime, |
| | | const std::string& endTime) { |
| | | |
| | | int AlarmManager::getTotalAlarmCount(const std::string& keyword, const std::string& startTime, const std::string& endTime) { |
| | | if (!m_pDB) { |
| | | return 0; |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "SELECT COUNT(*) FROM alarms a " |
| | | << "JOIN devices d ON a.device_id = d.device_id " |
| | | << "JOIN units u ON a.device_id = u.device_id AND a.unit_id = u.unit_id " |
| | | << "WHERE 1=1"; |
| | | query << R"( |
| | | SELECT COUNT(*) |
| | | FROM alarms a |
| | | JOIN devices d ON a.device_id = d.device_id |
| | | JOIN units u ON a.device_id = u.device_id AND a.unit_id = u.unit_id |
| | | WHERE 1=1)"; |
| | | |
| | | // æ·»å è¿æ»¤æ¡ä»¶ |
| | | if (!id.empty()) { |
| | | query << " AND a.id = '" << id << "'"; |
| | | // ç»ä¸å
³é®åæ¨¡ç³æ¥è¯¢ |
| | | if (!keyword.empty()) { |
| | | query << " AND (" |
| | | << "a.id LIKE '%" << keyword << "%' OR " |
| | | << "a.severity_level LIKE '%" << keyword << "%' OR " |
| | | << "d.device_name LIKE '%" << keyword << "%' OR " |
| | | << "u.unit_name LIKE '%" << keyword << "%' OR " |
| | | << "a.description LIKE '%" << keyword << "%')"; |
| | | } |
| | | if (!severityLevel.empty()) { |
| | | query << " AND a.severity_level = '" << severityLevel << "'"; |
| | | } |
| | | if (!deviceName.empty()) { |
| | | query << " AND d.device_name LIKE '%" << deviceName << "%'"; |
| | | } |
| | | if (!unitName.empty()) { |
| | | query << " AND u.unit_name LIKE '%" << unitName << "%'"; |
| | | } |
| | | if (!description.empty()) { |
| | | query << " AND a.description LIKE '%" << description << "%'"; |
| | | } |
| | | |
| | | // æ¶é´æ¡ä»¶ |
| | | if (!startTime.empty()) { |
| | | query << " AND a.start_time >= '" << startTime << "'"; |
| | | } |
| | |
| | | */ |
| | | std::vector<AlarmData> getAlarms(int startPosition, int count); |
| | | |
| | | /** |
| | | * è·åçéåçæ¥è¦æ°æ® |
| | | * @param id æ¥è¦IDçç鿡件 |
| | | * @param severityLevel æ¥è¦ç级ç鿡件 |
| | | * @param deviceName 设å¤åç§°çç鿡件 |
| | | * @param unitName åå
åç§°çç鿡件 |
| | | * @param description æ¥è¦æè¿°çç鿡件 |
| | | * @param startTime èµ·å§æ¶é´ç鿡件 |
| | | * @param endTime ç»ææ¶é´ç鿡件 |
| | | * @param pageNumber 页ç |
| | | * @param pageSize æ¯é¡µçè®°å½æ° |
| | | * @return å
嫿¥è¯¢ç»æçæ¥è¦æ°æ® |
| | | */ |
| | | std::vector<AlarmData> getFilteredAlarms( |
| | | const std::string& id, |
| | | const std::string& severityLevel, |
| | | const std::string& deviceName, |
| | | const std::string& unitName, |
| | | const std::string& description, |
| | | const std::string& startTime, |
| | | const std::string& endTime, |
| | | int pageNumber, |
| | | int pageSize); |
| | | /** |
| | | * çéæ¥è¦æ°æ® |
| | | * @param keyword å
³é®åç鿡件 |
| | | * @param startTime èµ·å§æ¶é´ç鿡件 |
| | | * @param endTime ç»ææ¶é´ç鿡件 |
| | | * @param pageNumber 页ç |
| | | * @param pageSize æ¯é¡µè®°å½æ° |
| | | * @return å
å«çéåæ¥è¦æ°æ®çç»æä½ |
| | | */ |
| | | std::vector<AlarmData> getFilteredAlarms(const std::string& keyword, const std::string& startTime, const std::string& endTime, int pageNumber, int pageSize); |
| | | |
| | | /** |
| | | * è·åç¬¦åæ¡ä»¶çæ¥è¦æ»æ° |
| | | * @param id æ¥è¦IDçç鿡件 |
| | | * @param severityLevel æ¥è¦ç级ç鿡件 |
| | | * @param deviceName 设å¤åç§°çç鿡件 |
| | | * @param unitName åå
åç§°çç鿡件 |
| | | * @param description æ¥è¦æè¿°çç鿡件 |
| | | * @param keyword å
³é®åç鿡件 |
| | | * @param startTime èµ·å§æ¶é´ç鿡件 |
| | | * @param endTime ç»ææ¶é´ç鿡件 |
| | | * @return ç¬¦åæ¡ä»¶çæ¥è¦æ»æ° |
| | | */ |
| | | int getTotalAlarmCount( |
| | | const std::string& id, |
| | | const std::string& severityLevel, |
| | | const std::string& deviceName, |
| | | const std::string& unitName, |
| | | const std::string& description, |
| | | const std::string& startTime, |
| | | const std::string& endTime); |
| | | int getTotalAlarmCount(const std::string& keyword, const std::string& startTime, const std::string& endTime); |
| | | |
| | | /** |
| | | * æ´æ°æ¥è¦ç»ææ¶é´ |
| | |
| | | void CAligner::initPins() |
| | | { |
| | | // å å
¥Pinåå§å代ç |
| | | LOGI("<CAligner>initPins"); |
| | | LOGD("<CAligner>initPins"); |
| | | addPin(SERVO::PinType::INPUT, _T("In1")); |
| | | addPin(SERVO::PinType::INPUT, _T("In2")); |
| | | addPin(SERVO::PinType::OUTPUT, _T("Out1")); |
| | |
| | | delete pStep; |
| | | } |
| | | } |
| | | |
| | | // VCR Event Report |
| | | // æºå¨ä¸æ¥æ«ç ç»æï¼æ«ç å¨é¢è®¡å®è£
å¨å·¡è¾¹æ£æºå¨ä¸ |
| | | { |
| | | CEqReadStep* pStep = new CEqReadStep(0x5fef, 15 * 2, |
| | | [&](void* pFrom, int code, const char* pszData, size_t size) -> int { |
| | | if (code == ROK && pszData != nullptr && size > 0) { |
| | | decodeVCREventReport((CStep*)pFrom, pszData, size); |
| | | } |
| | | return -1; |
| | | }); |
| | | pStep->setName(STEP_EQ_VCR1_EVENT_REPORT); |
| | | pStep->setProp("Port", (void*)1); |
| | | pStep->setWriteSignalDev(0x4a); |
| | | pStep->setReturnDev(0x91e); |
| | | if (addStep(STEP_ID_VCR1_EVENT_REPORT, pStep) != 0) { |
| | | delete pStep; |
| | | } |
| | | } |
| | | } |
| | | |
| | | void CAligner::onReceiveLBData(const char* pszData, size_t size) |
| | |
| | | void CBakeCooling::initPins() |
| | | { |
| | | // å å
¥Pinåå§å代ç |
| | | LOGI("<CBakeCooling>initPins"); |
| | | LOGD("<CBakeCooling>initPins"); |
| | | addPin(SERVO::PinType::INPUT, _T("In1")); |
| | | addPin(SERVO::PinType::INPUT, _T("In2")); |
| | | addPin(SERVO::PinType::OUTPUT, _T("Out")); |
| | |
| | | |
| | | // 3.ä¸è
ååå计 |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("ä¸è
ååå计", "", this->getName().c_str(), v * 0.01f)); |
| | | params.push_back(CParam("ä¸è
ååå计", "", this->getName().c_str(), ((short)v) * 0.01f)); |
| | | i += 2; |
| | | |
| | | // 4.管éç空è§å¼ |
| | |
| | | params.push_back(CParam("ä¸è
温度6", "", this->getName().c_str(), v * 0.1f)); |
| | | i += 2; |
| | | |
| | | // 18.ååå©ä½æ¶é´ |
| | | // 18.å çå©ä½æ¶é´ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("å çå©ä½æ¶é´", "", this->getName().c_str(), v * 0.01f)); |
| | | i += 2; |
| | | |
| | | // 19.ååå©ä½æ¶é´ |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8; |
| | | params.push_back(CParam("ååå©ä½æ¶é´", "", this->getName().c_str(), v * 0.01f)); |
| | | i += 2; |
| | |
| | | LOGI("<CEquipment-%s>åéRobotCmdSæå.", m_strName.c_str()); |
| | | } |
| | | else { |
| | | LOGI("<CEquipment-%s>åéRobotCmds失败ï¼code:%d", m_strName.c_str(), code); |
| | | LOGE("<CEquipment-%s>åéRobotCmds失败ï¼code:%d", m_strName.c_str(), code); |
| | | } |
| | | |
| | | return 0; |
| | |
| | | void CEFEM::initPins() |
| | | { |
| | | // å å
¥Pinåå§å代ç |
| | | LOGI("<CEFEM>initPins"); |
| | | LOGD("<CEFEM>initPins"); |
| | | } |
| | | |
| | | void CEFEM::initSteps() |
| | |
| | | pStep->setName(STEP_EQ_CIM_MESSAGE_CONFIRM); |
| | | pStep->setWriteSignalDev(0x49); |
| | | if (addStep(STEP_ID_CIM_MSG_CONFIRM_REPORT, pStep) != 0) { |
| | | delete pStep; |
| | | } |
| | | } |
| | | |
| | | { |
| | | // VCR Event Report |
| | | // æºå¨ä¸æ¥æ«ç ç»æï¼æ«ç å¨é¢è®¡å®è£
å¨å·¡è¾¹æ£æºå¨ä¸ |
| | | CEqReadStep* pStep = new CEqReadStep(0x5fef, 15 * 2, |
| | | [&](void* pFrom, int code, const char* pszData, size_t size) -> int { |
| | | if (code == ROK && pszData != nullptr && size > 0) { |
| | | decodeVCREventReport((CStep*)pFrom, pszData, size); |
| | | } |
| | | return -1; |
| | | }); |
| | | pStep->setName(STEP_EQ_VCR1_EVENT_REPORT); |
| | | pStep->setProp("Port", (void*)1); |
| | | pStep->setWriteSignalDev(0x4a); |
| | | pStep->setReturnDev(0x91e); |
| | | if (addStep(STEP_ID_VCR1_EVENT_REPORT, pStep) != 0) { |
| | | delete pStep; |
| | | } |
| | | } |
| | |
| | | |
| | | void CEFEM::printDebugRobotState() |
| | | { |
| | | LOGI("<CEFEM>Robot status:%d, ARM1:%s, ARM2:%s", |
| | | LOGD("<CEFEM>Robot status:%d, ARM1:%s, ARM2:%s", |
| | | m_robotData.status, |
| | | m_robotData.armState[0] ? _T("ON") : _T("OFF"), |
| | | m_robotData.armState[1] ? _T("ON") : _T("OFF")); |
| | |
| | | m_nAlarmCode = (unsigned int)CToolUnits::toInt16(&szBuffer[6]); |
| | | m_nAlarmLevel = (unsigned int)CToolUnits::toInt16(&szBuffer[8]); |
| | | |
| | | LOGI("<CEqAlarmStep> Equipment Alarm state Changed<State:%d, Unit:%d, Level:%d, Code:%d, ID:%d>", |
| | | LOGE("<CEqAlarmStep> Equipment Alarm state Changed<State:%d, Unit:%d, Level:%d, Code:%d, ID:%d>", |
| | | m_nAlarmState, m_nUnitId, m_nAlarmLevel, m_nAlarmCode, m_nAlarmId, |
| | | m_strText.c_str(), m_strDescription.c_str()); |
| | | |
| | |
| | | int CEqAlarmStep::onComplete() |
| | | { |
| | | CReadStep::onComplete(); |
| | | LOGI("<CEqAlarmStep> onComplete."); |
| | | LOGD("<CEqAlarmStep> onComplete."); |
| | | |
| | | return 0; |
| | | } |
| | |
| | | int CEqAlarmStep::onTimeout() |
| | | { |
| | | CReadStep::onTimeout(); |
| | | LOGI("<CEqAlarmStep> onTimeout."); |
| | | LOGE("<CEqAlarmStep> onTimeout."); |
| | | |
| | | return 0; |
| | | } |
| | |
| | | int CEqJobEventStep::onTimeout() |
| | | { |
| | | CReadStep::onTimeout(); |
| | | LOGI("<CEqJobEventStep> onTimeout."); |
| | | LOGE("<CEqJobEventStep> onTimeout."); |
| | | |
| | | return 0; |
| | | } |
| | |
| | | int CEqPortChangeStep::onTimeout() |
| | | { |
| | | CReadStep::onTimeout(); |
| | | LOGI("<CEQPortChangeStep> onTimeout."); |
| | | LOGE("<CEQPortChangeStep> onTimeout."); |
| | | |
| | | return 0; |
| | | } |
| | |
| | | int CEqProcessStep::onTimeout() |
| | | { |
| | | CReadStep::onTimeout(); |
| | | LOGI("<CEqProcessStep> onTimeout."); |
| | | LOGE("<CEqProcessStep> onTimeout."); |
| | | |
| | | return 0; |
| | | } |
| | |
| | | int CEqReadIntStep::onTimeout() |
| | | { |
| | | CReadStep::onTimeout(); |
| | | LOGI("<CEqReadIntStep> onTimeout."); |
| | | LOGE("<CEqReadIntStep> onTimeout."); |
| | | |
| | | return 0; |
| | | } |
| | |
| | | int nRet = m_pCclink->ReadData2(m_station, DeviceType::W, m_nDataDev, |
| | | (long)min(READ_BUFFER_MAX, m_nReadSize), szBuffer); |
| | | if (0 != nRet) { |
| | | LOGI("<CEqReadStep>Read data error."); |
| | | LOGE("<CEqReadStep>Read data error."); |
| | | if (m_onReadBlock != nullptr) { |
| | | m_onReadBlock(this, RERROR, nullptr, 0); |
| | | } |
| | | return -1; |
| | | } |
| | | |
| | | LOGI("<CEqReadStep>read data succeed."); |
| | | LOGD("<CEqReadStep>read data succeed."); |
| | | if (m_onReadBlock != nullptr) { |
| | | m_onReadBlock(this, ROK, szBuffer, m_nReadSize); |
| | | } |
| | |
| | | int CEqReadStep::onComplete() |
| | | { |
| | | CReadStep::onComplete(); |
| | | LOGI("<CEqReadStep> onComplete."); |
| | | LOGD("<CEqReadStep> onComplete."); |
| | | if (m_onReadBlock != nullptr) { |
| | | m_onReadBlock(this, RCOMPLETE, nullptr, 0); |
| | | } |
| | |
| | | int CEqReadStep::onTimeout() |
| | | { |
| | | CReadStep::onTimeout(); |
| | | LOGI("<CEqReadStep> onTimeout."); |
| | | LOGE("<CEqReadStep> onTimeout."); |
| | | if (m_onReadBlock != nullptr) { |
| | | m_onReadBlock(this, RTIMEOUT, nullptr, 0); |
| | | } |
| | |
| | | int CEqStatusStep::onTimeout() |
| | | { |
| | | CReadStep::onTimeout(); |
| | | LOGI("<CEqStatusStep> onTimeout."); |
| | | LOGE("<CEqStatusStep> onTimeout."); |
| | | |
| | | return 0; |
| | | } |
| | |
| | | int CEqVcrEventStep::onTimeout() |
| | | { |
| | | CReadStep::onTimeout(); |
| | | LOGI("<CEqVcrEventStep> onTimeout."); |
| | | LOGE("<CEqVcrEventStep> onTimeout."); |
| | | |
| | | return 0; |
| | | } |
| | |
| | | #include "CArm.h" |
| | | #include "CGlassPool.h" |
| | | #include "Servo.h" |
| | | #include "GlassJson.h" |
| | | |
| | | |
| | | namespace SERVO { |
| | |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | | m_slot[i].serialize(ar); |
| | | CGlass* pGlass = (CGlass *)m_slot[i].getContext(); |
| | | if (pGlass != nullptr) { |
| | | pGlass->serialize(ar); |
| | | if (pGlass != nullptr) { |
| | | const std::string pretty = GlassJson::ToPrettyString(*pGlass); |
| | | CString strPretty = CString(pretty.c_str()); |
| | | ar << strPretty; |
| | | |
| | | CGlass* pBuddy = pGlass->getBuddy(); |
| | | if (pBuddy != nullptr) { |
| | | pBuddy->serialize(ar); |
| | | const std::string prettyBuddy = GlassJson::ToPrettyString(*pBuddy); |
| | | CString strPrettyBuddy = CString(prettyBuddy.c_str()); |
| | | ar << strPrettyBuddy; |
| | | } |
| | | } |
| | | } |
| | |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | | m_slot[i].serialize(ar); |
| | | if (m_slot[i].getTempContext() != nullptr) { |
| | | CGlass* pGlass = theApp.m_model.m_glassPool.allocaGlass(); |
| | | pGlass->serialize(ar); |
| | | m_slot[i].setContext(pGlass); |
| | | if (pGlass->getBuddy() != nullptr) { |
| | | CGlass* pBuddy = theApp.m_model.m_glassPool.allocaGlass(); |
| | | pBuddy->serialize(ar); |
| | | pGlass->forceSetBuddy(pBuddy); |
| | | CString strPretty; |
| | | std::string pretty; |
| | | ar >> strPretty; |
| | | pretty = (LPTSTR)(LPCTSTR)strPretty; |
| | | if (!pretty.empty()) { |
| | | CGlass* pGlass = theApp.m_model.m_glassPool.allocaGlass(); |
| | | GlassJson::FromString(pretty, *pGlass); |
| | | m_slot[i].setContext(pGlass); |
| | | |
| | | if (!pGlass->getBuddyId().empty()) { |
| | | CGlass* pBuddy = theApp.m_model.m_glassPool.allocaGlass(); |
| | | CString strPrettyBuddy; |
| | | std::string prettyBuddy; |
| | | ar >> strPrettyBuddy; |
| | | prettyBuddy = (LPTSTR)(LPCTSTR)strPrettyBuddy; |
| | | GlassJson::FromString(prettyBuddy, *pBuddy); |
| | | pGlass->forceSetBuddy(pBuddy); |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | | |
| | | |
| | | // 梳çåç»çä¹é´çç»å®å
³ç³» |
| | | /* |
| | | Lock(); |
| | |
| | | CEquipment* pFromEq = pFromPin->getEquipment(); |
| | | ASSERT(pFromEq); |
| | | |
| | | LOGI("<CEquipment><%s-%s>æ¶å°æ¥èª<%s.%s>çIntent<%d,%s,0x%x>", |
| | | LOGD("<CEquipment><%s-%s>æ¶å°æ¥èª<%s.%s>çIntent<%d,%s,0x%x>", |
| | | this->getName().c_str(), |
| | | pPin->getName().c_str(), |
| | | pFromEq->getName().c_str(), |
| | |
| | | |
| | | ASSERT(pGlass); |
| | | Lock(); |
| | | pGlass->addPath(m_nID, getSlotUnit(putSlot)); |
| | | pGlass->addPath(m_nID, getSlotUnit(putSlot), putSlot); |
| | | CGlass* pBuddy = pGlass->getBuddy(); |
| | | if (pBuddy != nullptr) pBuddy->addPath(m_nID, getSlotUnit(putSlot), putSlot); |
| | | m_slot[putSlot - 1].setContext(pGlass); |
| | | pGlass->release(); // tempFetchOutéè¦è°ç¨ä¸æ¬¡release |
| | | Unlock(); |
| | |
| | | |
| | | |
| | | return nullptr; |
| | | } |
| | | |
| | | int CEquipment::getAllGlass(std::vector<CGlass*>& glasses) |
| | | { |
| | | Lock(); |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | | if (!m_slot[i].isEnable()) continue; |
| | | CGlass* pGlass = (CGlass*)m_slot[i].getContext(); |
| | | if (pGlass != nullptr) { |
| | | pGlass->addRef(); |
| | | glasses.push_back(pGlass); |
| | | } |
| | | } |
| | | Unlock(); |
| | | |
| | | return (int)glasses.size(); |
| | | } |
| | | |
| | | CJobDataS* CEquipment::getJobDataSWithCassette(int cassetteSequenceNo, int jobSequenceNo) |
| | |
| | | LOGI("<CEquipment-%s>设置DispatchingModeæå.", m_strName.c_str()); |
| | | } |
| | | else { |
| | | LOGI("<CEquipment-%s>设置DispatchingMode失败ï¼code:%d", m_strName.c_str(), code); |
| | | LOGE("<CEquipment-%s>设置DispatchingMode失败ï¼code:%d", m_strName.c_str(), code); |
| | | } |
| | | |
| | | return 0; |
| | |
| | | LOGI("<CEquipment-%s>è¿åå¼: %d", m_strName.c_str(), retCode); |
| | | } |
| | | else { |
| | | LOGI("<CEquipment-%s>设置indexerOperationMode失败ï¼code:%d", m_strName.c_str(), code); |
| | | LOGE("<CEquipment-%s>设置indexerOperationMode失败ï¼code:%d", m_strName.c_str(), code); |
| | | } |
| | | |
| | | if (onWritedRetBlock != nullptr) { |
| | |
| | | } |
| | | else { |
| | | m_recipesManager.syncFailed(); |
| | | LOGI("<CEquipment-%s>请æ±åå
<%d>主é
æ¹å表失败ï¼code:%d", m_strName.c_str(), unitNo, code); |
| | | LOGE("<CEquipment-%s>请æ±åå
<%d>主é
æ¹å表失败ï¼code:%d", m_strName.c_str(), unitNo, code); |
| | | } |
| | | |
| | | return 0; |
| | |
| | | } |
| | | else { |
| | | m_recipesManager.syncFailed(); |
| | | LOGI("<CEquipment-%s>请æ±åå
<%d>主é
æ¹åæ°å表失败ï¼code:%d", m_strName.c_str(), unitNo, code); |
| | | LOGE("<CEquipment-%s>请æ±åå
<%d>主é
æ¹åæ°å表失败ï¼code:%d", m_strName.c_str(), unitNo, code); |
| | | } |
| | | |
| | | return 0; |
| | |
| | | CSlot* CEquipment::getProcessedSlot(MaterialsType putSlotType, BOOL bJobMode/* = FALSE*/) |
| | | { |
| | | for (int i = 0; i < SLOT_MAX; i++) { |
| | | if (m_nTestFlag == 1) LOGI("getProcessedSlot 001"); |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 001"); |
| | | if (!m_slot[i].isEnable()) continue; |
| | | if (m_nTestFlag == 1) LOGI("getProcessedSlot 002"); |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 002"); |
| | | if (m_slot[i].isLock()) continue; |
| | | if (m_nTestFlag == 1) LOGI("getProcessedSlot 003"); |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 003"); |
| | | CGlass* pGlass = (CGlass*)m_slot[i].getContext(); |
| | | if (!isSlotProcessed(i)) continue; |
| | | if (m_nTestFlag == 1) LOGI("getProcessedSlot 004"); |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 004"); |
| | | if (pGlass == nullptr) continue; |
| | | if (m_nTestFlag == 1) LOGI("getProcessedSlot 005"); |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 005"); |
| | | if (!pGlass->isScheduledForProcessing()) continue; |
| | | if (m_nTestFlag == 1) LOGI("getProcessedSlot 006"); |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 006"); |
| | | if (bJobMode && pGlass->getProcessJob() == nullptr) continue; |
| | | if (m_nTestFlag == 1) LOGI("getProcessedSlot 007"); |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 007"); |
| | | if(pGlass->getInspResult(m_nID, 0) == InspResult::Fail) continue; |
| | | int lsPath = m_slot[i].getLinkSignalPath(); |
| | | if(!m_bLinkSignalToUpstream[lsPath][SIGNAL_UPSTREAM_INLINE] |
| | | || m_bLinkSignalToUpstream[lsPath][SIGNAL_UPSTREAM_TROUBLE] |
| | | || !m_bLinkSignalToUpstream[lsPath][SIGNAL_INTERLOCK] |
| | | || !m_bLinkSignalToUpstream[lsPath][SIGNAL_SEND_ABLE] ) continue; |
| | | if (m_nTestFlag == 1) LOGI("getProcessedSlot 008"); |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 008"); |
| | | MaterialsType glassType = pGlass->getType(); |
| | | if (glassType == MaterialsType::G1 && putSlotType == MaterialsType::G2) continue; |
| | | if (m_nTestFlag == 1) LOGI("getProcessedSlot 009"); |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 009"); |
| | | if (glassType == MaterialsType::G2 && putSlotType == MaterialsType::G1) continue; |
| | | if (m_nTestFlag == 1) LOGI("getProcessedSlot 00a"); |
| | | if (m_nTestFlag == 1) LOGD("getProcessedSlot 00a"); |
| | | return &m_slot[i]; |
| | | } |
| | | |
| | |
| | | CGlass* pGlass = this->getGlassWithCassette(processData.getCassetteSequenceNo(), |
| | | processData.getJobSequenceNo()); |
| | | if (pGlass == nullptr) { |
| | | LOGE("<CEquipment-%s>æ¾ä¸å°å¯¹åºGlass, å
³èå·¥èºåæ°å¤±è´¥ã", this->getName().c_str(), |
| | | LOGE("<CEquipment-%s>æ¾ä¸å°å¯¹åºGlass, å
³èå·¥èºåæ°å¤±è´¥ãCassetteSequenceNo:%d/%d", |
| | | this->getName().c_str(), |
| | | processData.getCassetteSequenceNo(), |
| | | processData.getJobSequenceNo()); |
| | | return -1; |
| | |
| | | std::vector<CParam> params; |
| | | this->parsingParams((const char*)rawData.data(), rawData.size(), params); |
| | | pGlass->addParams(params); |
| | | |
| | | |
| | | // å
³èçGlassä¹è¦æ´æ° |
| | | CGlass* pBuddy = pGlass->getBuddy(); |
| | | LOGI("<Equipment-%s>decodeProcessDataReport pBuddy=%x %s", getName().c_str(), pBuddy, pGlass->getID().c_str()); |
| | | if (pBuddy != nullptr) { |
| | | LOGI("<Equipment-%s>decodeProcessDataReport addParams pBuddy=%x %s", getName().c_str(), pBuddy, pGlass->getID().c_str()); |
| | | pBuddy->addParams(params); |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | |
| | | vcrEventReport.getGlassId().c_str()); |
| | | |
| | | |
| | | // æ´æ°GlassçID |
| | | CGlass* pGlass = getGlassWithCassette(vcrEventReport.getCassetteSequenceNo(), |
| | | vcrEventReport.getJobSequenceNo()); |
| | | if (pGlass != nullptr) { |
| | | pGlass->setID(vcrEventReport.getGlassId().c_str()); |
| | | } |
| | | |
| | | |
| | | // ç¼åAttributeï¼ç¨äºè°è¯æ¶æ¾ç¤ºä¿¡æ¯ |
| | | unsigned int weight = 201; |
| | | CAttributeVector& attrubutes = pStep->attributeVector(); |
| | | vcrEventReport.getAttributeVector(attrubutes, weight); |
| | | |
| | | |
| | | // 0426, å
åºå®è¿å1(OK) |
| | | ((CReadStep*)pStep)->setReturnCode((short)VCR_Reply_Code::OK); |
| | | |
| | | |
| | | return 0; |
| | | } |
| | |
| | | getName().c_str(), cassetteNo, jobSequenceNo); |
| | | return -1; |
| | | } |
| | | pGlass->setInspResult(m_nID, 0, judgeStringToInspResult(strPanelJudgeData)); |
| | | auto result = judgeStringToInspResult(strPanelJudgeData); |
| | | pGlass->setInspResult(m_nID, 0, result); |
| | | |
| | | if (m_listener.onPanelDataReport != nullptr) { |
| | | m_listener.onPanelDataReport(this, pGlass); |
| | | } |
| | | |
| | | return 0; |
| | | } |
| | |
| | | ONMAPMISMATCH onMapMismatch; |
| | | ONPORTSTATUSCHANGED onPortStatusChanged; |
| | | ONVCREVENTREPORT onSVDataReport; |
| | | ONVCREVENTREPORT onPanelDataReport; |
| | | } EquipmentListener; |
| | | |
| | | |
| | |
| | | CGlass* getGlassWithCassette(int cassetteSequenceNo, int jobSequenceNo); |
| | | CGlass* getAnyGlass(); |
| | | CGlass* getGlass(const char* pszGlassId); |
| | | int getAllGlass(std::vector<CGlass*>& glasses); |
| | | CJobDataS* getJobDataSWithCassette(int cassetteSequenceNo, int jobSequenceNo); |
| | | |
| | | // éªè¯ç»çåæ§½æ¯å¦å¹é
|
| | |
| | | AfxMessageBox("设置EASæ¨¡å¼æåï¼"); |
| | | } |
| | | else { |
| | | LOGI("<CEquipment-%s>设置DispatchingMode失败ï¼code:%d", m_pEquipment->getName().c_str(), code); |
| | | LOGE("<CEquipment-%s>设置DispatchingMode失败ï¼code:%d", m_pEquipment->getName().c_str(), code); |
| | | AfxMessageBox("设置EAS模å¼å¤±è´¥ï¼"); |
| | | } |
| | | |
| | |
| | | |
| | | IMPLEMENT_DYNAMIC(CExpandableListCtrl, CListCtrl) |
| | | |
| | | CExpandableListCtrl::CExpandableListCtrl() {} |
| | | CExpandableListCtrl::CExpandableListCtrl() |
| | | { |
| | | m_popupCols = { }; |
| | | } |
| | | |
| | | CExpandableListCtrl::~CExpandableListCtrl() {} |
| | | |
| | | BEGIN_MESSAGE_MAP(CExpandableListCtrl, CListCtrl) |
| | |
| | | if (CListCtrl::OnCreate(lpCreateStruct) == -1) |
| | | return -1; |
| | | |
| | | // æ¥è¡¨é£æ ¼åä¸¾ä¾ |
| | | SetExtendedStyle(GetExtendedStyle() |
| | | | LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_GRIDLINES | LVS_EX_DOUBLEBUFFER); |
| | | |
| | |
| | | |
| | | void CExpandableListCtrl::PreSubclassWindow() |
| | | { |
| | | // æ¥è¡¨é£æ ¼åä¸¾ä¾ |
| | | SetExtendedStyle(GetExtendedStyle() |
| | | | LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_GRIDLINES | LVS_EX_DOUBLEBUFFER); |
| | | |
| | | CListCtrl::PreSubclassWindow(); |
| | | } |
| | | |
| | | // ===== æ API ===== |
| | | CExpandableListCtrl::Node* CExpandableListCtrl::InsertRoot(const std::vector<CString>& cols) |
| | | { |
| | | auto n = std::make_unique<Node>((int)max(1, (int)cols.size())); |
| | |
| | | |
| | | void CExpandableListCtrl::RebuildVisible() |
| | | { |
| | | // 1) é建å¯è§åºå |
| | | m_visible.clear(); |
| | | for (auto& r : m_roots) appendVisible(r.get()); |
| | | |
| | | // 2) éç»/éå¡«æ°æ® |
| | | SetRedraw(FALSE); |
| | | DeleteAllItems(); |
| | | |
| | | // æå
¥å¯è§è¡ |
| | | for (int i = 0; i < (int)m_visible.size(); ++i) { |
| | | Node* n = m_visible[i]; |
| | | LVITEM lvi{}; |
| | |
| | | lvi.pszText = const_cast<LPTSTR>((LPCTSTR)(n->cols.empty() ? _T("") : n->cols[0])); |
| | | InsertItem(&lvi); |
| | | |
| | | for (int col = 1; col < GetHeaderCtrl()->GetItemCount(); ++col) { |
| | | const int colCount = GetHeaderCtrl() ? GetHeaderCtrl()->GetItemCount() : 1; |
| | | for (int col = 1; col < colCount; ++col) { |
| | | CString txt = (col < (int)n->cols.size()) ? n->cols[col] : _T(""); |
| | | SetItemText(i, col, txt); |
| | | } |
| | | } |
| | | |
| | | // é建åï¼æè¡å·é¢è²æ°ç»å¯¹é½ |
| | | m_rowColors.resize(GetItemCount()); |
| | | |
| | | SetRedraw(TRUE); |
| | | Invalidate(); |
| | | } |
| | |
| | | return m_visible[i]; |
| | | } |
| | | |
| | | // ===== é¢è² API ===== |
| | | void CExpandableListCtrl::SetNodeColor(Node* n, COLORREF text, COLORREF bk) |
| | | { |
| | | if (!n) return; |
| | | RowColor rc{}; |
| | | rc.text = text; rc.bk = bk; |
| | | rc.hasText = (text != CLR_DEFAULT); |
| | | rc.hasBk = (bk != CLR_DEFAULT); |
| | | m_colorByNode[n] = rc; |
| | | |
| | | for (int i = 0; i < (int)m_visible.size(); ++i) { |
| | | if (m_visible[i] == n) { |
| | | RedrawItems(i, i); |
| | | UpdateWindow(); |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | |
| | | void CExpandableListCtrl::ClearNodeColor(Node* n) |
| | | { |
| | | if (!n) return; |
| | | auto it = m_colorByNode.find(n); |
| | | if (it != m_colorByNode.end()) { |
| | | m_colorByNode.erase(it); |
| | | for (int i = 0; i < (int)m_visible.size(); ++i) { |
| | | if (m_visible[i] == n) { |
| | | RedrawItems(i, i); |
| | | UpdateWindow(); |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | void CExpandableListCtrl::ClearAllColors() |
| | | { |
| | | m_colorByNode.clear(); |
| | | m_rowColors.clear(); |
| | | Invalidate(FALSE); |
| | | } |
| | | |
| | | // å
¼å®¹æ§æ¥å£ï¼æâå¯è§è¡å·âçè² |
| | | void CExpandableListCtrl::SetItemColor(DWORD_PTR iItem, COLORREF TextColor, COLORREF TextBkColor) |
| | | { |
| | | SetItemColorByVisibleIndex((int)iItem, TextColor, TextBkColor); |
| | | } |
| | | void CExpandableListCtrl::SetItemColorByVisibleIndex(int row, COLORREF text, COLORREF bk) |
| | | { |
| | | if (row < 0) return; |
| | | if (row >= (int)m_rowColors.size()) |
| | | m_rowColors.resize(row + 1); |
| | | |
| | | RowColor rc{}; |
| | | rc.text = text; rc.bk = bk; |
| | | rc.hasText = (text != CLR_DEFAULT); |
| | | rc.hasBk = (bk != CLR_DEFAULT); |
| | | m_rowColors[row] = rc; |
| | | |
| | | RedrawItems(row, row); |
| | | UpdateWindow(); |
| | | } |
| | | |
| | | CRect CExpandableListCtrl::expanderRectForRow(int row) const |
| | | { |
| | | CRect rcLabel; |
| | |
| | | |
| | | Node* n = const_cast<CExpandableListCtrl*>(this)->GetNodeByVisibleIndex(row); |
| | | if (!n || n->children.empty()) |
| | | return CRect(0, 0, 0, 0); // å¶åä¸å ä½ï¼ææ¬å°±ä¸ä¼è¢«å¤æ¨ä¸æ ¼ |
| | | return CRect(0, 0, 0, 0); |
| | | |
| | | const int indent = n->level; |
| | | const int left = rcLabel.left + m_expanderPadding + indent * 16; |
| | |
| | | ); |
| | | } |
| | | |
| | | // é¢è²è®¡ç®ï¼ä¼å
Node*ï¼å
¶æ¬¡è¡å·ï¼è¥éè¦å让系ç»é«äº®è¦ç |
| | | void CExpandableListCtrl::computeColorsForRow(int row, COLORREF& outText, COLORREF& outBk) const |
| | | { |
| | | outText = ListView_GetTextColor(const_cast<CExpandableListCtrl*>(this)->m_hWnd); |
| | | outBk = ListView_GetBkColor(const_cast<CExpandableListCtrl*>(this)->m_hWnd); |
| | | |
| | | const bool selected = (const_cast<CExpandableListCtrl*>(this)->GetItemState(row, LVIS_SELECTED) & LVIS_SELECTED) != 0; |
| | | const bool focusOnCtrl = (const_cast<CExpandableListCtrl*>(this)->GetSafeHwnd() == ::GetFocus()); |
| | | |
| | | if (m_preserveSelHighlight && selected) { |
| | | outBk = GetSysColor(focusOnCtrl ? COLOR_HIGHLIGHT : COLOR_3DFACE); |
| | | outText = GetSysColor(focusOnCtrl ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT); |
| | | return; |
| | | } |
| | | |
| | | // Node* é¢è² |
| | | if (Node* n = const_cast<CExpandableListCtrl*>(this)->GetNodeByVisibleIndex(row)) { |
| | | auto it = m_colorByNode.find(n); |
| | | if (it != m_colorByNode.end()) { |
| | | if (it->second.hasText) outText = it->second.text; |
| | | if (it->second.hasBk) outBk = it->second.bk; |
| | | return; |
| | | } |
| | | } |
| | | |
| | | // è¡å·é¢è² |
| | | if (row >= 0 && row < (int)m_rowColors.size()) { |
| | | const RowColor& rc = m_rowColors[row]; |
| | | if (rc.hasText) outText = rc.text; |
| | | if (rc.hasBk) outBk = rc.bk; |
| | | } |
| | | } |
| | | |
| | | void CExpandableListCtrl::OnClick(NMHDR* pNMHDR, LRESULT* pResult) |
| | | { |
| | | LPNMITEMACTIVATE pia = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); |
| | | if (pia->iItem >= 0) { |
| | | CPoint pt = pia->ptAction; |
| | | |
| | | // å½ä¸å±å¼æé®ï¼ |
| | | CRect expRc = expanderRectForRow(pia->iItem); |
| | | if (expRc.PtInRect(pt)) { |
| | | Node* n = GetNodeByVisibleIndex(pia->iItem); |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | // ââ è¥ç¹å»å°éè¦âå
¨ææ¾ç¤ºâçåï¼ååç¶çªå£åéèªå®ä¹éç¥ ââ // |
| | | if (!m_popupCols.empty()) { |
| | | LPNMITEMACTIVATE pia = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); |
| | | |
| | | // ç¨ SubItemHitTest æ´ç²¾åæ¿å°å |
| | | LVHITTESTINFO ht{}; |
| | | ht.pt = pia->ptAction; |
| | | int hit = SubItemHitTest(&ht); |
| | | if (hit >= 0 && ht.iItem >= 0 && ht.iSubItem >= 0) { |
| | | const int row = ht.iItem; |
| | | const int col = ht.iSubItem; |
| | | |
| | | if (m_popupCols.count(col)) { |
| | | CString full = GetItemText(row, col); |
| | | if (!full.IsEmpty() && _IsCellTruncated(row, col, full)) { |
| | | NMC_ELC_SHOWFULLTEXT nm{}; |
| | | nm.hdr.hwndFrom = m_hWnd; |
| | | nm.hdr.idFrom = GetDlgCtrlID(); |
| | | nm.hdr.code = ELCN_SHOWFULLTEXT; |
| | | nm.iItem = row; |
| | | nm.iSubItem = col; |
| | | nm.text = full; |
| | | |
| | | if (CWnd* pParent = GetParent()) { |
| | | pParent->SendMessage(WM_NOTIFY, nm.hdr.idFrom, reinterpret_cast<LPARAM>(&nm)); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | *pResult = 0; |
| | | } |
| | | |
| | |
| | | return; |
| | | |
| | | case CDDS_ITEMPREPAINT: |
| | | { |
| | | const int row = (int)pCD->nmcd.dwItemSpec; |
| | | COLORREF txt, bk; |
| | | computeColorsForRow(row, txt, bk); |
| | | pCD->clrText = txt; |
| | | pCD->clrTextBk = bk; |
| | | *pResult = CDRF_NOTIFYSUBITEMDRAW; |
| | | return; |
| | | } |
| | | |
| | | case CDDS_ITEMPREPAINT | CDDS_SUBITEM: |
| | | { |
| | |
| | | const int col = pCD->iSubItem; |
| | | CDC* pDC = CDC::FromHandle(pCD->nmcd.hdc); |
| | | |
| | | if (col == 0) |
| | | { |
| | | CRect rc; GetSubItemRect(row, 0, LVIR_LABEL, rc); |
| | | Node* n = GetNodeByVisibleIndex(row); |
| | | if (!n) { *pResult = CDRF_DODEFAULT; return; } |
| | | |
| | | // 1) èæ¯/忝é¢è²ï¼ææ¯å¦éä¸ |
| | | const bool selected = (GetItemState(row, LVIS_SELECTED) & LVIS_SELECTED) != 0; |
| | | const bool focusOnCtrl = (GetSafeHwnd() == ::GetFocus()); |
| | | COLORREF bk = selected ? GetSysColor(focusOnCtrl ? COLOR_HIGHLIGHT : COLOR_3DFACE) |
| | | : ListView_GetBkColor(m_hWnd); |
| | | COLORREF txt = selected ? GetSysColor(focusOnCtrl ? COLOR_HIGHLIGHTTEXT : COLOR_WINDOWTEXT) |
| | | : ListView_GetTextColor(m_hWnd); |
| | | |
| | | // ä»
å¨éè¦æ¶å¡«å
èæ¯ï¼é¿å
âé»ä¸çâï¼ |
| | | CBrush bkBrush(bk); |
| | | pDC->FillRect(rc, &bkBrush); |
| | | |
| | | // 2) å±å¼/æå æç¤ºï¼åèæ§é¡¹ç®çå³å¯¹é½åæ æ³ï¼ååç´ å¯¹é½ï¼çº¯GDIï¼ |
| | | if (!n->children.empty()) |
| | | { |
| | | CRect box = expanderRectForRow(row); |
| | | |
| | | // ---- å¯è°åæ°ï¼ä¸æ§ä»£ç å½åä¸è´ ---- |
| | | // å³ä¾§çç½ï¼ä¸ææ¬é´é/ç½æ ¼çº¿ä¿æè·ç¦»ï¼ |
| | | const int ROFFSET = 2; |
| | | // éå/å±å¼çâ宽度â设置ï¼å¥æ°æ´é¡ºç¼ï¼9/11 é½è¡ï¼ |
| | | const int WIDE = max(9, min(min(box.Width(), box.Height()), 13)); // â¶ çè¾¹é¿ |
| | | const int WIDE2 = WIDE / 2; // ä¸å |
| | | const int EXPANDED_WIDE = WIDE; // â¼ çè¾¹é¿ |
| | | |
| | | // 轻微å
缩ï¼é¿å
è´´è¾¹ï¼ä¸ä½ æ§ä»£ç âæé®è¦å·ä¸ä¸âåæï¼ |
| | | box.DeflateRect(1, 1); |
| | | |
| | | // ç»ä¸åå¶æ°å¯¹é½ï¼åå°ååç´ é¯é½¿ |
| | | auto even = [](int v) { return (v & 1) ? (v - 1) : v; }; |
| | | |
| | | // 计ç®âèªä¸åä¸âçåºååç§»ï¼ä¸æ§ TreeCtrl ä¸è´ |
| | | // è¿éç¨ box ä½ä¸º pRect |
| | | POINT pt[3]; |
| | | if (n->expanded) { |
| | | // â¼ |
| | | int nBottomOffset = (box.Height() - EXPANDED_WIDE) / 2; |
| | | pt[0].x = box.right - ROFFSET - EXPANDED_WIDE; |
| | | pt[0].y = box.bottom - nBottomOffset; |
| | | pt[1].x = box.right - ROFFSET; |
| | | pt[1].y = box.bottom - nBottomOffset; |
| | | pt[2].x = box.right - ROFFSET; |
| | | pt[2].y = box.bottom - nBottomOffset - EXPANDED_WIDE; |
| | | } |
| | | else { |
| | | // â¶ |
| | | int nBottomOffset = (box.Height() - WIDE) / 2; |
| | | |
| | | pt[0].x = box.right - ROFFSET - WIDE2; |
| | | pt[0].y = box.bottom - nBottomOffset - WIDE; |
| | | pt[1].x = box.right - ROFFSET - WIDE2; |
| | | pt[1].y = box.bottom - nBottomOffset; |
| | | pt[2].x = box.right - ROFFSET; |
| | | pt[2].y = box.bottom - nBottomOffset - WIDE2; |
| | | } |
| | | |
| | | // ä»
å¡«å
ï¼ä¸æè¾¹ï¼æè¾¹ä¼å éå°é¶æï¼ï¼é¢è²ç¨ txt ä¸ä¸»é¢ä¸è´ |
| | | HGDIOBJ oldPen = pDC->SelectObject(GetStockObject(NULL_PEN)); |
| | | HBRUSH hBrush = CreateSolidBrush(txt); |
| | | HGDIOBJ oldBrush = pDC->SelectObject(hBrush); |
| | | |
| | | pDC->Polygon(pt, 3); |
| | | |
| | | pDC->SelectObject(oldPen); |
| | | pDC->SelectObject(oldBrush); |
| | | DeleteObject(hBrush); |
| | | } |
| | | |
| | | |
| | | |
| | | // 3) ææ¬ï¼åºäºé¦ååºåå³ç§»ï¼åºåæ¯å¦æåèç¹ï¼ |
| | | const int indentPx = n->level * 14; |
| | | const int baseLeft = rc.left + m_expanderPadding + indentPx; |
| | | |
| | | CRect textRc = rc; |
| | | if (!n->children.empty()) { |
| | | // æå项ï¼é¢çæé®ä½ + ææ¬é´é |
| | | textRc.left = baseLeft + m_expanderSize + m_textGap; |
| | | } |
| | | else { |
| | | // å¶åè¡ï¼ä¸é¢çæé®ä½ï¼åªç»ä¸ç¹ç¹å¶åé´éï¼è®©å±çº§ç¼©è¿ä»ç¶çæï¼ |
| | | constexpr int kLeafGap = 2; // ä½ å¯è° 0~4 |
| | | textRc.left = baseLeft + kLeafGap; |
| | | } |
| | | |
| | | pDC->SetBkMode(TRANSPARENT); |
| | | pDC->SetTextColor(txt); |
| | | CString txt0 = n->cols.empty() ? _T("") : n->cols[0]; |
| | | pDC->DrawText(txt0, textRc, DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_END_ELLIPSIS); |
| | | |
| | | |
| | | // ââ ç»å®ä¸è§ä¸ææ¬ä¹åï¼è¡¥ä¸æ¡è¯¥è¡çåºé¨æ¨ªåç½æ ¼çº¿ ââ |
| | | // ä»
å½å¼å¯äº LVS_EX_GRIDLINES æç»å¶ |
| | | if (GetExtendedStyle() & LVS_EX_GRIDLINES) |
| | | { |
| | | // ç¨æ´è¡ boundsï¼ä¿è¯æ¨ªçº¿è´¯ç©¿ææåçå¯è§å®½åº¦ |
| | | CRect rcRow; |
| | | GetSubItemRect(row, 0, LVIR_BOUNDS, rcRow); |
| | | |
| | | // åºè¾¹ y åæ ï¼ä¸ç³»ç»ç½æ ¼çº¿å¯¹é½ï¼ |
| | | const int y = rcRow.bottom - 1; |
| | | |
| | | // é¢è²ä¸ç³»ç»é£æ ¼æ¥è¿ï¼è¥è§å¾åæµ
ï¼å¯æ¢ COLOR_3DSHADOW |
| | | CPen pen(PS_SOLID, 1, GetSysColor(COLOR_3DLIGHT)); |
| | | CPen* oldPen = pDC->SelectObject(&pen); |
| | | |
| | | // 横线ä»è¡å·¦å°è¡å³ï¼å½åå¯è§åºåï¼ |
| | | pDC->MoveTo(rcRow.left, y); |
| | | pDC->LineTo(rcRow.right, y); |
| | | |
| | | pDC->SelectObject(oldPen); |
| | | } |
| | | |
| | | *pResult = CDRF_SKIPDEFAULT; |
| | | // å¦ææ²¡ææ èç¹ï¼çº¯å¹³å表ï¼ï¼é¦åä¹èµ°é»è®¤ç»å¶ |
| | | Node* n = GetNodeByVisibleIndex(row); |
| | | if (col != 0 || !n) { |
| | | *pResult = CDRF_DODEFAULT; |
| | | return; |
| | | } |
| | | |
| | | // å
¶ä»åé»è®¤ç»å¶ |
| | | *pResult = CDRF_DODEFAULT; |
| | | // é¦åèªç»ï¼æ 模å¼ï¼ |
| | | CRect rc; GetSubItemRect(row, 0, LVIR_LABEL, rc); |
| | | |
| | | COLORREF bk, txt; |
| | | computeColorsForRow(row, txt, bk); |
| | | |
| | | CBrush bkBrush(bk); |
| | | pDC->FillRect(rc, &bkBrush); |
| | | |
| | | if (!n->children.empty()) |
| | | { |
| | | CRect box = expanderRectForRow(row); |
| | | const int ROFFSET = 2; |
| | | const int WIDE = max(9, min(min(box.Width(), box.Height()), 13)); |
| | | const int WIDE2 = WIDE / 2; |
| | | const int EXPANDED_WIDE = WIDE; |
| | | |
| | | box.DeflateRect(1, 1); |
| | | |
| | | POINT pt[3]; |
| | | if (n->expanded) { |
| | | int nBottomOffset = (box.Height() - EXPANDED_WIDE) / 2; |
| | | pt[0].x = box.right - ROFFSET - EXPANDED_WIDE; |
| | | pt[0].y = box.bottom - nBottomOffset; |
| | | pt[1].x = box.right - ROFFSET; |
| | | pt[1].y = box.bottom - nBottomOffset; |
| | | pt[2].x = box.right - ROFFSET; |
| | | pt[2].y = box.bottom - nBottomOffset - EXPANDED_WIDE; |
| | | } |
| | | else { |
| | | int nBottomOffset = (box.Height() - WIDE) / 2; |
| | | pt[0].x = box.right - ROFFSET - WIDE2; |
| | | pt[0].y = box.bottom - nBottomOffset - WIDE; |
| | | pt[1].x = box.right - ROFFSET - WIDE2; |
| | | pt[1].y = box.bottom - nBottomOffset; |
| | | pt[2].x = box.right - ROFFSET; |
| | | pt[2].y = box.bottom - nBottomOffset - WIDE2; |
| | | } |
| | | |
| | | HGDIOBJ oldPen = pDC->SelectObject(GetStockObject(NULL_PEN)); |
| | | HBRUSH hBrush = CreateSolidBrush(txt); |
| | | HGDIOBJ oldBrush = pDC->SelectObject(hBrush); |
| | | pDC->Polygon(pt, 3); |
| | | pDC->SelectObject(oldPen); |
| | | pDC->SelectObject(oldBrush); |
| | | DeleteObject(hBrush); |
| | | } |
| | | |
| | | const int indentPx = n->level * 14; |
| | | const int baseLeft = rc.left + m_expanderPadding + indentPx; |
| | | |
| | | CRect textRc = rc; |
| | | if (!n->children.empty()) { |
| | | textRc.left = baseLeft + m_expanderSize + m_textGap; |
| | | } |
| | | else { |
| | | constexpr int kLeafGap = 2; |
| | | textRc.left = baseLeft + kLeafGap; |
| | | } |
| | | |
| | | pDC->SetBkMode(TRANSPARENT); |
| | | pDC->SetTextColor(txt); |
| | | CString txt0 = n->cols.empty() ? _T("") : n->cols[0]; |
| | | pDC->DrawText(txt0, textRc, DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_END_ELLIPSIS); |
| | | |
| | | if (GetExtendedStyle() & LVS_EX_GRIDLINES) |
| | | { |
| | | CRect rcRow; GetSubItemRect(row, 0, LVIR_BOUNDS, rcRow); |
| | | const int y = rcRow.bottom - 1; |
| | | CPen pen(PS_SOLID, 1, GetSysColor(COLOR_3DLIGHT)); |
| | | CPen* oldPen = pDC->SelectObject(&pen); |
| | | pDC->MoveTo(rcRow.left, y); |
| | | pDC->LineTo(rcRow.right, y); |
| | | pDC->SelectObject(oldPen); |
| | | } |
| | | |
| | | *pResult = CDRF_SKIPDEFAULT; |
| | | return; |
| | | } |
| | | |
| | | } |
| | | |
| | | *pResult = CDRF_DODEFAULT; |
| | | } |
| | | |
| | | // å
¼å®¹è¡ä¸ºï¼åæ¥ SetItemText å° Node->colsï¼ç»´æ¤è¡å·é¢è²æ°ç»çæå
¥/å é¤ |
| | | LRESULT CExpandableListCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) |
| | | { |
| | | // 忥 SetItemText å° Nodeï¼A/W å
¼å®¹ï¼ |
| | | if (message == LVM_SETITEMTEXT |
| | | #ifdef LVM_SETITEMTEXTA |
| | | || message == LVM_SETITEMTEXTA |
| | | #endif |
| | | #ifdef LVM_SETITEMTEXTW |
| | | || message == LVM_SETITEMTEXTW |
| | | #endif |
| | | ) |
| | | { |
| | | int row = static_cast<int>(wParam); |
| | | LVITEM* p = reinterpret_cast<LVITEM*>(lParam); |
| | | if (p) { |
| | | Node* n = GetNodeByVisibleIndex(row); |
| | | if (n) { |
| | | int sub = p->iSubItem; |
| | | if (sub >= (int)n->cols.size()) |
| | | n->cols.resize(sub + 1); |
| | | CString newText = p->pszText ? p->pszText : _T(""); |
| | | n->cols[sub] = newText; |
| | | } |
| | | } |
| | | // ç»§ç»äº¤ç»åºç±»å¤ç |
| | | } |
| | | |
| | | LRESULT nRet = CListCtrl::WindowProc(message, wParam, lParam); |
| | | |
| | | // ç»´æ¤è¡å·é¢è²æ°ç»ï¼å
¼å®¹æ§ SetItemColorï¼ |
| | | if (message == LVM_INSERTITEM) { |
| | | if (nRet != -1) { |
| | | LVITEM* p = (LVITEM*)lParam; |
| | | int pos = p ? p->iItem : (int)nRet; |
| | | if (pos < 0) pos = (int)nRet; |
| | | if (pos > (int)m_rowColors.size()) pos = (int)m_rowColors.size(); |
| | | m_rowColors.insert(m_rowColors.begin() + pos, RowColor{}); // é»è®¤è² |
| | | } |
| | | } |
| | | else if (message == LVM_DELETEITEM) { |
| | | if (nRet != 0) { |
| | | int pos = (int)wParam; |
| | | if (pos >= 0 && pos < (int)m_rowColors.size()) |
| | | m_rowColors.erase(m_rowColors.begin() + pos); |
| | | } |
| | | } |
| | | else if (message == LVM_DELETEALLITEMS) { |
| | | if (nRet != 0) { |
| | | m_rowColors.clear(); |
| | | } |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | | |
| | | // CExpandableListCtrl.cpp é |
| | | void CExpandableListCtrl::ClearTree() |
| | | { |
| | | // æ¸
æ°æ® |
| | | m_roots.clear(); |
| | | m_visible.clear(); |
| | | |
| | | // æ¸
å¯è§é¡¹ï¼å¡å¿
ï¼å¦åæ§é¡µçè¡ä¼æ®çï¼ |
| | | SetRedraw(FALSE); |
| | | DeleteAllItems(); |
| | | SetRedraw(TRUE); |
| | | |
| | | Invalidate(); |
| | | } |
| | | |
| | | void CExpandableListCtrl::SetPopupFullTextColumns(const std::vector<int>& cols) |
| | | { |
| | | m_popupCols.clear(); |
| | | for (int c : cols) m_popupCols.insert(c); |
| | | } |
| | | |
| | | bool CExpandableListCtrl::_IsCellTruncated(int row, int col, const CString& text) const |
| | | { |
| | | if (text.IsEmpty()) return false; |
| | | |
| | | // åå
æ ¼æ¾ç¤ºåºå宽度 |
| | | CRect rcCell; |
| | | if (!const_cast<CExpandableListCtrl*>(this)->GetSubItemRect(row, col, LVIR_BOUNDS, rcCell)) |
| | | return false; |
| | | |
| | | // ç¨æ§ä»¶å使µéææ¬åç´ å®½ |
| | | CClientDC dc(const_cast<CExpandableListCtrl*>(this)); |
| | | CFont* pOld = dc.SelectObject(const_cast<CExpandableListCtrl*>(this)->GetFont()); |
| | | CSize sz = dc.GetTextExtent(text); |
| | | dc.SelectObject(pOld); |
| | | |
| | | const int kPadding = 8; // é¢çä¸ç¹è¾¹è·/çç¥å·ä½é |
| | | return sz.cx > (rcCell.Width() - kPadding); |
| | | } |
| | | |
| | | |
| | |
| | | #pragma once |
| | | #include <vector> |
| | | #include <memory> |
| | | #include <unordered_map> |
| | | #include <set> |
| | | |
| | | |
| | | // ===== èªå®ä¹éç¥ï¼ç¹å»éè¦å¼¹åºå
¨æçåå
æ ¼ ===== |
| | | #ifndef ELCN_SHOWFULLTEXT |
| | | #define ELCN_SHOWFULLTEXT (NM_FIRST - 201) |
| | | struct NMC_ELC_SHOWFULLTEXT { |
| | | NMHDR hdr; // hwndFrom / idFrom / code = ELCN_SHOWFULLTEXT |
| | | int iItem; // è¡ |
| | | int iSubItem; // åï¼0-basedï¼ |
| | | CString text; // 宿´ææ¬ |
| | | }; |
| | | #endif |
| | | |
| | | class CExpandableListCtrl : public CListCtrl |
| | | { |
| | |
| | | std::vector<CString> cols; // ååææ¬ |
| | | bool expanded = false; |
| | | int level = 0; // 缩è¿å±çº§ |
| | | |
| | | Node(int nCols = 1) : cols(nCols) {} |
| | | }; |
| | | |
| | | CExpandableListCtrl(); |
| | | virtual ~CExpandableListCtrl(); |
| | | |
| | | // æ°æ®æå»º |
| | | // ===== æ æ°æ®æå»ºï¼éè¦æå åè½æ¶ä½¿ç¨ï¼çº¯å¹³å表å¯å¿½ç¥ï¼ ===== |
| | | Node* InsertRoot(const std::vector<CString>& cols); |
| | | Node* InsertChild(Node* parent, const std::vector<CString>& cols); |
| | | |
| | | // å±å¼/æå |
| | | void Expand(Node* n); |
| | | void Collapse(Node* n); |
| | | void Toggle(Node* n); |
| | | |
| | | // å·æ°å¯è§å表 |
| | | void RebuildVisible(); |
| | | |
| | | // 便æ·ï¼éè¿å¯è§è¡å·å Node* |
| | | void Expand(Node* n); |
| | | void Collapse(Node* n); |
| | | void Toggle(Node* n); |
| | | void RebuildVisible(); |
| | | Node* GetNodeByVisibleIndex(int i) const; |
| | | |
| | | // ===== è¡é
è² API ===== |
| | | // A) æ Node* çè²ï¼ç¨äºæ /坿å åºæ¯ï¼ç´¢å¼ååä¸åå½±åï¼ |
| | | void SetNodeColor(Node* n, COLORREF text, COLORREF bk); |
| | | void ClearNodeColor(Node* n); |
| | | void ClearAllColors(); |
| | | |
| | | // B) å
¼å®¹æ§æ¥å£ï¼æâå¯è§è¡å·âçè²ï¼ä¸ä½ å½å页é¢ä»£ç ä¸è´ï¼ |
| | | void SetItemColor(DWORD_PTR iItem, COLORREF TextColor, COLORREF TextBkColor); // å
¼å®¹ ListCtrlEx |
| | | void SetItemColorByVisibleIndex(int row, COLORREF text, COLORREF bk); // åä¸å«å |
| | | |
| | | // éä¸è¡æ¯å¦ä½¿ç¨ç³»ç»é«äº®ï¼TRUEï¼é»è®¤ï¼ï¼ |
| | | // è¥ä¸º FALSEï¼åé䏿¶ä»æ¾ç¤ºèªå®ä¹é¢è² |
| | | void SetPreserveSelectionHighlight(BOOL b) { m_preserveSelHighlight = b; } |
| | | |
| | | // æ¸
餿 |
| | | void ClearTree(); |
| | | |
| | | // 设置åªäºåéè¦âè¢«æªæåéç¥ç¶çªå£æ¾ç¤ºå
¨æâï¼0-basedåå·ï¼ |
| | | void SetPopupFullTextColumns(const std::vector<int>& cols); |
| | | |
| | | std::set<int> m_popupCols; // éè¦éç¥çåéå |
| | | bool _IsCellTruncated(int row, int col, const CString& text) const; |
| | | |
| | | protected: |
| | | virtual void PreSubclassWindow(); |
| | | afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); |
| | | afx_msg void OnClick(NMHDR* pNMHDR, LRESULT* pResult); |
| | | afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult); |
| | | virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam) override; |
| | | DECLARE_MESSAGE_MAP() |
| | | |
| | | private: |
| | | void appendVisible(Node* n); |
| | | CRect expanderRectForRow(int row) const; // é¦åå±å¼æé®åºå |
| | | virtual void PreSubclassWindow(); |
| | | |
| | | protected: |
| | | // æ¶æ¯ |
| | | afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); |
| | | afx_msg void OnClick(NMHDR* pNMHDR, LRESULT* pResult); |
| | | afx_msg void OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult); |
| | | DECLARE_MESSAGE_MAP() |
| | | void computeColorsForRow(int row, COLORREF& outText, COLORREF& outBk) const; |
| | | |
| | | private: |
| | | std::vector<std::unique_ptr<Node>> m_roots; // é¡¶å±èç¹ |
| | |
| | | int m_expanderPadding = 6; // é¦åå
ä¾§è¾¹è· |
| | | int m_expanderSize = 10; // å°ä¸è§/æ¹åå¤§å° |
| | | int m_textGap = 6; |
| | | |
| | | struct RowColor { |
| | | COLORREF text = CLR_DEFAULT; |
| | | COLORREF bk = CLR_DEFAULT; |
| | | bool hasText = false; |
| | | bool hasBk = false; |
| | | }; |
| | | |
| | | // é¢è²ï¼ä¸¤è·¯æ¥æºï¼ä¼å
级ï¼Node* > è¡å·ï¼ |
| | | std::unordered_map<Node*, RowColor> m_colorByNode; // æ èç¹é¢è² |
| | | std::vector<RowColor> m_rowColors; // æå½åå¯è§è¡å·çé¢è²ï¼å
¼å®¹æ§ä»£ç ï¼ |
| | | |
| | | BOOL m_preserveSelHighlight = TRUE; // TRUE=é䏿¶ä¼å
ç³»ç»é«äº® |
| | | }; |
| | | |
| | | |
| | |
| | | void CFliper::initPins() |
| | | { |
| | | // å å
¥Pinåå§å代ç |
| | | LOGI("<CFliper>initPins"); |
| | | LOGD("<CFliper>initPins"); |
| | | addPin(SERVO::PinType::INPUT, _T("In")); |
| | | addPin(SERVO::PinType::OUTPUT, _T("Out1")); |
| | | addPin(SERVO::PinType::OUTPUT, _T("Out2")); |
| | |
| | | |
| | | if (m_pBuddy != nullptr) { |
| | | m_pBuddy->release(); |
| | | m_pBuddy = nullptr; |
| | | } |
| | | } |
| | | |
| | |
| | | return strText; |
| | | } |
| | | |
| | | MaterialsType CGlass::getType() |
| | | MaterialsType CGlass::getType() const |
| | | { |
| | | return m_type; |
| | | } |
| | |
| | | m_strID = pszID; |
| | | } |
| | | |
| | | std::string& CGlass::getID() |
| | | const std::string& CGlass::getID() const |
| | | { |
| | | return m_strID; |
| | | } |
| | |
| | | return m_pPath; |
| | | } |
| | | |
| | | CPath* CGlass::getPathWithEq(unsigned int nEqId, unsigned int nUnit) |
| | | std::string CGlass::getPathDescription() const |
| | | { |
| | | std::string strOut, strPath; |
| | | char szBuffer[256]; |
| | | |
| | | CPath* pTemp = m_pPath; |
| | | while (pTemp != nullptr) { |
| | | pTemp->getSimpleDescription(strPath); |
| | | if (strPath.compare("ARM1") != 0 && strPath.compare("ARM2") != 0) { |
| | | if (!strOut.empty()) strOut.append(" -> "); |
| | | strOut.append(strPath); |
| | | } |
| | | |
| | | pTemp = pTemp->getNext(); |
| | | } |
| | | |
| | | return strOut; |
| | | } |
| | | |
| | | CPath* CGlass::getPathWithEq(unsigned int nEqId, unsigned int nUnit) const |
| | | { |
| | | CPath* pTemp = m_pPath; |
| | | while (pTemp != nullptr) { |
| | |
| | | return nullptr; |
| | | } |
| | | |
| | | void CGlass::addPath(unsigned int nEqId, unsigned int nUnit) |
| | | void CGlass::addPath(unsigned int nEqId, unsigned int nUnit, unsigned int slot) |
| | | { |
| | | CPath* pPath = new CPath(nEqId, nUnit); |
| | | CPath* pPath = new CPath(nEqId, nUnit, slot); |
| | | if (m_pPath == nullptr) { |
| | | m_pPath = pPath; |
| | | } |
| | |
| | | return m_pBuddy; |
| | | } |
| | | |
| | | std::string& CGlass::getBuddyId() |
| | | const std::string& CGlass::getBuddyId() const |
| | | { |
| | | return m_strBuddyId; |
| | | } |
| | | |
| | | void CGlass::setBuddyId(std::string& strId) |
| | | { |
| | | m_strBuddyId = strId; |
| | | } |
| | | |
| | | int CGlass::processEnd(unsigned int nEqId, unsigned int nUnit) |
| | |
| | | return 0; |
| | | } |
| | | |
| | | InspResult CGlass::getInspResult(unsigned int nEqId, unsigned int nUnit) |
| | | InspResult CGlass::getInspResult(unsigned int nEqId, unsigned int nUnit) const |
| | | { |
| | | CPath* pPath = getPathWithEq(nEqId, nUnit); |
| | | if (pPath == nullptr) return InspResult::NotInspected; |
| | | |
| | | return pPath->getInspResult(); |
| | | } |
| | | |
| | | InspResult CGlass::getAOIInspResult() const |
| | | { |
| | | return getInspResult(EQ_ID_MEASUREMENT, 0); |
| | | } |
| | | |
| | | std::string CGlass::getStateText() |
| | |
| | | |
| | | void CGlass::markStart() |
| | | { |
| | | m_state = GlsState::InProcess; |
| | | m_tStart = std::chrono::system_clock::now(); |
| | | } |
| | | |
| | | void CGlass::markEnd() |
| | | { |
| | | m_state = GlsState::Completed; |
| | | m_tEnd = std::chrono::system_clock::now(); |
| | | } |
| | | |
| | |
| | | { |
| | | return m_params; |
| | | } |
| | | |
| | | std::string CGlass::getParamsDescription() const |
| | | { |
| | | std::string strOut; |
| | | |
| | | char szBuffer[256]; |
| | | for (auto p : m_params) { |
| | | if (!strOut.empty()) strOut.append(","); |
| | | if (p.getValueType() == PVT_INT) { |
| | | sprintf_s(szBuffer, 256, "%s:%d", p.getName().c_str(), p.getIntValue()); |
| | | } |
| | | else if (p.getValueType() == PVT_DOUBLE) { |
| | | sprintf_s(szBuffer, 256, "%s:%f", p.getName().c_str(), p.getDoubleValue()); |
| | | } |
| | | strOut.append(szBuffer); |
| | | } |
| | | |
| | | return strOut; |
| | | } |
| | | } |
| | |
| | | public: |
| | | virtual std::string& getClassName(); |
| | | virtual std::string toString(); |
| | | short getCassetteSequenceNo() { return m_jobDataS.getCassetteSequenceNo(); } |
| | | short getJobSequenceNo() { return m_jobDataS.getJobSequenceNo(); } |
| | | MaterialsType getType(); |
| | | short getCassetteSequenceNo() const { return m_jobDataS.getCassetteSequenceNo(); } |
| | | short getJobSequenceNo() const { return m_jobDataS.getJobSequenceNo(); } |
| | | MaterialsType getType() const; |
| | | void setType(MaterialsType type); |
| | | void setID(const char* pszID); |
| | | std::string& getID(); |
| | | const std::string& getID() const; |
| | | void setOriginPort(int port, int slot); |
| | | void getOrginPort(int& port, int& slot); |
| | | BOOL isScheduledForProcessing(); |
| | | void setScheduledForProcessing(BOOL bProcessing); |
| | | CProcessJob* getProcessJob(); |
| | | void setProcessJob(CProcessJob* pProcessJob); |
| | | CPath* getPathWithEq(unsigned int nEqId, unsigned int nUnit); |
| | | CPath* getPathWithEq(unsigned int nEqId, unsigned int nUnit) const; |
| | | CPath* getPath(); |
| | | void addPath(unsigned int nEqId, unsigned int nUnit); |
| | | void addPath(unsigned int nEqId, unsigned int nUnit, unsigned int slot); |
| | | std::string getPathDescription() const; |
| | | std::string getParamsDescription() const; |
| | | void serialize(CArchive& ar); |
| | | void setJobDataS(CJobDataS* pJobDataS); |
| | | void updateJobDataS(CJobDataS* pJobDataS); |
| | |
| | | BOOL setBuddy(CGlass* pGlass); |
| | | BOOL forceSetBuddy(CGlass* pGlass); |
| | | CGlass* getBuddy(); |
| | | std::string& getBuddyId(); |
| | | const std::string& getBuddyId() const; |
| | | void setBuddyId(std::string& strId); |
| | | int processEnd(unsigned int nEqId, unsigned int nUnit); |
| | | BOOL isProcessed(unsigned int nEqId, unsigned int nUnit); |
| | | int setInspResult(unsigned int nEqId, unsigned int nUnit, InspResult result); |
| | | InspResult getInspResult(unsigned int nEqId, unsigned int nUnit); |
| | | InspResult getInspResult(unsigned int nEqId, unsigned int nUnit) const; |
| | | InspResult getAOIInspResult() const; |
| | | |
| | | public: |
| | | // æ°å¢ç¶æ |
| | |
| | | m_pOwner = pOwner; |
| | | } |
| | | |
| | | int CJobDataS::getCassetteSequenceNo() |
| | | int CJobDataS::getCassetteSequenceNo() const |
| | | { |
| | | return m_nCassetteSequenceNo; |
| | | } |
| | |
| | | m_nCassetteSequenceNo = no; |
| | | } |
| | | |
| | | int CJobDataS::getJobSequenceNo() |
| | | int CJobDataS::getJobSequenceNo() const |
| | | { |
| | | return m_nJobSequenceNo; |
| | | } |
| | |
| | | void copy(CJobDataS* pScr); |
| | | void update(CJobDataS* pScr); |
| | | CJobDataB& getJobDataB(CJobDataB& jobDataB); |
| | | int getCassetteSequenceNo(); |
| | | int getCassetteSequenceNo() const; |
| | | void setCassetteSequenceNo(int no); |
| | | int getJobSequenceNo(); |
| | | int getJobSequenceNo() const; |
| | | void setJobSequenceNo(int no); |
| | | std::string& getLotId(); |
| | | void setLotId(const char* pszId); |
| | |
| | | void CLoadPort::initPins() |
| | | { |
| | | // å å
¥Pinåå§å代ç |
| | | LOGI("<CLoadPort>initPins"); |
| | | LOGD("<CLoadPort>initPins"); |
| | | addPin(SERVO::PinType::INPUT, _T("In")); |
| | | addPin(SERVO::PinType::OUTPUT, _T("Out")); |
| | | } |
| | |
| | | } |
| | | |
| | | return (m_nIndex + 1) * 1000 + m_nNextCassetteSequenceNo; |
| | | } |
| | | |
| | | int CLoadPort::getPortCassetteSnSeed() |
| | | { |
| | | return m_nNextCassetteSequenceNo; |
| | | } |
| | | |
| | | void CLoadPort::setPortCassetteSnSeed(int seed) |
| | | { |
| | | m_nNextCassetteSequenceNo = seed; |
| | | if (m_nNextCassetteSequenceNo >= 1000) { |
| | | m_nNextCassetteSequenceNo = 0; |
| | | } |
| | | } |
| | | |
| | | void CLoadPort::setIndex(unsigned int index) |
| | |
| | | LOGI("<CLoadPort-%d>设置Port typeæå.", m_nIndex); |
| | | } |
| | | else { |
| | | LOGI("<CLoadPort-%d>设置Port type失败ï¼code:%d", m_nIndex, code); |
| | | LOGE("<CLoadPort-%d>设置Port type失败ï¼code:%d", m_nIndex, code); |
| | | } |
| | | if (onWritedBlock != nullptr) { |
| | | return onWritedBlock(code); |
| | |
| | | LOGI("<CLoadPort-%d>%s Portæå.", m_nIndex, bEnable ? _T("å¯ç¨") : _T("ç¦ç¨")); |
| | | } |
| | | else { |
| | | LOGI("<CLoadPort-%d>%s Port失败ï¼code:%d", m_nIndex, bEnable ? _T("å¯ç¨") : _T("ç¦ç¨"), code); |
| | | LOGE("<CLoadPort-%d>%s Port失败ï¼code:%d", m_nIndex, bEnable ? _T("å¯ç¨") : _T("ç¦ç¨"), code); |
| | | } |
| | | if (onWritedBlock != nullptr) { |
| | | return onWritedBlock(code); |
| | |
| | | LOGI("<CLoadPort-%d>设置Port modeæå.", m_nIndex); |
| | | } |
| | | else { |
| | | LOGI("<CLoadPort-%d>设置Port mode失败ï¼code:%d", m_nIndex, code); |
| | | LOGE("<CLoadPort-%d>设置Port mode失败ï¼code:%d", m_nIndex, code); |
| | | } |
| | | if (onWritedBlock != nullptr) { |
| | | return onWritedBlock(code); |
| | |
| | | LOGI("<CLoadPort-%d>设置Cassette Typeæå.", m_nIndex); |
| | | } |
| | | else { |
| | | LOGI("<CLoadPort-%d>设置Cassette Type失败ï¼code:%d", m_nIndex, code); |
| | | LOGE("<CLoadPort-%d>设置Cassette Type失败ï¼code:%d", m_nIndex, code); |
| | | } |
| | | if (onWritedBlock != nullptr) { |
| | | return onWritedBlock(code); |
| | |
| | | LOGI("<CLoadPort-%d>设置Transfer modeæå.", m_nIndex + 1); |
| | | } |
| | | else { |
| | | LOGI("<CLoadPort-%d>设置Transfer mode失败ï¼code:%d", m_nIndex + 1, code); |
| | | LOGE("<CLoadPort-%d>设置Transfer mode失败ï¼code:%d", m_nIndex + 1, code); |
| | | } |
| | | if (onWritedBlock != nullptr) { |
| | | return onWritedBlock(code); |
| | |
| | | LOGI("<CLoadPort-%d>%s Auto Changeæå.", m_nIndex, bEnable ? _T("å¯ç¨") : _T("ç¦ç¨")); |
| | | } |
| | | else { |
| | | LOGI("<CLoadPort-%d>%s Auto Change失败ï¼code:%d", m_nIndex, bEnable ? _T("å¯ç¨") : _T("ç¦ç¨"), code); |
| | | LOGE("<CLoadPort-%d>%s Auto Change失败ï¼code:%d", m_nIndex, bEnable ? _T("å¯ç¨") : _T("ç¦ç¨"), code); |
| | | } |
| | | if (onWritedBlock != nullptr) { |
| | | return onWritedBlock(code); |
| | |
| | | |
| | | CGlass* pGlass = theApp.m_model.m_glassPool.allocaGlass(); |
| | | pGlass->setOriginPort(m_nIndex, i); |
| | | pGlass->addPath(m_nID, 0); |
| | | pGlass->addPath(m_nID, 0, i + 1); |
| | | pGlass->processEnd(m_nID, 0); |
| | | pGlass->setID(szBuffer); |
| | | pGlass->setType(type); |
| | |
| | | CGlass* pGlass = theApp.m_model.m_glassPool.allocaGlass(); |
| | | pGlass->setOriginPort(m_nIndex, i); |
| | | pGlass->setScheduledForProcessing(i % 2 == 1); |
| | | pGlass->addPath(m_nID, 0); |
| | | pGlass->addPath(m_nID, 0, i + 1); |
| | | pGlass->processEnd(m_nID, 0); |
| | | pGlass->setID(szBuffer); |
| | | pGlass->setType(m_cassetteType); |
| | |
| | | |
| | | CGlass* pGlass = theApp.m_model.m_glassPool.allocaGlass(); |
| | | pGlass->setOriginPort(m_nIndex, nSlotIndex); |
| | | pGlass->addPath(m_nID, 0); |
| | | pGlass->addPath(m_nID, 0, slot.nSlotID); |
| | | pGlass->processEnd(m_nID, 0); |
| | | pGlass->setID(szBuffer); |
| | | pGlass->setType(static_cast<SERVO::MaterialsType>(config.nMaterialType)); |
| | |
| | | |
| | | public: |
| | | short getNextCassetteSequenceNo(); |
| | | int getPortCassetteSnSeed(); |
| | | void setPortCassetteSnSeed(int seed); |
| | | void setIndex(unsigned int index); |
| | | unsigned int getIndex(); |
| | | BOOL isEnable(); |
| | |
| | | m_ullRunTime = 0; |
| | | m_state = MASTERSTATE::READY; |
| | | m_pActiveRobotTask = nullptr; |
| | | m_nLastError = 0; |
| | | m_nLastError = ER_CODE_NOERROR; |
| | | m_isCompareMapsBeforeProceeding = FALSE; |
| | | m_bJobMode = FALSE; |
| | | m_bEnableEventReport = true; |
| | |
| | | BoardVersion version{}; |
| | | int nRet = m_cclink.GetBoardVersion(version); |
| | | if (nRet == 0) { |
| | | LOGI("çæ¬ä¿¡æ¯ï¼%s.", version.toString().c_str()); |
| | | LOGD("çæ¬ä¿¡æ¯ï¼%s.", version.toString().c_str()); |
| | | } |
| | | else { |
| | | LOGE("è·åCC-Linkçæ¬ä¿¡æ¯å¤±è´¥."); |
| | |
| | | BoardStatus status; |
| | | nRet = m_cclink.GetBoardStatus(status); |
| | | if (nRet == 0) { |
| | | LOGI("ç¶æï¼%s.", status.toString().c_str()); |
| | | LOGD("ç¶æï¼%s.", status.toString().c_str()); |
| | | } |
| | | else { |
| | | LOGE("è·åCC-Linkç¶æå¤±è´¥."); |
| | |
| | | return 0; |
| | | } |
| | | |
| | | int CMaster::stop() |
| | | int CMaster::stop(int nErCode/* = ER_CODE_NOERROR*/) |
| | | { |
| | | // è¿è¡æ¶é´ä¸ºç´¯å ç»æï¼æ¬æ¬¡åæ¢æ¶å·æ°ï¼ |
| | | lock(); |
| | |
| | | |
| | | |
| | | // æ´æ°ç¶æ |
| | | m_nLastError = nErCode; |
| | | setState(MASTERSTATE::STOPPING); |
| | | |
| | | |
| | |
| | | TRACE("a0001\n", writeCode, retCode); |
| | | }); |
| | | if (nRet != 0) { |
| | | LOGI("<Master>EFEM忢Startç¶æå¤±è´¥"); |
| | | LOGE("<Master>EFEM忢Startç¶æå¤±è´¥"); |
| | | m_nLastError = ER_CODE_OPERATION_MODE_FAIL; |
| | | m_strLastError = "EFEM忢Startç¶æå¤±è´¥."; |
| | | goto WAIT; |
| | | } |
| | |
| | | TRACE("a0002\n"); |
| | | }); |
| | | if (nRet != 0) { |
| | | LOGI("<Master>Bonder1忢Startç¶æå¤±è´¥"); |
| | | LOGE("<Master>Bonder1忢Startç¶æå¤±è´¥"); |
| | | m_nLastError = ER_CODE_BONDER_OPERATION_MODE_FAIL; |
| | | m_strLastError = "Bonder1忢Startç¶æå¤±è´¥."; |
| | | goto WAIT; |
| | | } |
| | |
| | | TRACE("a0003\n"); |
| | | }); |
| | | if (nRet != 0) { |
| | | LOGI("<Master>Bonder2忢Startç¶æå¤±è´¥"); |
| | | LOGE("<Master>Bonder2忢Startç¶æå¤±è´¥"); |
| | | m_nLastError = ER_CODE_BONDER_OPERATION_MODE_FAIL; |
| | | m_strLastError = "Bonder2忢Startç¶æå¤±è´¥."; |
| | | goto WAIT; |
| | | } |
| | |
| | | TRACE("a0004\n"); |
| | | }); |
| | | if (nRet != 0) { |
| | | LOGI("<Master>BakeCooling忢Startç¶æå¤±è´¥"); |
| | | LOGE("<Master>BakeCooling忢Startç¶æå¤±è´¥"); |
| | | m_nLastError = ER_CODE_OPERATION_MODE_FAIL; |
| | | m_strLastError = "BakeCooling忢Startç¶æå¤±è´¥."; |
| | | goto WAIT; |
| | | } |
| | |
| | | TRACE("a0005\n"); |
| | | }); |
| | | if (nRet != 0) { |
| | | LOGI("<Master>VacuumBake忢Startç¶æå¤±è´¥"); |
| | | LOGE("<Master>VacuumBake忢Startç¶æå¤±è´¥"); |
| | | m_nLastError = ER_CODE_OPERATION_MODE_FAIL; |
| | | m_strLastError = "VacuumBake忢Startç¶æå¤±è´¥."; |
| | | goto WAIT; |
| | | } |
| | |
| | | TRACE("a0006\n"); |
| | | }); |
| | | if (nRet != 0) { |
| | | LOGI("<Master>Measurement忢Startç¶æå¤±è´¥"); |
| | | LOGE("<Master>Measurement忢Startç¶æå¤±è´¥"); |
| | | m_nLastError = ER_CODE_OPERATION_MODE_FAIL; |
| | | m_strLastError = "Measurement忢Startç¶æå¤±è´¥."; |
| | | goto WAIT; |
| | | } |
| | |
| | | for (int i = 0; i < 6; i++) { |
| | | if (!bIomcOk[i]) { |
| | | bIomcOk[6] = FALSE; |
| | | LOGI("<Master>%s忢Startç¶æå¤±è´¥", pEq[i]->getName().c_str()); |
| | | LOGE("<Master>%s忢Startç¶æå¤±è´¥", pEq[i]->getName().c_str()); |
| | | } |
| | | } |
| | | |
| | |
| | | TRACE("s000%d: ret=%d\n", i + 1, retCode); |
| | | }); |
| | | if (nRet != 0) { |
| | | LOGI("<Master>%s忢Stopç¶æåé失败", pEq[i]->getName().c_str()); |
| | | LOGE("<Master>%s忢Stopç¶æåé失败", pEq[i]->getName().c_str()); |
| | | m_nLastError = ER_CODE_OPERATION_MODE_FAIL; |
| | | m_strLastError = pEq[i]->getName() + "忢Stopç¶æåé失败."; |
| | | bIomcOk[i] = FALSE; |
| | | promises[i].set_value(); // é¿å
wait é»å¡ |
| | |
| | | for (int i = 0; i < 6; ++i) { |
| | | if (!bIomcOk[i]) { |
| | | bIomcOk[6] = FALSE; |
| | | LOGI("<Master>%s忢Stopç¶æå¤±è´¥", pEq[i]->getName().c_str()); |
| | | LOGE("<Master>%s忢Stopç¶æå¤±è´¥", pEq[i]->getName().c_str()); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | LOGI("<Master>ææè®¾å¤æååæ¢å° Stop 模å¼"); |
| | | setState(MASTERSTATE::READY); |
| | | if(m_nLastError == ER_CODE_NOERROR) |
| | | setState(MASTERSTATE::READY); |
| | | else |
| | | setState(MASTERSTATE::ATHERERROR); |
| | | |
| | | continue; |
| | | } |
| | | |
| | |
| | | |
| | | if (!rmd.armState[0]) { |
| | | // m_nTestFlag = 1; |
| | | if (m_nTestFlag == 1) LOGI("createTransferTask 004df %d, %d", MaterialsType::G1, secondaryType); |
| | | if (m_nTestFlag == 1) LOGD("createTransferTask 004df %d, %d", MaterialsType::G1, secondaryType); |
| | | m_pActiveRobotTask = createTransferTask(pAligner, pVacuumBake, MaterialsType::G1, secondaryType); |
| | | CHECK_RUN_ACTIVE_ROBOT_TASK(m_pActiveRobotTask); |
| | | m_nTestFlag = 0; |
| | |
| | | continue; |
| | | } |
| | | |
| | | pGlass->queue(); |
| | | pGlass->start(); |
| | | pEFEM->setContext(m_pActiveRobotTask->getContext()); |
| | | goto PORT_GET; |
| | | } |
| | |
| | | CJState state = m_pControlJob->state(); |
| | | if (state == CJState::Completed || state == CJState::Aborted || state == CJState::Failed) { |
| | | // ConrolJpb已宿 |
| | | LOGI("<Master>ControlJobå·²ç»å®ææå¤±è´¥ä¸æ"); |
| | | LOGE("<Master>ControlJobå·²ç»å®ææå¤±è´¥ä¸æ"); |
| | | unlock(); |
| | | continue; |
| | | } |
| | |
| | | } |
| | | } |
| | | if (m_inProcesJobs.empty()) { |
| | | LOGI("<Master>éæ©å½åProcessJob失败ï¼"); |
| | | LOGE("<Master>éæ©å½åProcessJob失败ï¼"); |
| | | unlock(); |
| | | continue; |
| | | } |
| | |
| | | |
| | | // Measurement -> LoadPort |
| | | if (rmd.armState[0] || rmd.armState[1]) { |
| | | LOGI("Arm1 %s, Arm2 %s.", rmd.armState[0] ? _T("ä¸å¯ç¨") : _T("å¯ç¨"), |
| | | LOGD("Arm1 %s, Arm2 %s.", rmd.armState[0] ? _T("ä¸å¯ç¨") : _T("å¯ç¨"), |
| | | rmd.armState[1] ? _T("ä¸å¯ç¨") : _T("å¯ç¨")); |
| | | } |
| | | for (int s = 0; s < 4; s++) { |
| | |
| | | BOOL bOk = FALSE; |
| | | lock(); |
| | | if (m_pActiveRobotTask != nullptr) { |
| | | LOGI("<CMaster>onPreFethedOutJob 0001."); |
| | | LOGD("<CMaster>onPreFethedOutJob 0001."); |
| | | if (m_pActiveRobotTask->getSrcPosition() == p->getID()) { |
| | | LOGI("<CMaster>onPreFethedOutJob 0002."); |
| | | LOGD("<CMaster>onPreFethedOutJob 0002."); |
| | | CGlass* pGlass = p->getGlassFromSlot(m_pActiveRobotTask->getSrcSlot()); |
| | | if (pGlass != nullptr) { |
| | | LOGI("<CMaster>onPreFethedOutJob 0003."); |
| | | LOGD("<CMaster>onPreFethedOutJob 0003."); |
| | | CJobDataS* pJobDataS = pGlass->getJobDataS(); |
| | | if (pJobDataS != nullptr |
| | | && pJobDataS->getCassetteSequenceNo() == pJobDataB->getCassetteSequenceNo() |
| | | && pJobDataS->getJobSequenceNo() == pJobDataB->getJobSequenceNo()) { |
| | | bOk = TRUE; |
| | | LOGI("<CMaster>onPreFethedOutJob, å·²æ ¡éªæ°æ®ä¸è´æ§."); |
| | | LOGD("<CMaster>onPreFethedOutJob, å·²æ ¡éªæ°æ®ä¸è´æ§."); |
| | | } |
| | | LOGI("<CMaster>onPreFethedOutJob 0004."); |
| | | LOGD("<CMaster>onPreFethedOutJob 0004."); |
| | | if (pJobDataS != nullptr) { |
| | | LOGI("<CMaster>onPreFethedOutJob 0005. %d,%d,%d,%d", |
| | | LOGD("<CMaster>onPreFethedOutJob 0005. %d,%d,%d,%d", |
| | | pJobDataS->getCassetteSequenceNo(), |
| | | pJobDataB->getCassetteSequenceNo(), |
| | | pJobDataS->getJobSequenceNo(), |
| | |
| | | if (m_pActiveRobotTask->getSrcPosition() == EQ_ID_MEASUREMENT) { |
| | | CGlass* pGlass = (CGlass*)m_pActiveRobotTask->getContext(); |
| | | pGlass->complete(); |
| | | CGlass* pBuddy = pGlass->getBuddy(); |
| | | if (pBuddy != nullptr) pBuddy->complete(); |
| | | this->saveState(); |
| | | bool bMoved = glassFromInPorcessToComplete(pGlass); |
| | | if (bMoved) { |
| | |
| | | } |
| | | strOut.append(szBuffer); |
| | | } |
| | | LOGI("<CMaster-%s>SVDataReport:%s", ((CEquipment*)pEquipment)->getName().c_str(), strOut.c_str()); |
| | | LOGD("<CMaster-%s>SVDataReport:%s", ((CEquipment*)pEquipment)->getName().c_str(), strOut.c_str()); |
| | | }; |
| | | listener.onPanelDataReport = [&](void* pEquipment, void* pContext) { |
| | | LOGD("<CMaster-%s>onPanelDataReport", ((CEquipment*)pEquipment)->getName().c_str()); |
| | | |
| | | CEquipment* pEq = (CEquipment*)pEquipment; |
| | | CGlass* pGlass = (CGlass*)pContext; |
| | | |
| | | // 妿AOIæ£æµå¤±è´¥ï¼è¦åæº |
| | | if (pEq->getID() == EQ_ID_MEASUREMENT) { |
| | | LOGD("<CMaster-%s>onPanelDataReport 01", ((CEquipment*)pEquipment)->getName().c_str()); |
| | | if (pGlass->getAOIInspResult() == InspResult::Fail) { |
| | | LOGD("<CMaster-%s>onPanelDataReport 02", ((CEquipment*)pEquipment)->getName().c_str()); |
| | | if (stop() == 0) { |
| | | m_nLastError = ER_CODE_AOI_NG; |
| | | m_strLastError = "AOIæ£æµæªéè¿."; |
| | | } |
| | | } |
| | | } |
| | | |
| | | }; |
| | | pEquipment->setListener(listener); |
| | | pEquipment->setCcLink(&m_cclink); |
| | |
| | | if (!m_inProcesGlasses.empty()) { |
| | | CGlass* pGlass = m_inProcesGlasses.front(); |
| | | pGlass->complete(); |
| | | CGlass* pBuddy = pGlass->getBuddy(); |
| | | if (pBuddy != nullptr) pBuddy->complete(); |
| | | glassFromInPorcessToComplete(pGlass); |
| | | this->saveState(); |
| | | |
| | |
| | | pSrcEq->m_nTestFlag = m_nTestFlag; |
| | | pTarSlot = pTarEq->getAvailableSlotForGlass(primaryType); |
| | | pSrcSlot = pSrcEq->getProcessedSlot(primaryType, bJobMode); |
| | | if (m_nTestFlag == 1) LOGI("createTransferTask 003 %x, %x", pTarSlot, pSrcSlot); |
| | | if (m_nTestFlag == 1) LOGD("createTransferTask 003 %x, %x", pTarSlot, pSrcSlot); |
| | | if (pSrcSlot == nullptr || nullptr == pTarSlot && secondaryType != SERVO::MaterialsType::G0) { |
| | | pTarSlot = pTarEq->getAvailableSlotForGlass(secondaryType); |
| | | pSrcSlot = pSrcEq->getProcessedSlot(secondaryType, bJobMode); |
| | | } |
| | | if (m_nTestFlag == 1) LOGI("createTransferTask 004 %x, %x", pTarSlot, pSrcSlot); |
| | | if (m_nTestFlag == 1) LOGD("createTransferTask 004 %x, %x", pTarSlot, pSrcSlot); |
| | | |
| | | if (pSrcSlot != nullptr && nullptr != pTarSlot) { |
| | | pTask = new CRobotTask(); |
| | |
| | | int eqid[] = { EQ_ID_LOADPORT1, EQ_ID_LOADPORT2, EQ_ID_LOADPORT3, EQ_ID_LOADPORT4 }; |
| | | CLoadPort* pPort = (CLoadPort*)getEquipment(eqid[index]); |
| | | pPort->localEanblePort(bEnable); |
| | | } |
| | | |
| | | int CMaster::getPortCassetteSnSeed(int port) |
| | | { |
| | | ASSERT(1 <= port && port <= 4); |
| | | int eqid[] = { EQ_ID_LOADPORT1, EQ_ID_LOADPORT2, EQ_ID_LOADPORT3, EQ_ID_LOADPORT4 }; |
| | | CLoadPort* pPort = (CLoadPort*)getEquipment(eqid[port - 1]); |
| | | return pPort->getPortCassetteSnSeed(); |
| | | } |
| | | |
| | | void CMaster::setPortCassetteSnSeed(int port, int seed) |
| | | { |
| | | ASSERT(1 <= port && port <= 4); |
| | | int eqid[] = { EQ_ID_LOADPORT1, EQ_ID_LOADPORT2, EQ_ID_LOADPORT3, EQ_ID_LOADPORT4 }; |
| | | CLoadPort* pPort = (CLoadPort*)getEquipment(eqid[port - 1]); |
| | | return pPort->setPortCassetteSnSeed(seed); |
| | | } |
| | | |
| | | void CMaster::setCompareMapsBeforeProceeding(BOOL bCompare) |
| | |
| | | |
| | | return nullptr; |
| | | } |
| | | |
| | | int CMaster::getWipGlasses(std::vector<CGlass*>& glasses) |
| | | { |
| | | for (auto eq : m_listEquipment) { |
| | | auto p = dynamic_cast<CLoadPort*>(eq); |
| | | if (p == nullptr) { |
| | | eq->getAllGlass(glasses); |
| | | } |
| | | |
| | | } |
| | | |
| | | return (int)glasses.size(); |
| | | } |
| | | |
| | | int CMaster::getLastError() |
| | | { |
| | | return m_nLastError; |
| | | } |
| | | |
| | | std::string& CMaster::getLastErrorText() |
| | | { |
| | | return m_strLastError; |
| | | } |
| | | |
| | | void CMaster::test() |
| | | { |
| | | if (stop() == 0) { |
| | | m_nLastError = ER_CODE_AOI_NG; |
| | | m_strLastError = "AOIæ£æµæªéè¿."; |
| | | } |
| | | } |
| | | } |
| | |
| | | #define CTStep_begin CTStep_LoadPort_Aligner |
| | | #define CTStep_end CTStep_Measurement_LoadPort |
| | | |
| | | #define ER_CODE_NOERROR 0 |
| | | #define ER_CODE_OPERATION_MODE_FAIL -1 |
| | | #define ER_CODE_AOI_NG -2 |
| | | |
| | | namespace SERVO { |
| | | enum class MASTERSTATE { |
| | | READY = 0, |
| | |
| | | RUNNING_CONTINUOUS_TRANSFER, |
| | | RUNNING_BATCH, |
| | | STOPPING, |
| | | MSERROR |
| | | MSERROR, |
| | | ATHERERROR |
| | | }; |
| | | |
| | | typedef std::function<void(void* pMaster, MASTERSTATE state)> ONMASTERSTATECHANGED; |
| | |
| | | int start(); |
| | | int startContinuousTransfer(); |
| | | int startBatch(); |
| | | int stop(); |
| | | int stop(int nErCode = ER_CODE_NOERROR); |
| | | void clearError(); |
| | | ULONGLONG getRunTime(); |
| | | MASTERSTATE getState(); |
| | |
| | | CLoadPort* getPortWithCarrierId(const std::string& carrierId) const; |
| | | bool saveState() const; |
| | | bool loadState(const std::string& path); |
| | | int getWipGlasses(std::vector<CGlass*>& glasses); |
| | | void test(); |
| | | int getPortCassetteSnSeed(int port); |
| | | void setPortCassetteSnSeed(int port, int seed); |
| | | |
| | | private: |
| | | inline void lock() { EnterCriticalSection(&m_criticalSection); } |
| | |
| | | bool ceidDefined(uint32_t ceid) const override; |
| | | |
| | | public: |
| | | int getLastError(); |
| | | std::string& getLastErrorText(); |
| | | |
| | | public: |
| | | // æ°å¢å½æ° |
| | | CProcessJob* acquireNextProcessJob(); |
| | | CGlass* acquireNextGlass(); |
| | |
| | | params.push_back(CParam("æ£æµé度", "", this->getName().c_str(), v * 0.001)); |
| | | i += 4; |
| | | |
| | | // 3.æ£æµé度 |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("æ£æµé度", "", this->getName().c_str(), v * 0.001)); |
| | | i += 4; |
| | | |
| | | // 4.æ£æµ2æ°æ® |
| | | v = (pszData[i] & 0xff) | (pszData[i + 1] & 0xff) << 8 | (pszData[i + 2] & 0xff) << 16 | (pszData[i + 3] & 0xff) << 24; |
| | | params.push_back(CParam("æ£æµé度", "", this->getName().c_str(), v * 0.001)); |
| | | i += 4; |
| | | |
| | | return (int)params.size(); |
| | | } |
| | | |
| | |
| | | LOGI("sendCassetteCtrlCmd æå."); |
| | | } |
| | | else { |
| | | LOGI("sendCassetteCtrlCmd 失败."); |
| | | LOGE("sendCassetteCtrlCmd 失败."); |
| | | } |
| | | |
| | | return 0; |
| | |
| | | #include "CPageGlassList.h" |
| | | #include "afxdialogex.h" |
| | | #include "GlassJson.h" |
| | | #include "CServoUtilsTool.h" |
| | | #include "ToolUnits.h" |
| | | |
| | | #include <optional> |
| | | #include <unordered_set> |
| | | #include <unordered_map> |
| | | #include <vector> |
| | | #include <string> |
| | | |
| | | #define PAGE_SIZE 50 |
| | | #define PAGE_BACKGROUND_COLOR RGB(252, 252, 255) |
| | | |
| | | // WIP é¢è²ï¼ç¶ï¼æ ¹/æ buddyï¼= åºç¡ç»¿ï¼åï¼buddyï¼= æ´æµ
|
| | | static const COLORREF kWipText = RGB(0, 0, 0); |
| | | static const COLORREF kWipParentBk = RGB(201, 228, 180); // åºç¡ç»¿ |
| | | static const COLORREF kWipChildBk = RGB(221, 241, 208); // æ´æµ
ä¸ç¹ |
| | | |
| | | // ===== æ¾å¨ CPageGlassList.cpp é¡¶é¨çå¿åå·¥å
·ï¼æä»¶å
éæï¼ ===== |
| | | // æå½åâå·²å±å¼âçç¶è¡ï¼ç¨å®ä»¬ç classIdï¼ç¬¬4åææ¬ï¼å key è®°å½ä¸æ¥ |
| | | static std::unordered_set<std::string> SnapshotExpandedKeys(CExpandableListCtrl& lv) { |
| | | std::unordered_set<std::string> keys; |
| | | for (int i = 0; i < lv.GetItemCount(); ++i) { |
| | | auto* n = lv.GetNodeByVisibleIndex(i); |
| | | if (!n || n->children.empty() || !n->expanded) continue; |
| | | if ((int)n->cols.size() > 4) { |
| | | #ifdef _UNICODE |
| | | keys.insert(CT2A(n->cols[4])); |
| | | #else |
| | | keys.insert(n->cols[4].GetString()); |
| | | #endif |
| | | } |
| | | } |
| | | return keys; |
| | | } |
| | | |
| | | // æ ¹æ®å¿«ç
§æ¢å¤å±å¼ç¶æï¼å¨ä½ æ°å»ºå®æ¯ä¸ªâç¶èç¹âæ¶è°ç¨ä¸æ¬¡ï¼ |
| | | static void MaybeRestoreExpandByKey(CExpandableListCtrl::Node* n, |
| | | const std::unordered_set<std::string>& keys) { |
| | | if (!n || (int)n->cols.size() <= 4) return; |
| | | #ifdef _UNICODE |
| | | std::string k = CT2A(n->cols[4]); |
| | | #else |
| | | std::string k = n->cols[4].GetString(); |
| | | #endif |
| | | if (keys.find(k) != keys.end()) |
| | | n->expanded = true; |
| | | } |
| | | |
| | | static void CaptureUiState(CExpandableListCtrl& lv, |
| | | std::vector<CExpandableListCtrl::Node*>& outSel, |
| | | CExpandableListCtrl::Node*& outTopNode) |
| | | { |
| | | outSel.clear(); outTopNode = nullptr; |
| | | const int top = lv.GetTopIndex(); |
| | | if (top >= 0 && top < lv.GetItemCount()) |
| | | outTopNode = lv.GetNodeByVisibleIndex(top); |
| | | for (int i = 0; i < lv.GetItemCount(); ++i) { |
| | | if ((lv.GetItemState(i, LVIS_SELECTED) & LVIS_SELECTED) != 0) { |
| | | auto* n = lv.GetNodeByVisibleIndex(i); |
| | | if (n) outSel.push_back(n); |
| | | } |
| | | } |
| | | } |
| | | static void RestoreUiState(CExpandableListCtrl& lv, |
| | | const std::vector<CExpandableListCtrl::Node*>& sel, |
| | | CExpandableListCtrl::Node* topNode) |
| | | { |
| | | // æ¸
æç°æéæ© |
| | | for (int i = 0; i < lv.GetItemCount(); ++i) |
| | | lv.SetItemState(i, 0, LVIS_SELECTED); |
| | | |
| | | // æ¢å¤éæ© |
| | | for (auto* n : sel) { |
| | | for (int i = 0; i < lv.GetItemCount(); ++i) { |
| | | if (lv.GetNodeByVisibleIndex(i) == n) { |
| | | lv.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | // å°½éæä¹åçé¡¶è¡æ»åå¯è§ |
| | | if (topNode) { |
| | | for (int i = 0; i < lv.GetItemCount(); ++i) { |
| | | if (lv.GetNodeByVisibleIndex(i) == topNode) { |
| | | lv.EnsureVisible(i, FALSE); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // ====== å¼å
³ï¼1=å¯ç¨åæ°æ®ï¼åªæ¿æ¢ DB æ¥è¯¢ï¼ï¼0=ç¨çå® DB ====== |
| | | #define USE_FAKE_DB_DEMO 0 |
| | | |
| | | #if USE_FAKE_DB_DEMO |
| | | #include <ctime> |
| | | #include <atlconv.h> // CStringA |
| | | #include <initializer_list> |
| | | #include <string> |
| | | #include <vector> |
| | | |
| | | // ---- 模æè®°å½/åé¡µç»æï¼å段ä¸ä½ ç°æä»£ç ä¸è´ï¼---- |
| | | struct FakeDbRecord { |
| | | int id; |
| | | int cassetteSeqNo; |
| | | int jobSeqNo; |
| | | std::string classId; |
| | | int materialType; |
| | | int state; |
| | | std::string tStart; |
| | | std::string tEnd; |
| | | std::string buddyId; |
| | | int aoiResult; |
| | | std::string path; |
| | | std::string params; |
| | | }; |
| | | struct FakeDbPage { std::vector<FakeDbRecord> items; }; |
| | | |
| | | // ---- CString -> std::stringï¼ANSIï¼æ¬å°ä»£ç 页ï¼ä»
ç¨äºæµè¯æ¨¡æï¼---- |
| | | static std::string toAnsi(const CString& s) { |
| | | #ifdef _UNICODE |
| | | CStringA a(s); |
| | | return std::string(a.GetString()); |
| | | #else |
| | | return std::string(s.GetString()); |
| | | #endif |
| | | } |
| | | |
| | | // ---- å®å
¨æ¼æ¥å·¥å
·ï¼ä¸ä½¿ç¨è¿ç®ç¬¦ +ï¼é¿å
éè½½/转æ¢é®é¢ï¼---- |
| | | static std::string sjoin(std::initializer_list<std::string> parts) { |
| | | std::string out; |
| | | size_t total = 0; for (const auto& p : parts) total += p.size(); |
| | | out.reserve(total); |
| | | for (const auto& p : parts) out.append(p); |
| | | return out; |
| | | } |
| | | |
| | | // ---- æ¶é´æ ¼å¼å·¥å
·ï¼now + days/minutes åç§» ---- |
| | | static std::string _fmt_time(int daysOff, int minutesOff) { |
| | | using namespace std::chrono; |
| | | auto now = system_clock::now() + hours(24 * daysOff) + minutes(minutesOff); |
| | | std::time_t tt = system_clock::to_time_t(now); |
| | | std::tm tm{}; |
| | | #ifdef _WIN32 |
| | | localtime_s(&tm, &tt); |
| | | #else |
| | | tm = *std::localtime(&tt); |
| | | #endif |
| | | char buf[32]; |
| | | std::snprintf(buf, sizeof(buf), "%04d-%02d-%02d %02d:%02d:%02d", |
| | | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); |
| | | return std::string(buf); |
| | | } |
| | | |
| | | // ---- é å
¨éåæ°æ®ï¼å«å页é
对/跨页é
对/åæ¡ï¼---- |
| | | static void _make_all_fake(std::vector<FakeDbRecord>& outAll) { |
| | | outAll.clear(); |
| | | int id = 1000; |
| | | |
| | | // ===== å
é å æ¡â没æ Buddyâçè®°å½ï¼ä¿è¯åºç°å¨ç¬¬ 1 页å¼å¤´ï¼===== |
| | | for (int n = 1; n <= 4; ++n) { |
| | | CString cid; cid.Format(_T("NB%03d"), n); |
| | | outAll.push_back(FakeDbRecord{ |
| | | id++, 700 + n, 800 + n, toAnsi(cid), |
| | | n % 3, n % 5, |
| | | _fmt_time(0, -n * 5), // å¼å§æ¶é´ç¨æ©ä¸ç¹ |
| | | _fmt_time(0, -n * 5 + 1), |
| | | std::string(), // buddyId 为空 |
| | | n % 4, |
| | | sjoin({ "path/", toAnsi(cid) }), |
| | | sjoin({ "{\"noBuddy\":", std::to_string(n), "}" }) |
| | | }); |
| | | } |
| | | |
| | | // ===== é é
å¯¹æ°æ®çå·¥å
· ===== |
| | | auto mkPair = [&](int k, bool crossPage) { |
| | | // äºä¸º buddy çä¸¤æ¡ |
| | | CString a; a.Format(_T("G%04dA"), k); |
| | | CString b; b.Format(_T("G%04dB"), k); |
| | | |
| | | FakeDbRecord A{ |
| | | id++, 100 + k, 200 + k, toAnsi(a), |
| | | k % 3, k % 5, _fmt_time(0, k * 3), _fmt_time(0, k * 3 + 2), |
| | | toAnsi(b), k % 4, |
| | | sjoin({ "path/", toAnsi(a) }), |
| | | sjoin({ "{\"k\":\"", toAnsi(a), "\"}" }) |
| | | }; |
| | | FakeDbRecord B{ |
| | | id++, 110 + k, 210 + k, toAnsi(b), |
| | | (k + 1) % 3, (k + 2) % 5, _fmt_time(0, k * 3 + 1), _fmt_time(0, k * 3 + 4), |
| | | toAnsi(a), (k + 1) % 4, |
| | | sjoin({ "path/", toAnsi(b) }), |
| | | sjoin({ "{\"k\":\"", toAnsi(b), "\"}" }) |
| | | }; |
| | | |
| | | if (crossPage) { |
| | | // å
æ¾ Aï¼åæ 3 æ¡âåæ¡âæ B æ¤å°åé¡µï¼æåæ¾ B |
| | | outAll.push_back(A); |
| | | for (int s = 0; s < 3; ++s) { |
| | | CString sid; sid.Format(_T("S%04d_%d"), k, s); |
| | | outAll.push_back(FakeDbRecord{ |
| | | id++, 300 + k * 10 + s, 400 + k * 10 + s, toAnsi(sid), |
| | | (k + s) % 3, (k + s) % 5, _fmt_time(0, k * 2 + s), _fmt_time(0, k * 2 + s + 1), |
| | | std::string(), (k + s) % 4, |
| | | sjoin({ "path/", toAnsi(sid) }), |
| | | sjoin({ "{\"single\":", std::to_string(s), "}" }) |
| | | }); |
| | | } |
| | | outAll.push_back(B); |
| | | } |
| | | else { |
| | | // å页紧æ¨ç |
| | | outAll.push_back(A); |
| | | outAll.push_back(B); |
| | | } |
| | | }; |
| | | |
| | | // ===== ç¶åæåé»è¾è¿½å ï¼å页é
对 / 跨页é
坹 / 忡 ===== |
| | | // 6 ç»å页é
对ï¼12 æ¡ï¼ |
| | | for (int k = 1; k <= 6; ++k) mkPair(k, false); |
| | | // 4 ç»è·¨é¡µé
å¯¹ï¼æ¯ç»ä¸é´æ 3 æ¡âåæ¡âï¼ |
| | | for (int k = 101; k <= 104; ++k) mkPair(k, true); |
| | | // è¥å¹²âåæ¡â |
| | | for (int u = 201; u < 806; ++u) { |
| | | CString cid; cid.Format(_T("U%04d"), u); |
| | | outAll.push_back(FakeDbRecord{ |
| | | id++, 500 + u, 600 + u, toAnsi(cid), |
| | | u % 3, u % 5, _fmt_time(0, u % 17), _fmt_time(0, (u % 17) + 1), |
| | | std::string(), u % 4, |
| | | sjoin({ "path/", toAnsi(cid) }), |
| | | sjoin({ "{\"u\":", std::to_string(u), "}" }) |
| | | }); |
| | | } |
| | | } |
| | | |
| | | |
| | | #define PAGE_SIZE 100 |
| | | #define PAGE_BACKGROUND_COLOR RGB(252, 252, 255) |
| | | // ---- åå页åçï¼å¯æéå æ´ä¸¥æ ¼ç filtersï¼---- |
| | | static FakeDbPage _make_page_fake(const GlassLogDb::Filters& /*f*/, int pageSize, int offset) { |
| | | std::vector<FakeDbRecord> all; |
| | | _make_all_fake(all); |
| | | |
| | | FakeDbPage page; |
| | | int n = (int)all.size(); |
| | | int beg = min(max(0, offset), n); |
| | | int end = min(beg + max(0, pageSize), n); |
| | | page.items.insert(page.items.end(), all.begin() + beg, all.begin() + end); |
| | | return page; |
| | | } |
| | | static int _fake_total_count() { |
| | | std::vector<FakeDbRecord> all; |
| | | _make_all_fake(all); |
| | | return (int)all.size(); |
| | | } |
| | | #endif // USE_FAKE_DB_DEMO |
| | | |
| | | // 夿æ parent 䏿¯å¦å·²åå¨ classId == cid çåèç¹ï¼å¿½ç¥å¤§å°åï¼ |
| | | static bool NodeHasChildWithClassId(CExpandableListCtrl::Node* parent, const CString& cid) |
| | | { |
| | | if (!parent) return false; |
| | | for (auto& ch : parent->children) { |
| | | if (ch && ch->cols.size() > 4) { |
| | | if (ch->cols[4].CompareNoCase(cid) == 0) |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | // æ cols ååå°æä¸è¡ï¼ä»ç¬¬1åå¼å§ï¼ç¬¬0åæä»¬æ²¡ç¨ï¼ |
| | | static void ApplyColsToRow(CListCtrl& lv, int row, const std::vector<CString>& cols) { |
| | | int colCount = 0; |
| | | if (auto* hdr = lv.GetHeaderCtrl()) colCount = hdr->GetItemCount(); |
| | | colCount = min(colCount, (int)cols.size()); |
| | | for (int c = 1; c < colCount; ++c) { |
| | | lv.SetItemText(row, c, cols[c]); |
| | | } |
| | | } |
| | | |
| | | // éä¸è¡ç ClassID å¿«ç
§ï¼ç¨äºéå»ºåæ¢å¤ï¼ |
| | | static std::unordered_set<std::string> SnapshotSelectedKeys(CListCtrl& lv) { |
| | | std::unordered_set<std::string> keys; |
| | | int n = lv.GetItemCount(); |
| | | for (int i = 0; i < n; ++i) { |
| | | if ((lv.GetItemState(i, LVIS_SELECTED) & LVIS_SELECTED) == 0) continue; |
| | | CString cls = lv.GetItemText(i, 4); |
| | | #ifdef _UNICODE |
| | | keys.insert(CT2A(cls)); |
| | | #else |
| | | keys.insert(cls.GetString()); |
| | | #endif |
| | | } |
| | | return keys; |
| | | } |
| | | |
| | | // é¡¶è¡ï¼TopIndexï¼å¯¹åºç ClassID |
| | | static std::optional<std::string> SnapshotTopKey(CListCtrl& lv) { |
| | | int top = lv.GetTopIndex(); |
| | | if (top < 0 || top >= lv.GetItemCount()) return std::nullopt; |
| | | CString cls = lv.GetItemText(top, 4); |
| | | #ifdef _UNICODE |
| | | return std::optional<std::string>(CT2A(cls)); |
| | | #else |
| | | return std::optional<std::string>(cls.GetString()); |
| | | #endif |
| | | } |
| | | |
| | | // ç¨ ClassID é忢å¤éä¸ |
| | | static void RestoreSelectionByKeys(CListCtrl& lv, const std::unordered_set<std::string>& keys) { |
| | | int n = lv.GetItemCount(); |
| | | for (int i = 0; i < n; ++i) lv.SetItemState(i, 0, LVIS_SELECTED); |
| | | for (int i = 0; i < n; ++i) { |
| | | CString cls = lv.GetItemText(i, 4); |
| | | #ifdef _UNICODE |
| | | if (keys.count(CT2A(cls))) lv.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); |
| | | #else |
| | | if (keys.count(cls.GetString())) lv.SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); |
| | | #endif |
| | | } |
| | | } |
| | | |
| | | // å°½éææä¸ª ClassID æ»åå¯è§ |
| | | static void RestoreTopByKey(CListCtrl& lv, const std::optional<std::string>& key) { |
| | | if (!key) return; |
| | | int n = lv.GetItemCount(); |
| | | for (int i = 0; i < n; ++i) { |
| | | CString cls = lv.GetItemText(i, 4); |
| | | #ifdef _UNICODE |
| | | if (CT2A(cls) == *key) { lv.EnsureVisible(i, FALSE); break; } |
| | | #else |
| | | if (cls.GetString() == *key) { lv.EnsureVisible(i, FALSE); break; } |
| | | #endif |
| | | } |
| | | } |
| | | |
| | | bool CopyUtf8ToClipboard(const std::string& utf8) |
| | | { |
| | | // 1) UTF-8 -> UTF-16 é¿åº¦ï¼å«ç»å°¾ '\0'ï¼ |
| | | int wlen = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, nullptr, 0); |
| | | if (wlen <= 0) return false; |
| | | |
| | | // 2) 为åªè´´æ¿åé
å
¨å±å¯ç§»å¨å
åï¼å¿
é¡» GMEM_MOVEABLEï¼ |
| | | SIZE_T bytes = static_cast<SIZE_T>(wlen) * sizeof(wchar_t); |
| | | HGLOBAL hMem = GlobalAlloc(GMEM_MOVEABLE, bytes); |
| | | if (!hMem) return false; |
| | | |
| | | // 3) å¡«å
UTF-16 ææ¬ |
| | | wchar_t* wbuf = static_cast<wchar_t*>(GlobalLock(hMem)); |
| | | if (!wbuf) { GlobalFree(hMem); return false; } |
| | | MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, wbuf, wlen); |
| | | GlobalUnlock(hMem); |
| | | |
| | | // 4) æå¼åªè´´æ¿å¹¶è®¾ç½®æ°æ®ï¼CF_UNICODETEXTï¼ |
| | | if (!OpenClipboard(nullptr)) { GlobalFree(hMem); return false; } |
| | | if (!EmptyClipboard()) { CloseClipboard(); GlobalFree(hMem); return false; } |
| | | |
| | | // æååï¼å
åæææäº¤ç»åªè´´æ¿ï¼ä¸è½å GlobalFree |
| | | if (!SetClipboardData(CF_UNICODETEXT, hMem)) { |
| | | CloseClipboard(); |
| | | GlobalFree(hMem); |
| | | return false; |
| | | } |
| | | |
| | | CloseClipboard(); |
| | | return true; |
| | | } |
| | | |
| | | |
| | | // CPageGlassList å¯¹è¯æ¡ |
| | | |
| | | IMPLEMENT_DYNAMIC(CPageGlassList, CDialogEx) |
| | | |
| | | CPageGlassList::CPageGlassList(CWnd* pParent /*=nullptr*/) |
| | | : CDialogEx(IDD_PAGE_GLASS_LIST, pParent) |
| | | : CDialogEx(IDD_PAGE_GLASS_LIST, pParent) |
| | | { |
| | | m_crBkgnd = PAGE_BACKGROUND_COLOR; |
| | | m_hbrBkgnd = nullptr; |
| | | m_pObserver = nullptr; |
| | | m_crBkgnd = PAGE_BACKGROUND_COLOR; |
| | | m_hbrBkgnd = nullptr; |
| | | m_pObserver = nullptr; |
| | | |
| | | m_strStatus = ""; |
| | | m_strKeyword = ""; |
| | | m_nCurPage = 0; |
| | | m_nTotalPages = 0; |
| | | m_strStatus = ""; |
| | | m_nCurPage = 1; |
| | | m_nTotalPages = 1; |
| | | |
| | | memset(m_szTimeStart, 0, sizeof(m_szTimeStart)); |
| | | memset(m_szTimeEnd, 0, sizeof(m_szTimeEnd)); |
| | | m_szTimeStart[0] = '\0'; |
| | | m_szTimeEnd[0] = '\0'; |
| | | memset(m_szTimeStart, 0, sizeof(m_szTimeStart)); |
| | | memset(m_szTimeEnd, 0, sizeof(m_szTimeEnd)); |
| | | m_szTimeStart[0] = '\0'; |
| | | m_szTimeEnd[0] = '\0'; |
| | | } |
| | | |
| | | CPageGlassList::~CPageGlassList() |
| | | { |
| | | if (m_hbrBkgnd != nullptr) { |
| | | ::DeleteObject(m_hbrBkgnd); |
| | | } |
| | | if (m_pObserver != nullptr) { |
| | | m_pObserver->unsubscribe(); |
| | | m_pObserver = nullptr; |
| | | } |
| | | if (m_hbrBkgnd != nullptr) { |
| | | ::DeleteObject(m_hbrBkgnd); |
| | | m_hbrBkgnd = nullptr; |
| | | } |
| | | if (m_pObserver != nullptr) { |
| | | m_pObserver->unsubscribe(); |
| | | m_pObserver = nullptr; |
| | | } |
| | | } |
| | | |
| | | void CPageGlassList::DoDataExchange(CDataExchange* pDX) |
| | | { |
| | | CDialogEx::DoDataExchange(pDX); |
| | | DDX_Control(pDX, IDC_DATETIMEPICKER_START, m_dateTimeStart); |
| | | DDX_Control(pDX, IDC_DATETIMEPICKER_END, m_dateTimeEnd); |
| | | DDX_Control(pDX, IDC_LIST_ALARM, m_listCtrl); |
| | | CDialogEx::DoDataExchange(pDX); |
| | | DDX_Control(pDX, IDC_DATETIMEPICKER_START, m_dateTimeStart); |
| | | DDX_Control(pDX, IDC_DATETIMEPICKER_END, m_dateTimeEnd); |
| | | DDX_Control(pDX, IDC_LIST_ALARM, m_listCtrl); |
| | | } |
| | | |
| | | |
| | | BEGIN_MESSAGE_MAP(CPageGlassList, CDialogEx) |
| | | ON_WM_CTLCOLOR() |
| | | ON_WM_DESTROY() |
| | | ON_WM_SIZE() |
| | | ON_WM_TIMER() |
| | | ON_CBN_SELCHANGE(IDC_COMBO_DATETIME, &CPageGlassList::OnCbnSelchangeComboDatetime) |
| | | ON_CBN_SELCHANGE(IDC_COMBO_STATUS_FILTER, &CPageGlassList::OnCbnSelchangeComboStatusFilter) |
| | | ON_BN_CLICKED(IDC_BUTTON_SEARCH, &CPageGlassList::OnBnClickedButtonSearch) |
| | | ON_BN_CLICKED(IDC_BUTTON_EXPORT, &CPageGlassList::OnBnClickedButtonExport) |
| | | ON_BN_CLICKED(IDC_BUTTON_PREV_PAGE, &CPageGlassList::OnBnClickedButtonPrevPage) |
| | | ON_BN_CLICKED(IDC_BUTTON_NEXT_PAGE, &CPageGlassList::OnBnClickedButtonNextPage) |
| | | ON_WM_CTLCOLOR() |
| | | ON_WM_DESTROY() |
| | | ON_WM_SIZE() |
| | | ON_WM_TIMER() |
| | | ON_CBN_SELCHANGE(IDC_COMBO_DATETIME, &CPageGlassList::OnCbnSelchangeComboDatetime) |
| | | ON_CBN_SELCHANGE(IDC_COMBO_STATUS_FILTER, &CPageGlassList::OnCbnSelchangeComboStatusFilter) |
| | | ON_BN_CLICKED(IDC_BUTTON_SEARCH, &CPageGlassList::OnBnClickedButtonSearch) |
| | | ON_BN_CLICKED(IDC_BUTTON_EXPORT, &CPageGlassList::OnBnClickedButtonExport) |
| | | ON_BN_CLICKED(IDC_BUTTON_PREV_PAGE, &CPageGlassList::OnBnClickedButtonPrevPage) |
| | | ON_BN_CLICKED(IDC_BUTTON_NEXT_PAGE, &CPageGlassList::OnBnClickedButtonNextPage) |
| | | ON_NOTIFY(ELCN_SHOWFULLTEXT, IDC_LIST_ALARM, &CPageGlassList::OnShowFullText) |
| | | END_MESSAGE_MAP() |
| | | |
| | | // ===== ç§æå°å·¥å
· ===== |
| | | static int GetColumnCount(CListCtrl& lv) |
| | | { |
| | | CHeaderCtrl* pHdr = lv.GetHeaderCtrl(); |
| | | return pHdr ? pHdr->GetItemCount() : 0; |
| | | } |
| | | |
| | | // CPageGlassList æ¶æ¯å¤çç¨åº |
| | | // ===== CPageGlassList æ¶æ¯å¤çç¨åº ===== |
| | | void CPageGlassList::InitRxWindow() |
| | | { |
| | | /* code */ |
| | | // 订é
æ°æ® |
| | | IRxWindows* pRxWindows = RX_GetRxWindows(); |
| | | pRxWindows->enableLog(5); |
| | | if (m_pObserver == NULL) { |
| | | m_pObserver = pRxWindows->allocObserver([&](IAny* pAny) -> void { |
| | | // onNext |
| | | pAny->addRef(); |
| | | int code = pAny->getCode(); |
| | | // 订é
æ°æ® |
| | | IRxWindows* pRxWindows = RX_GetRxWindows(); |
| | | pRxWindows->enableLog(5); |
| | | if (m_pObserver == NULL) { |
| | | m_pObserver = pRxWindows->allocObserver([&](IAny* pAny) -> void { |
| | | // onNext |
| | | pAny->addRef(); |
| | | int code = pAny->getCode(); |
| | | |
| | | if (RX_CODE_EQ_ROBOT_TASK == code) { |
| | | UpdatePageData(); |
| | | } |
| | | if (RX_CODE_EQ_ROBOT_TASK == code) { |
| | | UpdateWipData(); // åªæ´æ°ï¼ä¸é建ï¼ä¸æ¹åå±å¼/éæ© |
| | | } |
| | | |
| | | pAny->release(); |
| | | }, [&]() -> void { |
| | | // onComplete |
| | | }, [&](IThrowable* pThrowable) -> void { |
| | | // onErrorm |
| | | pThrowable->printf(); |
| | | }); |
| | | pAny->release(); |
| | | }, [&]() -> void { |
| | | // onComplete |
| | | }, [&](IThrowable* pThrowable) -> void { |
| | | // onError |
| | | pThrowable->printf(); |
| | | }); |
| | | |
| | | theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())->subscribe(m_pObserver); |
| | | } |
| | | theApp.m_model.getObservable()->observeOn(pRxWindows->mainThread())->subscribe(m_pObserver); |
| | | } |
| | | } |
| | | |
| | | void CPageGlassList::Resize() |
| | | { |
| | | CRect rcClient; |
| | | GetClientRect(&rcClient); |
| | | CRect rcClient; |
| | | GetClientRect(&rcClient); |
| | | |
| | | // ===== 常éå®ä¹ ===== |
| | | const int nLeft = 12; |
| | | const int nRight = 12; |
| | | const int nTop = 58; |
| | | const int nButtonHeight = 28; |
| | | const int nButtonMarginBottom = 12; |
| | | const int nSpacing = 8; |
| | | const int nButtonWidth = 80; |
| | | const int nLabelWidth = 100; |
| | | // ===== 常éå®ä¹ ===== |
| | | const int nLeft = 12; |
| | | const int nRight = 12; |
| | | const int nTop = 58; |
| | | const int nButtonHeight = 28; |
| | | const int nButtonMarginBottom = 12; |
| | | const int nSpacing = 8; |
| | | const int nButtonWidth = 80; |
| | | const int nLabelWidth = 100; |
| | | |
| | | // ===== å页æ§ä»¶å¸å± ===== |
| | | int yBottom = rcClient.bottom - nButtonMarginBottom - nButtonHeight; |
| | | int xRight = rcClient.Width() - nRight; |
| | | // ===== å页æ§ä»¶å¸å± ===== |
| | | int yBottom = rcClient.bottom - nButtonMarginBottom - nButtonHeight; |
| | | int xRight = rcClient.Width() - nRight; |
| | | |
| | | CWnd* pBtnNext = GetDlgItem(IDC_BUTTON_NEXT_PAGE); |
| | | CWnd* pBtnPrev = GetDlgItem(IDC_BUTTON_PREV_PAGE); |
| | | CWnd* pLabelPage = GetDlgItem(IDC_LABEL_PAGE_NUMBER); |
| | | CWnd* pBtnNext = GetDlgItem(IDC_BUTTON_NEXT_PAGE); |
| | | CWnd* pBtnPrev = GetDlgItem(IDC_BUTTON_PREV_PAGE); |
| | | CWnd* pLabelPage = GetDlgItem(IDC_LABEL_PAGE_NUMBER); |
| | | |
| | | if (pBtnNext && pBtnPrev && pLabelPage) { |
| | | // è·ååé¡µææ¬å®½åº¦ä¼°ç® |
| | | //CString strLabel; |
| | | //GetDlgItemText(IDC_LABEL_PAGE_NUMBER, strLabel); |
| | | //if (strLabel.IsEmpty()) { |
| | | // strLabel = _T("第 1 / 1 页"); |
| | | //} |
| | | //int nCharWidth = 8; |
| | | //int nLabelWidth = strLabel.GetLength() * nCharWidth + 20; |
| | | if (pBtnNext && pBtnPrev && pLabelPage) { |
| | | pBtnNext->MoveWindow(xRight - nButtonWidth, yBottom, nButtonWidth, nButtonHeight); |
| | | xRight -= nButtonWidth + nSpacing; |
| | | |
| | | // 设置æé®åæ ç¾ä½ç½® |
| | | pBtnNext->MoveWindow(xRight - nButtonWidth, yBottom, nButtonWidth, nButtonHeight); |
| | | xRight -= nButtonWidth + nSpacing; |
| | | pLabelPage->MoveWindow(xRight - nLabelWidth, yBottom, nLabelWidth, nButtonHeight); |
| | | xRight -= nLabelWidth + nSpacing; |
| | | |
| | | pLabelPage->MoveWindow(xRight - nLabelWidth, yBottom, nLabelWidth, nButtonHeight); |
| | | xRight -= nLabelWidth + nSpacing; |
| | | pBtnPrev->MoveWindow(xRight - nButtonWidth, yBottom, nButtonWidth, nButtonHeight); |
| | | } |
| | | |
| | | pBtnPrev->MoveWindow(xRight - nButtonWidth, yBottom, nButtonWidth, nButtonHeight); |
| | | } |
| | | |
| | | // ===== è¡¨æ ¼åºåå¸å± ===== |
| | | if (nullptr != m_listCtrl.m_hWnd) { |
| | | int listHeight = yBottom - nTop - nSpacing; |
| | | m_listCtrl.MoveWindow(nLeft, nTop, rcClient.Width() - nLeft - nRight, listHeight); |
| | | } |
| | | // ===== è¡¨æ ¼åºåå¸å± ===== |
| | | if (nullptr != m_listCtrl.m_hWnd) { |
| | | int listHeight = yBottom - nTop - nSpacing; |
| | | m_listCtrl.MoveWindow(nLeft, nTop, rcClient.Width() - nLeft - nRight, listHeight); |
| | | } |
| | | } |
| | | |
| | | void CPageGlassList::InitStatusCombo() |
| | | { |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_STATUS_FILTER); |
| | | if (nullptr != pComboBox) { |
| | | pComboBox->ResetContent(); |
| | | pComboBox->AddString(_T("å
¨é¨")); |
| | | pComboBox->AddString(_T("Ready")); |
| | | pComboBox->AddString(_T("Running")); |
| | | pComboBox->AddString(_T("Error")); |
| | | pComboBox->AddString(_T("Abort")); |
| | | pComboBox->AddString(_T("Completed")); |
| | | pComboBox->SetCurSel(0); |
| | | } |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_STATUS_FILTER); |
| | | if (nullptr != pComboBox) { |
| | | pComboBox->ResetContent(); |
| | | pComboBox->AddString(_T("å
¨é¨")); |
| | | pComboBox->AddString(_T("Ready")); |
| | | pComboBox->AddString(_T("Running")); |
| | | pComboBox->AddString(_T("Error")); |
| | | pComboBox->AddString(_T("Abort")); |
| | | pComboBox->AddString(_T("Completed")); |
| | | pComboBox->SetCurSel(0); |
| | | } |
| | | } |
| | | |
| | | void CPageGlassList::InitTimeRangeCombo() |
| | | { |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME); |
| | | if (nullptr != pComboBox) { |
| | | pComboBox->ResetContent(); |
| | | pComboBox->AddString(_T("ä¸é")); |
| | | pComboBox->AddString(_T("ä»å¤©")); |
| | | pComboBox->AddString(_T("ä¸å¤©å
")); |
| | | pComboBox->AddString(_T("æ¬æ")); |
| | | pComboBox->AddString(_T("ä»å¹´")); |
| | | pComboBox->AddString(_T("èªå®ä¹")); |
| | | pComboBox->SetCurSel(0); |
| | | } |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME); |
| | | if (nullptr != pComboBox) { |
| | | pComboBox->ResetContent(); |
| | | pComboBox->AddString(_T("ä¸é")); |
| | | pComboBox->AddString(_T("ä»å¤©")); |
| | | pComboBox->AddString(_T("ä¸å¤©å
")); |
| | | pComboBox->AddString(_T("æ¬æ")); |
| | | pComboBox->AddString(_T("ä»å¹´")); |
| | | pComboBox->AddString(_T("èªå®ä¹")); |
| | | pComboBox->SetCurSel(0); |
| | | } |
| | | } |
| | | |
| | | void CPageGlassList::InitDateTimeControls() |
| | | { |
| | | if (m_dateTimeStart.m_hWnd == nullptr || m_dateTimeEnd.m_hWnd == nullptr) { |
| | | return; |
| | | } |
| | | |
| | | // ç¦ç¨åå§ç¶æ |
| | | m_dateTimeStart.EnableWindow(FALSE); |
| | | m_dateTimeEnd.EnableWindow(FALSE); |
| | | |
| | | // è®¾ç½®æ ¼å¼ï¼æ¾ç¤ºæ¥æ + æ¶é´ |
| | | //m_dateTimeStart.SetFormat(_T("yyyy/MM/dd HH:mm:ss")); |
| | | //m_dateTimeEnd.SetFormat(_T("yyyy/MM/dd HH:mm:ss")); |
| | | |
| | | // ä¿®æ¹æ ·å¼ä»¥æ¯ææ¶é´æ ¼å¼ |
| | | //DWORD dwStyleStart = m_dateTimeStart.GetStyle(); |
| | | //DWORD dwStyleEnd = m_dateTimeEnd.GetStyle(); |
| | | |
| | | //m_dateTimeStart.ModifyStyle(0, DTS_TIMEFORMAT | DTS_UPDOWN); |
| | | //m_dateTimeEnd.ModifyStyle(0, DTS_TIMEFORMAT); |
| | | if (m_dateTimeStart.m_hWnd == nullptr || m_dateTimeEnd.m_hWnd == nullptr) { |
| | | return; |
| | | } |
| | | // èªå®ä¹èå´æ¶æå¯ç¼è¾ |
| | | m_dateTimeStart.EnableWindow(FALSE); |
| | | m_dateTimeEnd.EnableWindow(FALSE); |
| | | } |
| | | |
| | | void CPageGlassList::LoadTransfers() |
| | | void CPageGlassList::LoadData() |
| | | { |
| | | m_nCurPage = 1; |
| | | UpdatePageData(); |
| | | m_nCurPage = 1; |
| | | UpdatePageData(); |
| | | } |
| | | |
| | | void CPageGlassList::UpdatePageData() |
| | | { |
| | | /* |
| | | TransferData filter; |
| | | filter.strStatus = m_strStatus; |
| | | filter.strDescription = m_strKeyword; |
| | | filter.strCreateTime = m_szTimeStart; |
| | | filter.strEndTime = m_szTimeEnd; |
| | | auto vecData = TransferManager::getInstance().getTransfers(filter, m_nCurPage, PAGE_SIZE); |
| | | FillDataToListCtrl(vecData); |
| | | m_rebuilding = true; |
| | | |
| | | int nTotalRecords = TransferManager::getInstance().getFilteredTransferCount(filter); |
| | | m_nTotalPages = (nTotalRecords + PAGE_SIZE - 1) / PAGE_SIZE; |
| | | UpdatePageControls(); |
| | | */ |
| | | // æ¾å¨ä»»ä½æ¸
空/é建å¨ä½ä¹åï¼è®°å½å±å¼çç¶èç¹ keyï¼ClassIDï¼ |
| | | auto expandedKeys = SnapshotExpandedKeys(m_listCtrl); |
| | | |
| | | // ââ åä¿é©ï¼å
æ¸
æå¯è§é¡¹ï¼åæ¸
æ ç»æ ââ |
| | | m_listCtrl.SetRedraw(FALSE); |
| | | m_listCtrl.DeleteAllItems(); |
| | | m_listCtrl.SetRedraw(TRUE); |
| | | |
| | | // ââ æ¸
空æ ï¼ä¾èµ CExpandableListCtrl::ClearTree()ï¼ââ |
| | | m_listCtrl.ClearTree(); |
| | | |
| | | const int colCount = m_listCtrl.GetHeaderCtrl() ? m_listCtrl.GetHeaderCtrl()->GetItemCount() : 0; |
| | | if (colCount <= 0) { m_rebuilding = false; return; } |
| | | |
| | | // ==================== 1) WIPï¼ä»
第 1 页æå»ºï¼ä¸æ¾å¨æé¡¶é¨ ==================== |
| | | if (m_nCurPage == 1) { |
| | | std::vector<SERVO::CGlass*> wipGlasses; |
| | | theApp.m_model.m_master.getWipGlasses(wipGlasses); |
| | | std::vector<SERVO::CGlass*> tempGlasses = wipGlasses; // å¾
éæ¾ |
| | | |
| | | auto glassHit = [&](SERVO::CGlass* g) -> bool { |
| | | return g && GlassMatchesFilters(*g, m_filters); |
| | | }; |
| | | |
| | | std::unordered_set<SERVO::CGlass*> usedWip; |
| | | |
| | | for (auto* g : wipGlasses) { |
| | | if (!glassHit(g) || usedWip.count(g)) continue; |
| | | |
| | | SERVO::CGlass* b = g->getBuddy(); |
| | | if (b) { |
| | | // æä½ ç约å®ï¼g æ¯ç¶ï¼buddy æ¯å |
| | | SERVO::CGlass* parent = g; |
| | | SERVO::CGlass* child = b; |
| | | |
| | | // parent |
| | | std::vector<CString> pcols(colCount); |
| | | pcols[1] = _T(""); |
| | | pcols[2] = std::to_string(parent->getCassetteSequenceNo()).c_str(); |
| | | pcols[3] = std::to_string(parent->getJobSequenceNo()).c_str(); |
| | | pcols[4] = parent->getID().c_str(); |
| | | pcols[5] = SERVO::CServoUtilsTool::getMaterialsTypeText(parent->getType()).c_str(); |
| | | pcols[6] = SERVO::CServoUtilsTool::getGlassStateText(parent->state()).c_str(); |
| | | pcols[7] = CToolUnits::TimePointToLocalString(parent->tStart()).c_str(); |
| | | pcols[8] = CToolUnits::TimePointToLocalString(parent->tEnd()).c_str(); |
| | | pcols[9] = parent->getBuddyId().c_str(); |
| | | pcols[10] = SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)parent->getAOIInspResult()).c_str(); |
| | | pcols[11] = parent->getPathDescription().c_str(); |
| | | pcols[12] = parent->getParamsDescription().c_str(); |
| | | |
| | | auto* nParent = m_listCtrl.InsertRoot(pcols); |
| | | MaybeRestoreExpandByKey(nParent, expandedKeys); |
| | | m_listCtrl.SetNodeColor(nParent, kWipText, kWipParentBk); // ç¶ï¼åºç¡ç»¿ |
| | | |
| | | // child |
| | | std::vector<CString> ccols(colCount); |
| | | ccols[1] = _T(""); |
| | | ccols[2] = std::to_string(child->getCassetteSequenceNo()).c_str(); |
| | | ccols[3] = std::to_string(child->getJobSequenceNo()).c_str(); |
| | | ccols[4] = child->getID().c_str(); |
| | | ccols[5] = SERVO::CServoUtilsTool::getMaterialsTypeText(child->getType()).c_str(); |
| | | ccols[6] = SERVO::CServoUtilsTool::getGlassStateText(child->state()).c_str(); |
| | | ccols[7] = CToolUnits::TimePointToLocalString(child->tStart()).c_str(); |
| | | ccols[8] = CToolUnits::TimePointToLocalString(child->tEnd()).c_str(); |
| | | ccols[9] = child->getBuddyId().c_str(); |
| | | ccols[10] = SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)child->getAOIInspResult()).c_str(); |
| | | ccols[11] = child->getPathDescription().c_str(); |
| | | ccols[12] = child->getParamsDescription().c_str(); |
| | | |
| | | auto* nChild = m_listCtrl.InsertChild(nParent, ccols); |
| | | m_listCtrl.SetNodeColor(nChild, kWipText, kWipChildBk); // åï¼æ´æµ
|
| | | |
| | | usedWip.insert(parent); |
| | | usedWip.insert(child); |
| | | } |
| | | else { |
| | | std::vector<CString> cols(colCount); |
| | | cols[1] = _T(""); |
| | | cols[2] = std::to_string(g->getCassetteSequenceNo()).c_str(); |
| | | cols[3] = std::to_string(g->getJobSequenceNo()).c_str(); |
| | | cols[4] = g->getID().c_str(); |
| | | cols[5] = SERVO::CServoUtilsTool::getMaterialsTypeText(g->getType()).c_str(); |
| | | cols[6] = SERVO::CServoUtilsTool::getGlassStateText(g->state()).c_str(); |
| | | cols[7] = CToolUnits::TimePointToLocalString(g->tStart()).c_str(); |
| | | cols[8] = CToolUnits::TimePointToLocalString(g->tEnd()).c_str(); |
| | | cols[9] = g->getBuddyId().c_str(); |
| | | cols[10] = SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)g->getAOIInspResult()).c_str(); |
| | | cols[11] = g->getPathDescription().c_str(); |
| | | cols[12] = g->getParamsDescription().c_str(); |
| | | |
| | | auto* n = m_listCtrl.InsertRoot(cols); |
| | | m_listCtrl.SetNodeColor(n, kWipText, kWipParentBk); // ä»ç¨åºç¡ç»¿ |
| | | usedWip.insert(g); |
| | | } |
| | | } |
| | | for (auto* item : tempGlasses) item->release(); |
| | | } |
| | | |
| | | // ==================== 2) DB å½å页ï¼ä¸¤é¶æ®µæå»ºï¼å¤çåå buddyï¼ ==================== |
| | | const int rawLimit = PAGE_SIZE + 1; |
| | | const int rawOffset = PAGE_SIZE * (m_nCurPage - 1); |
| | | #if USE_FAKE_DB_DEMO |
| | | auto page = _make_page_fake(m_filters, rawLimit, rawOffset); |
| | | #else |
| | | auto& db = GlassLogDb::Instance(); |
| | | auto pageFull = db.queryPaged(m_filters, rawLimit, rawOffset); |
| | | #endif |
| | | |
| | | // 妿å¤åºä¸æ¡ï¼çç宿¯å¦æ¯âæ¬é¡µæå䏿¡âç buddy |
| | | std::optional<decltype(pageFull.items)::value_type> lookahead; // é¢è¯»è®°å½ï¼è¥ä¸æå䏿¡é
å¯¹ï¼ |
| | | auto iEquals = [](const std::string& a, const std::string& b) { |
| | | #ifdef _WIN32 |
| | | return _stricmp(a.c_str(), b.c_str()) == 0; |
| | | #else |
| | | return strcasecmp(a.c_str(), b.c_str()) == 0; |
| | | #endif |
| | | }; |
| | | |
| | | if (pageFull.items.size() == rawLimit) { |
| | | const auto& last = pageFull.items[PAGE_SIZE - 1]; |
| | | const auto& extra = pageFull.items[PAGE_SIZE]; |
| | | |
| | | bool pair = |
| | | (!last.buddyId.empty() && iEquals(last.buddyId, extra.classId)) || |
| | | (!extra.buddyId.empty() && iEquals(extra.buddyId, last.classId)); |
| | | |
| | | if (pair) { |
| | | lookahead = extra; // æé¢è¯»ä¿å䏿¥ï¼ç¨åè¡¥æåè¡ |
| | | } |
| | | // æ 论æ¯å¦é
对ï¼å表é½ç¼©å PAGE_SIZE æ¡ï¼é¢è¯»ä¸ç®å
¥æ¬é¡µæ°æ®éï¼ |
| | | pageFull.items.pop_back(); |
| | | } |
| | | |
| | | // ä¹åæ£å¸¸æ page æå»º |
| | | auto& page = pageFull; // 为äºå¤ç¨ä½ åæåéå |
| | | |
| | | // 建索å¼ï¼classId -> index |
| | | std::unordered_map<std::string, size_t> idxById; |
| | | idxById.reserve(page.items.size()); |
| | | for (size_t i = 0; i < page.items.size(); ++i) { |
| | | idxById[page.items[i].classId] = i; |
| | | } |
| | | |
| | | // å·²æ¶è´¹ï¼å·²æå
¥ä¸ºç¶æåï¼ |
| | | std::unordered_set<std::string> consumed; |
| | | int zebra = 0; |
| | | auto zebraBk = [&](int z) -> COLORREF { |
| | | return (z % 2 == 0) ? RGB(255, 255, 255) : RGB(235, 235, 235); |
| | | }; |
| | | |
| | | // -------- Phase 1: å
å¤çâæ buddyId çè®°å½âï¼è½é
å°±é
ï¼ååä¹é
ï¼ ---------- |
| | | for (size_t i = 0; i < page.items.size(); ++i) { |
| | | const auto& r = page.items[i]; |
| | | // CopyUtf8ToClipboard(r.pretty); |
| | | |
| | | if (consumed.count(r.classId)) continue; |
| | | if (r.buddyId.empty()) continue; |
| | | |
| | | COLORREF bk = zebraBk(zebra); |
| | | |
| | | auto it = idxById.find(r.buddyId); |
| | | if (it != idxById.end()) { |
| | | const auto& br = page.items[it->second]; |
| | | if (!consumed.count(br.classId)) { |
| | | // ââ ä»¥âæ buddyId çè¿æ¡ râ为ç¶ï¼buddy ä½ä¸ºåï¼ååä¹è½é
ï¼ââ |
| | | std::vector<CString> pcols(colCount); |
| | | pcols[1] = std::to_string(r.id).c_str(); |
| | | pcols[2] = std::to_string(r.cassetteSeqNo).c_str(); |
| | | pcols[3] = std::to_string(r.jobSeqNo).c_str(); |
| | | pcols[4] = r.classId.c_str(); |
| | | pcols[5] = SERVO::CServoUtilsTool::getMaterialsTypeText((SERVO::MaterialsType)r.materialType).c_str(); |
| | | pcols[6] = SERVO::CServoUtilsTool::getGlassStateText((SERVO::GlsState)r.state).c_str(); |
| | | pcols[7] = r.tStart.c_str(); |
| | | pcols[8] = r.tEnd.c_str(); |
| | | pcols[9] = r.buddyId.c_str(); |
| | | pcols[10] = SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)r.aoiResult).c_str(); |
| | | pcols[11] = r.path.c_str(); |
| | | pcols[12] = r.params.c_str(); |
| | | |
| | | auto* nParent = m_listCtrl.InsertRoot(pcols); |
| | | MaybeRestoreExpandByKey(nParent, expandedKeys); |
| | | m_listCtrl.SetNodeColor(nParent, RGB(0, 0, 0), bk); |
| | | |
| | | std::vector<CString> ccols(colCount); |
| | | ccols[1] = std::to_string(br.id).c_str(); |
| | | ccols[2] = std::to_string(br.cassetteSeqNo).c_str(); |
| | | ccols[3] = std::to_string(br.jobSeqNo).c_str(); |
| | | ccols[4] = br.classId.c_str(); |
| | | ccols[5] = SERVO::CServoUtilsTool::getMaterialsTypeText((SERVO::MaterialsType)br.materialType).c_str(); |
| | | ccols[6] = SERVO::CServoUtilsTool::getGlassStateText((SERVO::GlsState)br.state).c_str(); |
| | | ccols[7] = br.tStart.c_str(); |
| | | ccols[8] = br.tEnd.c_str(); |
| | | ccols[9] = br.buddyId.c_str(); |
| | | ccols[10] = SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)br.aoiResult).c_str(); |
| | | ccols[11] = br.path.c_str(); |
| | | ccols[12] = br.params.c_str(); |
| | | |
| | | auto* nChild = m_listCtrl.InsertChild(nParent, ccols); |
| | | m_listCtrl.SetNodeColor(nChild, RGB(0, 0, 0), bk); |
| | | |
| | | consumed.insert(r.classId); |
| | | consumed.insert(br.classId); |
| | | ++zebra; |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | // å页没æ¾å° buddyï¼æå·²è¢«æ¶è´¹ï¼â æå ä½åè¡ |
| | | std::vector<CString> pcols(colCount); |
| | | pcols[1] = std::to_string(r.id).c_str(); |
| | | pcols[2] = std::to_string(r.cassetteSeqNo).c_str(); |
| | | pcols[3] = std::to_string(r.jobSeqNo).c_str(); |
| | | pcols[4] = r.classId.c_str(); |
| | | pcols[5] = SERVO::CServoUtilsTool::getMaterialsTypeText((SERVO::MaterialsType)r.materialType).c_str(); |
| | | pcols[6] = SERVO::CServoUtilsTool::getGlassStateText((SERVO::GlsState)r.state).c_str(); |
| | | pcols[7] = r.tStart.c_str(); |
| | | pcols[8] = r.tEnd.c_str(); |
| | | pcols[9] = r.buddyId.c_str(); |
| | | pcols[10] = SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)r.aoiResult).c_str(); |
| | | pcols[11] = r.path.c_str(); |
| | | pcols[12] = r.params.c_str(); |
| | | |
| | | auto* nParent = m_listCtrl.InsertRoot(pcols); |
| | | MaybeRestoreExpandByKey(nParent, expandedKeys); |
| | | m_listCtrl.SetNodeColor(nParent, RGB(0, 0, 0), bk); |
| | | |
| | | std::vector<CString> ccols(colCount); // å ä½åªå ClassID |
| | | ccols[4] = r.buddyId.c_str(); |
| | | auto* nChild = m_listCtrl.InsertChild(nParent, ccols); |
| | | m_listCtrl.SetNodeColor(nChild, RGB(0, 0, 0), bk); |
| | | |
| | | consumed.insert(r.classId); |
| | | ++zebra; |
| | | } |
| | | |
| | | // -------- Phase 2: å©ä½æªæ¶è´¹çï¼ä½ä¸ºâåæ¡æ ¹è¡â ---------- |
| | | for (size_t i = 0; i < page.items.size(); ++i) { |
| | | const auto& r = page.items[i]; |
| | | if (consumed.count(r.classId)) continue; |
| | | |
| | | COLORREF bk = zebraBk(zebra); |
| | | |
| | | std::vector<CString> cols(colCount); |
| | | cols[1] = std::to_string(r.id).c_str(); |
| | | cols[2] = std::to_string(r.cassetteSeqNo).c_str(); |
| | | cols[3] = std::to_string(r.jobSeqNo).c_str(); |
| | | cols[4] = r.classId.c_str(); |
| | | cols[5] = SERVO::CServoUtilsTool::getMaterialsTypeText((SERVO::MaterialsType)r.materialType).c_str(); |
| | | cols[6] = SERVO::CServoUtilsTool::getGlassStateText((SERVO::GlsState)r.state).c_str(); |
| | | cols[7] = r.tStart.c_str(); |
| | | cols[8] = r.tEnd.c_str(); |
| | | cols[9] = r.buddyId.c_str(); |
| | | cols[10] = SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)r.aoiResult).c_str(); |
| | | cols[11] = r.path.c_str(); |
| | | cols[12] = r.params.c_str(); |
| | | |
| | | auto* n = m_listCtrl.InsertRoot(cols); |
| | | m_listCtrl.SetNodeColor(n, RGB(0, 0, 0), bk); |
| | | |
| | | consumed.insert(r.classId); |
| | | ++zebra; |
| | | } |
| | | |
| | | // 䏿¬¡æ§éç» |
| | | m_listCtrl.RebuildVisible(); |
| | | |
| | | // ä¸ä¸é¡µ / ä¸ä¸é¡µ |
| | | UpdatePageControls(); |
| | | |
| | | m_rebuilding = false; |
| | | } |
| | | |
| | | |
| | | void CPageGlassList::UpdatePageControls() |
| | | { |
| | | CString strPage; |
| | | strPage.Format(_T("第 %d / %d 页"), m_nCurPage, m_nTotalPages); |
| | | SetDlgItemText(IDC_LABEL_PAGE_NUMBER, strPage); |
| | | GetDlgItem(IDC_BUTTON_PREV_PAGE)->EnableWindow(m_nCurPage > 1); |
| | | GetDlgItem(IDC_BUTTON_NEXT_PAGE)->EnableWindow(m_nCurPage < m_nTotalPages); |
| | | |
| | | Resize(); |
| | | CString strPage; |
| | | strPage.Format(_T("第 %d / %d 页"), m_nCurPage, m_nTotalPages); |
| | | SetDlgItemText(IDC_LABEL_PAGE_NUMBER, strPage); |
| | | GetDlgItem(IDC_BUTTON_PREV_PAGE)->EnableWindow(m_nCurPage > 1); |
| | | GetDlgItem(IDC_BUTTON_NEXT_PAGE)->EnableWindow(m_nCurPage < m_nTotalPages); |
| | | } |
| | | |
| | | void CPageGlassList::UpdateDateFilter() |
| | | { |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME); |
| | | if (nullptr != pComboBox) { |
| | | int nIndex = pComboBox->GetCurSel(); |
| | | if (nIndex == 0) { |
| | | memset(m_szTimeStart, 0, sizeof(m_szTimeStart)); |
| | | memset(m_szTimeEnd, 0, sizeof(m_szTimeEnd)); |
| | | m_szTimeStart[0] = '\0'; |
| | | m_szTimeEnd[0] = '\0'; |
| | | } |
| | | else { |
| | | CTime time = CTime::GetCurrentTime(); |
| | | if (nIndex == 1) { |
| | | sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d 00:00:00", time.GetYear(), time.GetMonth(), time.GetDay()); |
| | | sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", time.GetYear(), time.GetMonth(), time.GetDay()); |
| | | } |
| | | else if (nIndex == 2) { |
| | | CTime time2 = time - CTimeSpan(7, 0, 0, 0); |
| | | sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d 00:00:00", time2.GetYear(), time2.GetMonth(), time2.GetDay()); |
| | | sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", time.GetYear(), time.GetMonth(), time.GetDay()); |
| | | } |
| | | else if (nIndex == 3) { |
| | | sprintf_s(m_szTimeStart, 64, "%d-%02d-01 00:00:00", time.GetYear(), time.GetMonth()); |
| | | sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", time.GetYear(), time.GetMonth(), time.GetDay()); |
| | | } |
| | | else if (nIndex == 4) { |
| | | sprintf_s(m_szTimeStart, 64, "%d-01-01 00:00:00", time.GetYear()); |
| | | sprintf_s(m_szTimeEnd, 64, "%d-12-31 23:59:59", time.GetYear()); |
| | | } |
| | | else if (nIndex == 5) { |
| | | SYSTEMTIME t1, t2; |
| | | m_dateTimeStart.GetTime(&t1); |
| | | m_dateTimeEnd.GetTime(&t2); |
| | | //sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d %02d:%02d:%02d", t1.wYear, t1.wMonth, t1.wDay, t1.wHour, t1.wMinute, t1.wSecond); |
| | | //sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d %02d:%02d:%02d", t2.wYear, t2.wMonth, t2.wDay, t2.wHour, t2.wMinute, t2.wSecond); |
| | | |
| | | sprintf_s(m_szTimeStart, 64, "%d-%02d-%02d 00:00:00", t1.wYear, t1.wMonth, t1.wDay); |
| | | sprintf_s(m_szTimeEnd, 64, "%d-%02d-%02d 23:59:59", t2.wYear, t2.wMonth, t2.wDay); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /* |
| | | void CPageGlassList::FillDataToListCtrl(const std::vector<TransferData>& vecData) |
| | | { |
| | | if (m_listCtrl.m_hWnd == nullptr) { |
| | | return; |
| | | } |
| | | |
| | | m_listCtrl.DeleteAllItems(); |
| | | for (const auto& item : vecData) { |
| | | InsertTransferData(item); |
| | | } |
| | | } |
| | | |
| | | void CPageGlassList::InsertTransferData(const TransferData& data) |
| | | { |
| | | if (m_listCtrl.m_hWnd == nullptr) { |
| | | return; |
| | | } |
| | | |
| | | int nIndex = m_listCtrl.GetItemCount(); |
| | | if (nIndex < 0) { |
| | | return; |
| | | } |
| | | |
| | | int nItem = m_listCtrl.InsertItem(nIndex, _T("")); |
| | | CString str; |
| | | str.Format(_T("%d"), data.nRecordId); |
| | | m_listCtrl.SetItemText(nItem, 1, str); |
| | | m_listCtrl.SetItemText(nItem, 2, CString(data.strStatus.c_str())); |
| | | m_listCtrl.SetItemText(nItem, 3, CString(data.strClassID.c_str())); |
| | | m_listCtrl.SetItemText(nItem, 4, CString(data.strCreateTime.c_str())); |
| | | m_listCtrl.SetItemText(nItem, 5, CString(data.strPickTime.c_str())); |
| | | m_listCtrl.SetItemText(nItem, 6, CString(data.strPlaceTime.c_str())); |
| | | m_listCtrl.SetItemText(nItem, 7, CString(data.strEndTime.c_str())); |
| | | m_listCtrl.SetItemText(nItem, 8, CString(data.strDescription.c_str())); |
| | | } |
| | | */ |
| | | // CPageTransferLog æ¶æ¯å¤çç¨åº |
| | | |
| | | BOOL CPageGlassList::OnInitDialog() |
| | | { |
| | | CDialogEx::OnInitDialog(); |
| | | CDialogEx::OnInitDialog(); |
| | | |
| | | // TODO: 卿¤æ·»å é¢å¤çåå§å |
| | | SetTimer(1, 3000, nullptr); |
| | | // 宿¶å¨ï¼1=åå§å订é
ï¼2=卿巿°ï¼åªå¢éï¼ |
| | | SetTimer(1, 3000, nullptr); |
| | | SetTimer(2, 2000, nullptr); |
| | | |
| | | // ä¸ææ¡æ§ä»¶ |
| | | InitStatusCombo(); |
| | | InitTimeRangeCombo(); |
| | | // ä¸ææ¡æ§ä»¶ |
| | | InitStatusCombo(); |
| | | InitTimeRangeCombo(); |
| | | |
| | | // æ¥ææ§ä»¶ |
| | | InitDateTimeControls(); |
| | | // æ¥ææ§ä»¶ |
| | | InitDateTimeControls(); |
| | | |
| | | // æ¥è¡¨æ§ä»¶ |
| | | CString strIniFile, strItem; |
| | | strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir); |
| | | // æ¥è¡¨æ§ä»¶ |
| | | CString strIniFile, strItem; |
| | | strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir); |
| | | |
| | | DWORD dwStyle = m_listCtrl.GetExtendedStyle(); |
| | | dwStyle |= LVS_EX_FULLROWSELECT; |
| | | dwStyle |= LVS_EX_GRIDLINES; |
| | | m_listCtrl.SetExtendedStyle(dwStyle); |
| | | DWORD dwStyle = m_listCtrl.GetExtendedStyle(); |
| | | dwStyle |= LVS_EX_FULLROWSELECT; |
| | | dwStyle |= LVS_EX_GRIDLINES; |
| | | dwStyle |= LVS_EX_DOUBLEBUFFER; |
| | | m_listCtrl.SetExtendedStyle(dwStyle); |
| | | |
| | | HIMAGELIST imageList = ImageList_Create(24, 24, ILC_COLOR24, 1, 1); |
| | | ListView_SetImageList(m_listCtrl.GetSafeHwnd(), imageList, LVSIL_SMALL); |
| | | HIMAGELIST imageList = ImageList_Create(24, 24, ILC_COLOR24, 1, 1); |
| | | ListView_SetImageList(m_listCtrl.GetSafeHwnd(), imageList, LVSIL_SMALL); |
| | | |
| | | CString headers[] = { |
| | | _T(""), |
| | | _T("Cassette Sequence No"), |
| | | _T("Job Sequence No"), |
| | | _T("Class ID"), |
| | | _T("ç©æç±»å"), |
| | | _T("ç¶æ"), |
| | | _T("å·¥èºå¼å§æ¶é´"), |
| | | _T("å·¥èºç»ææ¶é´"), |
| | | _T("é¦å®Glass ID"), |
| | | _T("AOIæ£æµç»æ"), |
| | | _T("è·¯å¾"), |
| | | _T("å·¥èºåæ°") |
| | | }; |
| | | int widths[] = { 0, 80, 80, 100, 120, 120, 120, 120, 200, 200, 200, 200 }; |
| | | for (int i = 0; i < _countof(headers); ++i) { |
| | | strItem.Format(_T("Col_%d_Width"), i); |
| | | widths[i] = GetPrivateProfileInt("GlassListCtrl", strItem, widths[i], strIniFile); |
| | | m_listCtrl.InsertColumn(i, headers[i], LVCFMT_LEFT, widths[i]); |
| | | } |
| | | m_listCtrl.SetColumnWidth(10, LVSCW_AUTOSIZE_USEHEADER); |
| | | CString headers[] = { |
| | | _T(""), |
| | | _T("id"), |
| | | _T("Cassette SN"), |
| | | _T("Job SN"), |
| | | _T("Class ID"), |
| | | _T("ç©æç±»å"), |
| | | _T("ç¶æ"), |
| | | _T("å·¥èºå¼å§æ¶é´"), |
| | | _T("å·¥èºç»ææ¶é´"), |
| | | _T("é¦å®Glass ID"), |
| | | _T("AOIæ£æµç»æ"), |
| | | _T("è·¯å¾"), |
| | | _T("å·¥èºåæ°") |
| | | }; |
| | | int widths[] = { 24, 80, 80, 80, 100, 120, 120, 120, 120, 200, 200, 200, 200 }; |
| | | for (int i = 0; i < _countof(headers); ++i) { |
| | | strItem.Format(_T("Col_%d_Width"), i); |
| | | int def = widths[i]; |
| | | widths[i] = GetPrivateProfileInt("GlassListCtrl", strItem, def, strIniFile); |
| | | if (i == 0 && widths[i] < 16) widths[i] = 24; // 让ä¸è§å¾æ æç©ºé´å±ç¤º |
| | | m_listCtrl.InsertColumn(i, headers[i], i == 0 ? LVCFMT_RIGHT : LVCFMT_LEFT, widths[i]); |
| | | } |
| | | // äºæ¬¡å
åºï¼é²æ¢ ini åè¿äº 0 |
| | | if (m_listCtrl.GetColumnWidth(0) < 16) m_listCtrl.SetColumnWidth(0, 24); |
| | | m_listCtrl.SetPopupFullTextColumns({ 11, 12 }); |
| | | |
| | | Resize(); |
| | | OnBnClickedButtonSearch(); // 触å䏿¬¡æ¥è¯¢ä¸é¦å±å¡«å
|
| | | |
| | | // è®¡ç®æ»é¡µæ° |
| | | /* |
| | | int nTotalRecords = TransferManager::getInstance().getTotalTransferCountAll(); |
| | | m_nTotalPages = (nTotalRecords + PAGE_SIZE - 1) / PAGE_SIZE; |
| | | m_nCurPage = 1; |
| | | */ |
| | | |
| | | Resize(); |
| | | LoadTransfers(); |
| | | |
| | | return TRUE; // return TRUE unless you set the focus to a control |
| | | // å¼å¸¸: OCX 屿§é¡µåºè¿å FALSE |
| | | return TRUE; // return TRUE unless you set the focus to a control |
| | | } |
| | | |
| | | HBRUSH CPageGlassList::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) |
| | | { |
| | | if (nCtlColor == CTLCOLOR_STATIC) { |
| | | pDC->SetBkColor(m_crBkgnd); |
| | | } |
| | | |
| | | if (m_hbrBkgnd == nullptr) { |
| | | m_hbrBkgnd = CreateSolidBrush(m_crBkgnd); |
| | | } |
| | | |
| | | return m_hbrBkgnd; |
| | | if (nCtlColor == CTLCOLOR_STATIC) { |
| | | pDC->SetBkColor(m_crBkgnd); |
| | | } |
| | | if (m_hbrBkgnd == nullptr) { |
| | | m_hbrBkgnd = CreateSolidBrush(m_crBkgnd); |
| | | } |
| | | return m_hbrBkgnd; |
| | | } |
| | | |
| | | void CPageGlassList::OnDestroy() |
| | | { |
| | | CDialogEx::OnDestroy(); |
| | | if (m_hbrBkgnd != nullptr) { |
| | | ::DeleteObject(m_hbrBkgnd); |
| | | m_hbrBkgnd = nullptr; |
| | | } |
| | | if (m_pObserver != nullptr) { |
| | | m_pObserver->unsubscribe(); |
| | | m_pObserver = nullptr; |
| | | } |
| | | CDialogEx::OnDestroy(); |
| | | if (m_hbrBkgnd != nullptr) { |
| | | ::DeleteObject(m_hbrBkgnd); |
| | | m_hbrBkgnd = nullptr; |
| | | } |
| | | if (m_pObserver != nullptr) { |
| | | m_pObserver->unsubscribe(); |
| | | m_pObserver = nullptr; |
| | | } |
| | | |
| | | // ä¿åå宽 |
| | | CString strIniFile, strItem, strTemp; |
| | | strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir); |
| | | CHeaderCtrl* pHeader = m_listCtrl.GetHeaderCtrl(); |
| | | for (int i = 0; i < pHeader->GetItemCount(); i++) { |
| | | RECT rect; |
| | | pHeader->GetItemRect(i, &rect); |
| | | strItem.Format(_T("Col_%d_Width"), i); |
| | | strTemp.Format(_T("%d"), rect.right - rect.left); |
| | | WritePrivateProfileString("GlassListCtrl", strItem, strTemp, strIniFile); |
| | | } |
| | | // ä¿åå宽ï¼é¦åå
åºï¼é¿å
æ 0 ååå»ï¼ |
| | | CString strIniFile, strItem, strTemp; |
| | | strIniFile.Format(_T("%s\\configuration.ini"), (LPTSTR)(LPCTSTR)theApp.m_strAppDir); |
| | | CHeaderCtrl* pHeader = m_listCtrl.GetHeaderCtrl(); |
| | | if (pHeader) { |
| | | for (int i = 0; i < pHeader->GetItemCount(); i++) { |
| | | RECT rect; |
| | | pHeader->GetItemRect(i, &rect); |
| | | strItem.Format(_T("Col_%d_Width"), i); |
| | | int w = rect.right - rect.left; |
| | | if (i == 0 && w < 16) w = 24; |
| | | strTemp.Format(_T("%d"), w); |
| | | WritePrivateProfileString("GlassListCtrl", strItem, strTemp, strIniFile); |
| | | } |
| | | } |
| | | } |
| | | |
| | | void CPageGlassList::OnSize(UINT nType, int cx, int cy) |
| | | { |
| | | CDialogEx::OnSize(nType, cx, cy); |
| | | Resize(); |
| | | CDialogEx::OnSize(nType, cx, cy); |
| | | Resize(); |
| | | } |
| | | |
| | | void CPageGlassList::OnTimer(UINT_PTR nIDEvent) |
| | | { |
| | | if (nIDEvent == 1) { |
| | | KillTimer(1); |
| | | InitRxWindow(); |
| | | } |
| | | CDialogEx::OnTimer(nIDEvent); |
| | | if (nIDEvent == 1) { |
| | | KillTimer(1); |
| | | InitRxWindow(); |
| | | } |
| | | else if (nIDEvent == 2) { |
| | | UpdateWipData(); // åªåå¢éï¼ä¸é建 |
| | | } |
| | | |
| | | CDialogEx::OnTimer(nIDEvent); |
| | | } |
| | | |
| | | void CPageGlassList::OnCbnSelchangeComboDatetime() |
| | | { |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME); |
| | | int nIndex = pComboBox->GetCurSel(); |
| | | int nCount = pComboBox->GetCount(); |
| | | m_dateTimeStart.EnableWindow(nIndex == nCount - 1); |
| | | m_dateTimeEnd.EnableWindow(nIndex == nCount - 1); |
| | | |
| | | // æ´æ°æ¥æè¿æ»¤å¨å页颿°æ® |
| | | UpdateDateFilter(); |
| | | LoadTransfers(); |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME); |
| | | int nIndex = pComboBox->GetCurSel(); |
| | | int nCount = pComboBox->GetCount(); |
| | | m_dateTimeStart.EnableWindow(nIndex == nCount - 1); |
| | | m_dateTimeEnd.EnableWindow(nIndex == nCount - 1); |
| | | } |
| | | |
| | | void CPageGlassList::OnCbnSelchangeComboStatusFilter() |
| | | { |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_STATUS_FILTER); |
| | | int nIndex = pComboBox->GetCurSel(); |
| | | if (nIndex == 0) { |
| | | m_strStatus.clear(); |
| | | } |
| | | else { |
| | | CString cstrText; |
| | | pComboBox->GetLBText(nIndex, cstrText); |
| | | m_strStatus = CT2A(cstrText); |
| | | } |
| | | LoadTransfers(); |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_STATUS_FILTER); |
| | | int nIndex = pComboBox->GetCurSel(); |
| | | if (nIndex == 0) { |
| | | m_strStatus.clear(); |
| | | } |
| | | else { |
| | | CString cstrText; |
| | | pComboBox->GetLBText(nIndex, cstrText); |
| | | m_strStatus = CT2A(cstrText); |
| | | } |
| | | } |
| | | |
| | | void CPageGlassList::OnBnClickedButtonSearch() |
| | | { |
| | | // è·åå
³é®åè¾å
¥æ¡å
容 |
| | | CString strKeyword; |
| | | GetDlgItemText(IDC_EDIT_KEYWORD, strKeyword); |
| | | m_strKeyword = CT2A(strKeyword); |
| | | // è·åå
³é®åè¾å
¥æ¡å
容 |
| | | CString strKeyword; |
| | | GetDlgItemText(IDC_EDIT_KEYWORD, strKeyword); |
| | | m_filters.keyword = CT2A(strKeyword); |
| | | |
| | | // æ´æ°æ¥æè¿æ»¤å¨å页颿°æ® |
| | | UpdateDateFilter(); |
| | | LoadTransfers(); |
| | | CComboBox* pComboBox = (CComboBox*)GetDlgItem(IDC_COMBO_DATETIME); |
| | | int index = pComboBox->GetCurSel(); |
| | | if (index == 0) { |
| | | // ä¸é |
| | | m_filters.tStartFrom = std::nullopt; |
| | | m_filters.tStartTo = std::nullopt; |
| | | } |
| | | else if (index == 1) { |
| | | auto [fromUtc, toUtc] = CToolUnits::CalcQuickRangeUtc(QuickRange::Today); |
| | | m_filters.tStartFrom = fromUtc; |
| | | m_filters.tStartTo = toUtc; |
| | | } |
| | | else if (index == 2) { |
| | | auto [fromUtc, toUtc] = CToolUnits::CalcQuickRangeUtc(QuickRange::Last7Days); |
| | | m_filters.tStartFrom = fromUtc; |
| | | m_filters.tStartTo = toUtc; |
| | | } |
| | | else if (index == 3) { |
| | | auto [fromUtc, toUtc] = CToolUnits::CalcQuickRangeUtc(QuickRange::ThisMonth); |
| | | m_filters.tStartFrom = fromUtc; |
| | | m_filters.tStartTo = toUtc; |
| | | } |
| | | else if (index == 4) { |
| | | auto [fromUtc, toUtc] = CToolUnits::CalcQuickRangeUtc(QuickRange::ThisYear); |
| | | m_filters.tStartFrom = fromUtc; |
| | | m_filters.tStartTo = toUtc; |
| | | } |
| | | else if (index == 5) { |
| | | // èªå®ä¹ |
| | | std::chrono::system_clock::time_point tp; |
| | | if (CToolUnits::GetCtrlDateRangeUtc_StartOfDay(m_dateTimeStart, tp)) m_filters.tStartFrom = tp; |
| | | if (CToolUnits::GetCtrlDateRangeUtc_EndOfDay(m_dateTimeEnd, tp)) m_filters.tStartTo = tp; |
| | | } |
| | | |
| | | #if USE_FAKE_DB_DEMO |
| | | long long total = _fake_total_count(); |
| | | #else |
| | | auto& db = GlassLogDb::Instance(); |
| | | long long total = db.count(m_filters); |
| | | #endif |
| | | m_nTotalPages = (PAGE_SIZE > 0) ? int((total + PAGE_SIZE - 1) / PAGE_SIZE) : 1; |
| | | |
| | | LoadData(); |
| | | } |
| | | |
| | | void CPageGlassList::OnBnClickedButtonExport() |
| | | { |
| | | CFileDialog fileDialog(FALSE, _T("csv"), NULL, OFN_HIDEREADONLY, _T("CSV Files (*.csv)|*.csv||")); |
| | | if (fileDialog.DoModal() != IDOK) { |
| | | return; |
| | | } |
| | | CFileDialog fileDialog(FALSE, _T("csv"), NULL, OFN_HIDEREADONLY, _T("CSV Files (*.csv)|*.csv||")); |
| | | if (fileDialog.DoModal() != IDOK) { |
| | | return; |
| | | } |
| | | |
| | | CStdioFile file; |
| | | if (!file.Open(fileDialog.GetPathName(), CFile::modeCreate | CFile::modeWrite | CFile::typeText)) { |
| | | AfxMessageBox(_T("å建æä»¶å¤±è´¥ï¼")); |
| | | return; |
| | | } |
| | | |
| | | CString strHeader = _T("ä»»å¡ID,ç¶æ,ClassID,å建æ¶é´,åçæ¶é´,æ¾çæ¶é´,ç»ææ¶é´,æè¿°\n"); |
| | | file.WriteString(strHeader); |
| | | |
| | | for (int i = 0; i < m_listCtrl.GetItemCount(); ++i) { |
| | | CString row; |
| | | for (int j = 1; j <= 8; ++j) { |
| | | row += m_listCtrl.GetItemText(i, j); |
| | | if (j != 8) { |
| | | row += ","; |
| | | } |
| | | } |
| | | row += "\n"; |
| | | file.WriteString(row); |
| | | } |
| | | file.Close(); |
| | | // å¯¼åº CSVï¼å¯¼åºç¬¦å filters çâå
¨é¨è®°å½âï¼ä¸åå页éå¶ï¼ |
| | | auto& db = GlassLogDb::Instance(); |
| | | std::string csvPath((LPTSTR)(LPCTSTR)fileDialog.GetPathName()); |
| | | if (db.exportCsv(csvPath, m_filters) > 0) { |
| | | AfxMessageBox("导åºCSVæåï¼"); |
| | | } |
| | | } |
| | | |
| | | void CPageGlassList::OnBnClickedButtonPrevPage() |
| | | { |
| | | SERVO::CGlass g; |
| | | g.setID("GLS-001"); |
| | | g.setType(SERVO::MaterialsType::G1); |
| | | g.setOriginPort(1, 5); |
| | | g.setScheduledForProcessing(TRUE); |
| | | g.m_failReason = "none"; |
| | | g.markQueued(); |
| | | g.markStart(); |
| | | |
| | | |
| | | // æ·»å åæ° |
| | | CParam p1("æ ¡æ£å¯¹ä½å»¶æ¶", "P001", "ms", 123); |
| | | CParam p2("温度", "P002", "degC", 25.5); |
| | | g.getParams().push_back(p1); |
| | | g.getParams().push_back(p2); |
| | | |
| | | // 设置 JobDataS |
| | | SERVO::CJobDataS* js = g.getJobDataS(); |
| | | js->setCassetteSequenceNo(10); |
| | | js->setJobSequenceNo(20); |
| | | js->setLotId("LOT-ABC"); |
| | | js->setGlass1Id("GLS-001"); |
| | | |
| | | // æ·»å Path |
| | | g.addPath(100, 1); |
| | | SERVO::CPath* tail = g.getPath()->getTailPath(); |
| | | tail->setInTime(111111); |
| | | tail->setOutTime(222222); |
| | | tail->setInspResult(SERVO::InspResult::Pass); |
| | | tail->processEnd(); |
| | | return; |
| | | // 2. 转为 JSON |
| | | std::string jsonText = GlassJson::ToPrettyString(g); |
| | | TRACE("åºååç»æ:\n%s\n\n", jsonText.c_str()); |
| | | |
| | | // 3. ååºåå |
| | | SERVO::CGlass g2; |
| | | std::string err; |
| | | if (!GlassJson::FromString(jsonText, g2, &err)) { |
| | | TRACE("è§£æå¤±è´¥: %s\n", err.c_str()); |
| | | return; |
| | | } |
| | | |
| | | // 4. æå°éªè¯ |
| | | TRACE("ååºåååçID: %s\n", g2.getID().c_str()); |
| | | TRACE("ååºåååçåæ°æ°é: %d\n", (int)g2.getParams().size()); |
| | | if (!g2.getParams().empty()) { |
| | | TRACE("第ä¸ä¸ªåæ°å: %s å¼=%d\n", |
| | | g2.getParams()[0].getName().c_str(), |
| | | g2.getParams()[0].getIntValue()); |
| | | } |
| | | |
| | | |
| | | |
| | | if (m_nCurPage > 1) { |
| | | m_nCurPage--; |
| | | UpdatePageData(); |
| | | } |
| | | |
| | | if (m_nCurPage > 1) { |
| | | m_nCurPage--; |
| | | UpdatePageData(); |
| | | } |
| | | } |
| | | |
| | | void CPageGlassList::OnBnClickedButtonNextPage() |
| | | { |
| | | if (m_nCurPage < m_nTotalPages) { |
| | | m_nCurPage++; |
| | | UpdatePageData(); |
| | | } |
| | | } |
| | | if (m_nCurPage < m_nTotalPages) { |
| | | m_nCurPage++; |
| | | UpdatePageData(); |
| | | } |
| | | } |
| | | |
| | | void CPageGlassList::OnShowFullText(NMHDR* pNMHDR, LRESULT* pResult) |
| | | { |
| | | auto* p = reinterpret_cast<NMC_ELC_SHOWFULLTEXT*>(pNMHDR); |
| | | |
| | | // è¿éææ¶ç¨æ¶æ¯æ¡æ¾ç¤ºï¼åç»å¯æ¢æä½ ç详æ
页 |
| | | CString strNewMsg = p->text; |
| | | strNewMsg.Replace(_T(","), _T("\n")); |
| | | MessageBox(strNewMsg, _T("详ç»ä¿¡æ¯"), MB_OK | MB_ICONINFORMATION); |
| | | *pResult = 0; |
| | | } |
| | | |
| | | void CPageGlassList::UpdateWipData() |
| | | { |
| | | // åªå¨ç¬¬ 1 页巿° WIPï¼å
¶å®é¡µä¸å¨ |
| | | if (m_nCurPage != 1) return; |
| | | // è¥åå¥½å¨ UpdatePageData() é建æé´ï¼è·³è¿è¿è½®å¢éï¼é¿å
äºç¸å¹²æ° |
| | | if (m_rebuilding) return; |
| | | |
| | | const int colCount = m_listCtrl.GetHeaderCtrl() ? m_listCtrl.GetHeaderCtrl()->GetItemCount() : 0; |
| | | if (colCount <= 0) return; |
| | | |
| | | // 1) æ¶éå½åå¯è§éçâWIP è¡âï¼ç¬¬1å id ä¸ºç©ºï¼ |
| | | // a) wipRowByIdï¼classId -> (row, node*)ï¼æ¶éæ ¹+åï¼ä¾¿äºå¤æâbuddy æ¯å¦å·²å¨å¯è§è¡¨ä¸â |
| | | // b) wipRootByIdï¼classId -> node*ï¼ä»
æ¶éæ ¹èç¹ï¼ä¾¿äºåªå¯¹âæ ¹âè¡¥å项 |
| | | std::unordered_map<std::string, std::pair<int, CExpandableListCtrl::Node*>> wipRowById; |
| | | std::unordered_map<std::string, CExpandableListCtrl::Node*> wipRootById; |
| | | for (int row = 0; row < m_listCtrl.GetItemCount(); ++row) { |
| | | CString idDb = m_listCtrl.GetItemText(row, 1); // 第1忝 DB id |
| | | if (!idDb.IsEmpty()) continue; // æ id çæ¯ DB è¡ï¼è·³è¿ |
| | | |
| | | auto* node = m_listCtrl.GetNodeByVisibleIndex(row); |
| | | CString cls = m_listCtrl.GetItemText(row, 4); // 第4å Class ID |
| | | #ifdef _UNICODE |
| | | std::string key = CT2A(cls); |
| | | #else |
| | | std::string key = cls.GetString(); |
| | | #endif |
| | | wipRowById[key] = { row, node }; |
| | | if (node && node->parent == nullptr) { |
| | | wipRootById[key] = node; // ä»
æ ¹èç¹è¿å
¥è¿ä¸ªè¡¨ |
| | | } |
| | | } |
| | | |
| | | // 2) æå½å WIP å表 |
| | | std::vector<SERVO::CGlass*> wipGlasses; |
| | | theApp.m_model.m_master.getWipGlasses(wipGlasses); |
| | | std::vector<SERVO::CGlass*> tempRetain = wipGlasses; // ç¨åç»ä¸ release |
| | | |
| | | auto makeColsFromWip = [&](SERVO::CGlass* g) { |
| | | std::vector<CString> cols(colCount); |
| | | cols[1] = _T(""); // WIP 没 DB id |
| | | cols[2] = std::to_string(g->getCassetteSequenceNo()).c_str(); |
| | | cols[3] = std::to_string(g->getJobSequenceNo()).c_str(); |
| | | cols[4] = g->getID().c_str(); |
| | | cols[5] = SERVO::CServoUtilsTool::getMaterialsTypeText(g->getType()).c_str(); |
| | | cols[6] = SERVO::CServoUtilsTool::getGlassStateText(g->state()).c_str(); |
| | | cols[7] = CToolUnits::TimePointToLocalString(g->tStart()).c_str(); |
| | | cols[8] = CToolUnits::TimePointToLocalString(g->tEnd()).c_str(); |
| | | cols[9] = g->getBuddyId().c_str(); |
| | | cols[10] = SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)g->getAOIInspResult()).c_str(); |
| | | cols[11] = g->getPathDescription().c_str(); |
| | | cols[12] = g->getParamsDescription().c_str(); |
| | | return cols; |
| | | }; |
| | | |
| | | // 2.1 æå»ºâææ° WIP é®éâï¼å« buddyï¼ä¸å½ä¸è¿æ»¤ï¼ï¼ç¨äºæ£æµâ缺失/å é¤â |
| | | std::unordered_set<std::string> newWipKeys; |
| | | for (auto* g : wipGlasses) { |
| | | if (!GlassMatchesFilters(*g, m_filters)) continue; |
| | | #ifdef _UNICODE |
| | | newWipKeys.insert(CT2A(CString(g->getID().c_str()))); |
| | | #else |
| | | newWipKeys.insert(g->getID()); |
| | | #endif |
| | | if (auto* b = g->getBuddy()) { |
| | | if (GlassMatchesFilters(*b, m_filters)) { |
| | | #ifdef _UNICODE |
| | | newWipKeys.insert(CT2A(CString(b->getID().c_str()))); |
| | | #else |
| | | newWipKeys.insert(b->getID()); |
| | | #endif |
| | | } |
| | | } |
| | | } |
| | | |
| | | bool needRebuildRemoval = false; // WIP åå°/æ¸
空ï¼éè¦æ´é¡µé建 |
| | | bool needRebuildChildren = false; // ç»æååï¼æ°å¢å |
| | | bool needRebuildAllForNewRoot = false; // æ°å¢æ ¹ï¼ä¿è¯ WIP ä»å¨é¡¶é¨ï¼ |
| | | std::vector<int> rowsToRedraw; // ä»
ææ¬åå |
| | | |
| | | // å¯è§é䏿使°æ°æ®é没æ -> 触åâå é¤/åå°âçæ´é¡µé建 |
| | | for (const auto& kv : wipRowById) { |
| | | if (newWipKeys.find(kv.first) == newWipKeys.end()) { needRebuildRemoval = true; break; } |
| | | } |
| | | |
| | | // UI ç¶æï¼å½éè¦é建æ¶ä½¿ç¨ï¼ |
| | | std::vector<CExpandableListCtrl::Node*> savedSel; |
| | | CExpandableListCtrl::Node* savedTop = nullptr; |
| | | |
| | | // 3) é个å¤ç WIPï¼å·²åå¨ -> 就尿´æ°ï¼å¿
è¦æ¶âåªå¯¹æ ¹è¡¥å项â |
| | | // ä¸åå¨ -> ä¼å
æå° buddy 容å¨ï¼å¦åè§¦åæ´é¡µéå»ºï¼æ°æ ¹ä¿æé¡¶é¨ï¼ |
| | | for (auto* g : wipGlasses) { |
| | | if (!GlassMatchesFilters(*g, m_filters)) continue; |
| | | |
| | | #ifdef _UNICODE |
| | | std::string cid = CT2A(CString(g->getID().c_str())); |
| | | #else |
| | | std::string cid = g->getID(); |
| | | #endif |
| | | |
| | | auto itAny = wipRowById.find(cid); |
| | | if (itAny != wipRowById.end()) { |
| | | // (A) å·²åå¨ï¼ä»
æ´æ°ææ¡ & éç»è¯¥è¡ |
| | | int row = itAny->second.first; |
| | | m_listCtrl.SetItemText(row, 2, std::to_string(g->getCassetteSequenceNo()).c_str()); |
| | | m_listCtrl.SetItemText(row, 3, std::to_string(g->getJobSequenceNo()).c_str()); |
| | | m_listCtrl.SetItemText(row, 4, g->getID().c_str()); |
| | | m_listCtrl.SetItemText(row, 5, SERVO::CServoUtilsTool::getMaterialsTypeText(g->getType()).c_str()); |
| | | m_listCtrl.SetItemText(row, 6, SERVO::CServoUtilsTool::getGlassStateText(g->state()).c_str()); |
| | | m_listCtrl.SetItemText(row, 7, CToolUnits::TimePointToLocalString(g->tStart()).c_str()); |
| | | m_listCtrl.SetItemText(row, 8, CToolUnits::TimePointToLocalString(g->tEnd()).c_str()); |
| | | m_listCtrl.SetItemText(row, 9, g->getBuddyId().c_str()); |
| | | m_listCtrl.SetItemText(row, 10, SERVO::CServoUtilsTool::getInspResultText((SERVO::InspResult)g->getAOIInspResult()).c_str()); |
| | | m_listCtrl.SetItemText(row, 11, g->getPathDescription().c_str()); |
| | | m_listCtrl.SetItemText(row, 12, g->getParamsDescription().c_str()); |
| | | rowsToRedraw.push_back(row); |
| | | |
| | | // ââ é¡ºå¸¦å·æ° buddy åè¡ï¼å¦æå®å·²å¨å¯è§è¡¨éï¼ââ |
| | | if (SERVO::CGlass* b = g->getBuddy()) { |
| | | #ifdef _UNICODE |
| | | std::string bid = CT2A(CString(b->getID().c_str())); |
| | | #else |
| | | std::string bid = b->getID(); |
| | | #endif |
| | | auto itChildAny = wipRowById.find(bid); |
| | | if (itChildAny != wipRowById.end()) { |
| | | int crow = itChildAny->second.first; |
| | | auto bcols = makeColsFromWip(b); |
| | | ApplyColsToRow(m_listCtrl, crow, bcols); |
| | | rowsToRedraw.push_back(crow); |
| | | } |
| | | } |
| | | |
| | | // ââ åªå¯¹âæ ¹èç¹âè¡¥å项ï¼ä¸ä»
å½ buddy å°æªåºç°å¨å¯è§è¡¨ï¼ä¸æ ¹ä¸ä¹æ²¡æè¯¥ buddy ââ |
| | | SERVO::CGlass* b = g->getBuddy(); |
| | | if (b) { |
| | | auto itRoot = wipRootById.find(cid); |
| | | if (itRoot != wipRootById.end()) { |
| | | CExpandableListCtrl::Node* container = itRoot->second; |
| | | |
| | | CString newBuddyCid = b->getID().c_str(); |
| | | #ifdef _UNICODE |
| | | std::string newBid = CT2A(newBuddyCid); |
| | | #else |
| | | std::string newBid = newBuddyCid.GetString(); |
| | | #endif |
| | | |
| | | // ç°æå®¹å¨ä¸çâ第ä¸ä¸ªå classIdâï¼å¦ææçè¯ï¼ |
| | | CString oldChildCid; |
| | | if (!container->children.empty() && container->children[0] && container->children[0]->cols.size() > 4) |
| | | oldChildCid = container->children[0]->cols[4]; |
| | | |
| | | bool buddyExistsAnywhere = (wipRowById.find(newBid) != wipRowById.end()); |
| | | bool hasChildAlready = NodeHasChildWithClassId(container, newBuddyCid); |
| | | |
| | | // å
³ç³»æ¯å¦åçååï¼ï¼oldChildCid ä¸ newBuddyCid ä¸åï¼ææåä½ç°å¨æ²¡ buddyï¼ |
| | | bool relationChanged = |
| | | (!oldChildCid.IsEmpty() && newBuddyCid.IsEmpty()) || |
| | | (oldChildCid.IsEmpty() && !newBuddyCid.IsEmpty()) || |
| | | (!oldChildCid.IsEmpty() && !newBuddyCid.IsEmpty() && |
| | | oldChildCid.CompareNoCase(newBuddyCid) != 0); |
| | | |
| | | if (relationChanged) { |
| | | needRebuildAllForNewRoot = true; // é¿å
é夿ååæè½½ |
| | | } |
| | | else { |
| | | // å
³ç³»æªåï¼è¥ buddy ä¸å¨å¯è§è¡¨ä¸å®¹å¨ä¸ä¹æ²¡æï¼åè¡¥å |
| | | if (!buddyExistsAnywhere && !hasChildAlready) { |
| | | if (!needRebuildChildren) { CaptureUiState(m_listCtrl, savedSel, savedTop); } |
| | | needRebuildChildren = true; |
| | | auto cols = makeColsFromWip(b); |
| | | auto* ch = m_listCtrl.InsertChild(container, cols); |
| | | m_listCtrl.SetNodeColor(ch, kWipText, kWipChildBk); // åï¼æµ
è² |
| | | m_listCtrl.SetNodeColor(container, kWipText, kWipParentBk); // ç¶ï¼åºç¡ç»¿ |
| | | } |
| | | // è¥å·²æåï¼åæ¥å·æ°åè¡ææ¬ä¸é¢è² |
| | | else if (hasChildAlready) { |
| | | for (auto& ch : container->children) { |
| | | if (ch && ch->cols.size() > 4 && ch->cols[4].CompareNoCase(newBuddyCid) == 0) { |
| | | auto cols = makeColsFromWip(b); |
| | | ch->cols = cols; // æ´æ°åºå±æ°æ® |
| | | // å¯è§è¡å·æ° |
| | | for (int r = 0; r < m_listCtrl.GetItemCount(); ++r) { |
| | | if (m_listCtrl.GetNodeByVisibleIndex(r) == ch.get()) { |
| | | for (int c = 1; c < (int)cols.size(); ++c) |
| | | m_listCtrl.SetItemText(r, c, cols[c]); |
| | | rowsToRedraw.push_back(r); |
| | | break; |
| | | } |
| | | } |
| | | m_listCtrl.SetNodeColor(ch.get(), kWipText, kWipChildBk); |
| | | m_listCtrl.SetNodeColor(container, kWipText, kWipParentBk); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // è¥å½åæ¯âåèç¹âï¼ä¸å¨è¿éè°æ´ç¶åå
³ç³»ï¼è®©âå
³ç³»ååâèµ°å
¨éé建 |
| | | } |
| | | else { |
| | | // 没æ buddyï¼å¦æå®¹å¨ä¸ç°å¨æåï¼ä¹ç®å
³ç³»ååï¼è§¦åé建 |
| | | auto itRoot = wipRootById.find(cid); |
| | | if (itRoot != wipRootById.end()) { |
| | | CExpandableListCtrl::Node* container = itRoot->second; |
| | | if (!container->children.empty()) |
| | | needRebuildAllForNewRoot = true; |
| | | } |
| | | } |
| | | } |
| | | else { |
| | | // (B) ä¸åå¨ï¼æ°å¢ |
| | | // å
å°è¯âæå° buddy ç容卿 ¹âä¸é¢ï¼ |
| | | // è¥ buddy ä¸å¨å½åå¯è§è¡¨ï¼å触åå
¨éé建ï¼ä¿è¯ WIP é¡¶é¨ï¼ã |
| | | SERVO::CGlass* b = g->getBuddy(); |
| | | CExpandableListCtrl::Node* container = nullptr; |
| | | |
| | | if (b) { |
| | | #ifdef _UNICODE |
| | | std::string bid = CT2A(CString(b->getID().c_str())); |
| | | #else |
| | | std::string bid = b->getID(); |
| | | #endif |
| | | auto itB = wipRowById.find(bid); |
| | | if (itB != wipRowById.end()) { |
| | | CExpandableListCtrl::Node* buddyNode = itB->second.second; |
| | | container = buddyNode ? (buddyNode->parent ? buddyNode->parent : buddyNode) : nullptr; |
| | | } |
| | | } |
| | | |
| | | if (container) { |
| | | // buddy 容å¨åå¨ï¼æ g ä½ä¸ºâåè¡âæä¸å»ï¼é¿å
éå¤ï¼ |
| | | CString cidCs = g->getID().c_str(); |
| | | if (!NodeHasChildWithClassId(container, cidCs)) { |
| | | if (!needRebuildChildren) { CaptureUiState(m_listCtrl, savedSel, savedTop); } |
| | | needRebuildChildren = true; |
| | | |
| | | auto cols = makeColsFromWip(g); |
| | | auto* ch = m_listCtrl.InsertChild(container, cols); |
| | | // åï¼æ´æµ
ï¼ç¶ï¼åºç¡ç»¿ï¼å
åºï¼ |
| | | m_listCtrl.SetNodeColor(ch, kWipText, kWipChildBk); |
| | | m_listCtrl.SetNodeColor(container, kWipText, kWipParentBk); |
| | | } |
| | | } |
| | | else { |
| | | // buddy ä¸å¨å¯è§è¡¨ï¼ä¸ºäºä¿æâWIP æ°¸è¿å¨é¡¶é¨âï¼è§¦å䏿¬¡å
¨éé建 |
| | | needRebuildAllForNewRoot = true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 4) åºç¨ UI æ´æ° ââ æâå é¤/åå°âçæ
åµå¹¶å
¥å
¨ééå»ºåæ¯ |
| | | if (needRebuildAllForNewRoot || needRebuildRemoval) { |
| | | auto selKeys = SnapshotSelectedKeys(m_listCtrl); |
| | | auto topKey = SnapshotTopKey(m_listCtrl); |
| | | UpdatePageData(); // å
¨éé建ï¼WIP é¡¶é¨ & å 餿 æé¡¹ï¼ |
| | | RestoreSelectionByKeys(m_listCtrl, selKeys); |
| | | RestoreTopByKey(m_listCtrl, topKey); |
| | | } |
| | | else if (needRebuildChildren) { |
| | | auto selKeys = SnapshotSelectedKeys(m_listCtrl); |
| | | auto topKey = SnapshotTopKey(m_listCtrl); |
| | | m_listCtrl.RebuildVisible(); // ä»
ç»æååï¼å åï¼ |
| | | RestoreSelectionByKeys(m_listCtrl, selKeys); |
| | | RestoreTopByKey(m_listCtrl, topKey); |
| | | } |
| | | else { |
| | | for (int row : rowsToRedraw) // ä»
ææ¬åå |
| | | m_listCtrl.RedrawItems(row, row); |
| | | } |
| | | |
| | | // 5) éæ¾ retain |
| | | for (auto* g : tempRetain) g->release(); |
| | | } |
| | | |
| | | void CPageGlassList::InsertWipRow(SERVO::CGlass* /*pGlass*/) |
| | | { |
| | | // ä¸åä½¿ç¨ |
| | | } |
| | | |
| | | void CPageGlassList::UpdateWipRow(unsigned int /*index*/, SERVO::CGlass* /*pGlass*/) |
| | | { |
| | | // ä¸åä½¿ç¨ |
| | | } |
| | | |
| | | bool CPageGlassList::eraseGlassInVector(SERVO::CGlass* /*pGlass*/, std::vector<SERVO::CGlass*>& /*glasses*/) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | // ===== è¿æ»¤é»è¾ï¼åæ ·ä¿çï¼ ===== |
| | | |
| | | // æ ¸å¿ï¼WIP ç CGlass æ¯å¦å½ä¸å½å Filters |
| | | // useEndTime=true æ¶ç¨ tEnd 夿¶é´ï¼æ¯å¦â宿å表âç¨ t_endï¼ï¼é»è®¤æ tStartã |
| | | bool CPageGlassList::GlassMatchesFilters(const SERVO::CGlass& g, |
| | | const GlassLogDb::Filters& f, |
| | | bool useEndTime/* = false*/) |
| | | { |
| | | // 1) ç²¾ç¡®åæ®µ |
| | | if (f.classId && g.getID() != *f.classId) return false; |
| | | if (f.cassetteSeqNo && g.getCassetteSequenceNo() != *f.cassetteSeqNo) return false; |
| | | if (f.jobSeqNo && g.getJobSequenceNo() != *f.jobSeqNo) return false; |
| | | |
| | | // 2) å
³é®åï¼ä¸ DB ä¿æä¸è´ï¼class_id / buddy_id / path / params / prettyï¼ |
| | | if (f.keyword) { |
| | | const std::string& kw = *f.keyword; |
| | | if (!(CToolUnits::containsCI(g.getID(), kw) |
| | | || CToolUnits::containsCI(g.getBuddyId(), kw) |
| | | || CToolUnits::containsCI(g.getPathDescription(), kw) |
| | | || CToolUnits::containsCI(g.getParamsDescription(), kw))) |
| | | return false; |
| | | } |
| | | |
| | | // 3) æ¶é´ï¼ä¸ DB ä¿æä¸è´ï¼é»è®¤æ t_start è¿æ»¤ï¼éè¦å¯åå° t_endï¼ |
| | | if (f.tStartFrom || f.tStartTo) { |
| | | std::optional<std::chrono::system_clock::time_point> tp = useEndTime ? g.tEnd() : g.tStart(); |
| | | // 约å®ï¼è¥æ²¡æå¯¹åºæ¶é´æ³ï¼åè§ä¸ºä¸å½ä¸ï¼ä¸ DB ç¸åï¼NULL ä¸ä¼å½ä¸èå´ï¼ |
| | | if (!tp) return false; |
| | | if (f.tStartFrom && *tp < *f.tStartFrom) return false; |
| | | if (f.tStartTo && *tp > *f.tStartTo) return false; |
| | | } |
| | | |
| | | return true; |
| | | } |
| | |
| | | #pragma once |
| | | #include "ListCtrlEx.h" |
| | | #include "CExpandableListCtrl.h" |
| | | #include "GlassLogDb.h" |
| | | |
| | | |
| | | // CPageGlassList å¯¹è¯æ¡ |
| | |
| | | IObserver* m_pObserver; |
| | | |
| | | // æç´¢å
³é®å |
| | | GlassLogDb::Filters m_filters; |
| | | std::string m_strStatus; |
| | | std::string m_strKeyword; |
| | | |
| | | // 页ç |
| | | int m_nCurPage; |
| | |
| | | // æ§ä»¶ |
| | | CDateTimeCtrl m_dateTimeStart; |
| | | CDateTimeCtrl m_dateTimeEnd; |
| | | CListCtrlEx m_listCtrl; |
| | | CExpandableListCtrl m_listCtrl; |
| | | |
| | | private: |
| | | int m_nColCount = 0; |
| | | bool m_rebuilding = false; |
| | | |
| | | private: |
| | | void InitRxWindow(); |
| | |
| | | void InitStatusCombo(); |
| | | void InitTimeRangeCombo(); |
| | | void InitDateTimeControls(); |
| | | void LoadTransfers(); |
| | | void LoadData(); |
| | | void UpdatePageData(); |
| | | void UpdatePageControls(); |
| | | void UpdateDateFilter(); |
| | | /* |
| | | void FillDataToListCtrl(const std::vector<TransferData>& vecData); |
| | | void InsertTransferData(const TransferData& data); |
| | | */ |
| | | void InsertWipRow(SERVO::CGlass* pGlass); |
| | | static bool GlassMatchesFilters(const SERVO::CGlass& g, |
| | | const GlassLogDb::Filters& f, |
| | | bool useEndTime = false); |
| | | void UpdateWipData(); |
| | | bool eraseGlassInVector(SERVO::CGlass* pGlass, std::vector<SERVO::CGlass*>& glasses); |
| | | void UpdateWipRow(unsigned int index, SERVO::CGlass* pGlass); |
| | | |
| | | // å¯¹è¯æ¡æ°æ® |
| | | #ifdef AFX_DESIGN_TIME |
| | |
| | | afx_msg void OnBnClickedButtonExport(); |
| | | afx_msg void OnBnClickedButtonPrevPage(); |
| | | afx_msg void OnBnClickedButtonNextPage(); |
| | | afx_msg void OnShowFullText(NMHDR* pNMHDR, LRESULT* pResult); |
| | | DECLARE_MESSAGE_MAP() |
| | | }; |
| | |
| | | #include "stdafx.h" |
| | | #include "CPath.h" |
| | | #include "ToolUnits.h" |
| | | #include "CServoUtilsTool.h" |
| | | |
| | | |
| | | namespace SERVO { |
| | |
| | | m_pNext = nullptr; |
| | | } |
| | | |
| | | CPath::CPath(unsigned int nEqId, unsigned int nUnit) |
| | | CPath::CPath(unsigned int nEqId, unsigned int nUnit, unsigned int nSlot) |
| | | { |
| | | m_nEqID = nEqId; |
| | | m_nUnit = nUnit; |
| | | m_nSlot = nSlot; |
| | | m_timeOut = 0; |
| | | m_timeIn = CToolUnits::getTimestamp(); |
| | | m_bProcessed = FALSE; |
| | |
| | | strOut = strOut + ">"; |
| | | } |
| | | |
| | | void CPath::getSimpleDescription(std::string& strOut) |
| | | { |
| | | strOut = CServoUtilsTool::getEqUnitName(m_nEqID, m_nUnit, m_nSlot); |
| | | } |
| | | |
| | | void CPath::serialize(CArchive& ar) |
| | | { |
| | | if (ar.IsStoring()) { |
| | | ar << m_nEqID; |
| | | ar << m_nUnit; |
| | | ar << m_nSlot; |
| | | ar << m_timeIn; |
| | | ar << m_timeOut; |
| | | ar << m_bProcessed; |
| | |
| | | |
| | | ar >> m_nEqID; |
| | | ar >> m_nUnit; |
| | | ar >> m_nSlot; |
| | | ar >> m_timeIn; |
| | | ar >> m_timeOut; |
| | | ar >> m_bProcessed; |
| | |
| | | return m_nUnit; |
| | | } |
| | | |
| | | unsigned int CPath::getSlot() |
| | | { |
| | | return m_nSlot; |
| | | } |
| | | |
| | | void CPath::setInTime(ULONGLONG time) |
| | | { |
| | | m_timeIn = time; |
| | |
| | | { |
| | | public: |
| | | CPath(); |
| | | CPath(unsigned int nEqId, unsigned int nUnit); |
| | | CPath(unsigned int nEqId, unsigned int nUnit, unsigned int nSlot); |
| | | virtual ~CPath(); |
| | | |
| | | public: |
| | | void getDescription(std::string& strOut); |
| | | void getSimpleDescription(std::string& strOut); |
| | | void serialize(CArchive& ar); |
| | | CPath* getPrev(); |
| | | CPath* getNext(); |
| | |
| | | CPath* getHeadPath(); |
| | | unsigned int getEqID(); |
| | | unsigned int getUnit(); |
| | | unsigned int getSlot(); |
| | | void setInTime(ULONGLONG time); |
| | | ULONGLONG getInTime(); |
| | | void setOutTime(ULONGLONG time); |
| | |
| | | private: |
| | | unsigned int m_nEqID; |
| | | unsigned int m_nUnit; |
| | | unsigned int m_nSlot; |
| | | ULONGLONG m_timeIn; |
| | | ULONGLONG m_timeOut; |
| | | BOOL m_bProcessed; |
| | |
| | | LOGI(_T("RobotTaskå·²ä¸åå°EFEM")); |
| | | } |
| | | else { |
| | | LOGI(_T("RobotTaskä¸å失败")); |
| | | LOGE(_T("RobotTaskä¸å失败")); |
| | | } |
| | | |
| | | return 0; |
| | |
| | | LOGI(_T("RobotTask/getå·²ä¸åå°EFEM")); |
| | | } |
| | | else { |
| | | LOGI(_T("RobotTask/getå·²ä¸å失败")); |
| | | LOGE(_T("RobotTask/getå·²ä¸å失败")); |
| | | } |
| | | |
| | | return 0; |
| | |
| | | LOGI(_T("RobotTask/putå·²ä¸åå°EFEM")); |
| | | } |
| | | else { |
| | | LOGI(_T("RobotTask/putå·²ä¸å失败")); |
| | | LOGE(_T("RobotTask/putå·²ä¸å失败")); |
| | | } |
| | | |
| | | return 0; |
| | |
| | | LOGI(_T("RobotTask/restore-putå·²ä¸åå°EFEM")); |
| | | } |
| | | else { |
| | | LOGI(_T("RobotTask/restore-putå·²ä¸å失败")); |
| | | LOGE(_T("RobotTask/restore-putå·²ä¸å失败")); |
| | | } |
| | | |
| | | return 0; |
| | |
| | | |
| | | int index = 0; |
| | | CSVData svData; |
| | | CToolUnits::convertString(&pszBuffer[index], 8, m_strTime); |
| | | index += 8; |
| | | CToolUnits::convertString(&pszBuffer[index], 8 * 2, m_strTime); |
| | | index += 8 * 2; |
| | | |
| | | m_svRawData.clear(); |
| | | m_svRawData.insert(m_svRawData.end(), (uint8_t*)(pszBuffer), (uint8_t*)(pszBuffer)+125); |
| | | index += 125; |
| | | m_svRawData.insert(m_svRawData.end(), (uint8_t*)(&pszBuffer[index]), (uint8_t*)(pszBuffer)+(125 * 2)); |
| | | index += 125 * 2; |
| | | |
| | | return 133; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #include "stdafx.h" |
| | | #include "CServoUtilsTool.h" |
| | | #include "Common.h" |
| | | |
| | | |
| | | namespace SERVO { |
| | | CServoUtilsTool::CServoUtilsTool() |
| | | { |
| | | |
| | | } |
| | | |
| | | CServoUtilsTool::~CServoUtilsTool() |
| | | { |
| | | |
| | | } |
| | | |
| | | std::string CServoUtilsTool::getEqUnitName(int eqid, int unit) |
| | | { |
| | | char szBuffer[256]; |
| | | if (eqid == EQ_ID_LOADPORT1 |
| | | || eqid == EQ_ID_LOADPORT2 |
| | | || eqid == EQ_ID_LOADPORT3 |
| | | || eqid == EQ_ID_LOADPORT4 |
| | | ) { |
| | | sprintf_s(szBuffer, 256, "Port%d(Slot%d)", eqid - EQ_ID_LOADPORT1 + 1, unit + 1); |
| | | return std::string(szBuffer); |
| | | } |
| | | |
| | | if (eqid == EQ_ID_ALIGNER) { |
| | | return "Aligner"; |
| | | } |
| | | |
| | | if (eqid == EQ_ID_FLIPER) { |
| | | return "Fliper"; |
| | | } |
| | | |
| | | if (eqid == EQ_ID_VACUUMBAKE) { |
| | | if (unit == 0) return "çç¤Aè
"; |
| | | if (unit == 1) return "çç¤Bè
"; |
| | | } |
| | | |
| | | if (eqid == EQ_ID_VACUUMBAKE) { |
| | | if (unit == 0) return "çç¤Aè
"; |
| | | if (unit == 1) return "çç¤Bè
"; |
| | | } |
| | | |
| | | if (eqid == EQ_ID_Bonder1) { |
| | | return "Bonder1"; |
| | | } |
| | | |
| | | if (eqid == EQ_ID_Bonder2) { |
| | | return "Bonder2"; |
| | | } |
| | | |
| | | if (eqid == EQ_ID_BAKE_COOLING) { |
| | | |
| | | if (unit == 0) return "åçç¤Aè
"; |
| | | if (unit == 1) return "å·å´A"; |
| | | if (unit == 0) return "åçç¤Bè
"; |
| | | if (unit == 1) return "å·å´B"; |
| | | } |
| | | |
| | | if (eqid == EQ_ID_MEASUREMENT) { |
| | | return "AOI"; |
| | | } |
| | | |
| | | |
| | | if (eqid == EQ_ID_ARM_TRAY1) { |
| | | return "ARM1"; |
| | | } |
| | | |
| | | if (eqid == EQ_ID_ARM_TRAY2) { |
| | | return "ARM2"; |
| | | } |
| | | |
| | | return ""; |
| | | } |
| | | |
| | | std::string CServoUtilsTool::getEqUnitName(int eqid, int unit, int slot) |
| | | { |
| | | char szBuffer[256]; |
| | | if (eqid == EQ_ID_LOADPORT1 |
| | | || eqid == EQ_ID_LOADPORT2 |
| | | || eqid == EQ_ID_LOADPORT3 |
| | | || eqid == EQ_ID_LOADPORT4 |
| | | ) { |
| | | sprintf_s(szBuffer, 256, "Port%d(Slot%d)", eqid - EQ_ID_LOADPORT1 + 1, slot); |
| | | return std::string(szBuffer); |
| | | } |
| | | |
| | | if (eqid == EQ_ID_ALIGNER) { |
| | | return "Aligner"; |
| | | } |
| | | |
| | | if (eqid == EQ_ID_FLIPER) { |
| | | return "Fliper"; |
| | | } |
| | | |
| | | if (eqid == EQ_ID_VACUUMBAKE) { |
| | | if (unit == 0) { |
| | | sprintf_s(szBuffer, 256, "çç¤Aè
(Slot%d)", slot); |
| | | return std::string(szBuffer); |
| | | } |
| | | if (unit == 1) { |
| | | sprintf_s(szBuffer, 256, "çç¤Bè
(Slot%d)", slot); |
| | | return std::string(szBuffer); |
| | | } |
| | | } |
| | | |
| | | if (eqid == EQ_ID_Bonder1) { |
| | | sprintf_s(szBuffer, 256, "Bonder1(Slot%d)", slot); |
| | | return std::string(szBuffer); |
| | | } |
| | | |
| | | if (eqid == EQ_ID_Bonder2) { |
| | | sprintf_s(szBuffer, 256, "Bonder2(Slot%d)", slot); |
| | | return std::string(szBuffer); |
| | | } |
| | | |
| | | if (eqid == EQ_ID_BAKE_COOLING) { |
| | | |
| | | if (slot == 0) return "åçç¤Aè
"; |
| | | if (slot == 1) return "å·å´A"; |
| | | if (slot == 2) return "åçç¤Bè
"; |
| | | if (slot == 3) return "å·å´B"; |
| | | } |
| | | |
| | | if (eqid == EQ_ID_MEASUREMENT) { |
| | | return "AOI"; |
| | | } |
| | | |
| | | |
| | | if (eqid == EQ_ID_ARM_TRAY1) { |
| | | return "ARM1"; |
| | | } |
| | | |
| | | if (eqid == EQ_ID_ARM_TRAY2) { |
| | | return "ARM2"; |
| | | } |
| | | |
| | | return ""; |
| | | } |
| | | |
| | | std::string CServoUtilsTool::getMaterialsTypeText(MaterialsType type) |
| | | { |
| | | if (type == MaterialsType::G1) { |
| | | return "G1"; |
| | | } |
| | | |
| | | if (type == MaterialsType::G2) { |
| | | return "G2"; |
| | | } |
| | | |
| | | return ""; |
| | | } |
| | | |
| | | std::string CServoUtilsTool::getGlassStateText(SERVO::GlsState state) |
| | | { |
| | | switch (state) |
| | | { |
| | | case SERVO::GlsState::NoState: |
| | | return "NoState"; |
| | | break; |
| | | case SERVO::GlsState::Queued: |
| | | return "Queued"; |
| | | break; |
| | | case SERVO::GlsState::InProcess: |
| | | return "InProcess"; |
| | | break; |
| | | case SERVO::GlsState::Paused: |
| | | return "Paused"; |
| | | break; |
| | | case SERVO::GlsState::Completed: |
| | | return "Completed"; |
| | | break; |
| | | case SERVO::GlsState::Aborted: |
| | | return "Aborted"; |
| | | break; |
| | | case SERVO::GlsState::Failed: |
| | | return "Failed"; |
| | | break; |
| | | default: |
| | | return ""; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | std::string CServoUtilsTool::getInspResultText(SERVO::InspResult result) |
| | | { |
| | | switch (result) |
| | | { |
| | | case SERVO::InspResult::NotInspected: |
| | | return ""; |
| | | break; |
| | | case SERVO::InspResult::Pass: |
| | | return "Pass"; |
| | | break; |
| | | case SERVO::InspResult::Fail: |
| | | return "Fail"; |
| | | break; |
| | | default: |
| | | return ""; |
| | | break; |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #pragma once |
| | | #include "ServoCommo.h" |
| | | #include "CGlass.h" |
| | | |
| | | |
| | | namespace SERVO { |
| | | class CServoUtilsTool |
| | | { |
| | | public: |
| | | CServoUtilsTool(); |
| | | virtual ~CServoUtilsTool(); |
| | | |
| | | public: |
| | | static std::string getEqUnitName(int eqid, int unit); |
| | | static std::string getEqUnitName(int eqid, int unit, int slot); |
| | | static std::string getMaterialsTypeText(MaterialsType type); |
| | | static std::string getGlassStateText(SERVO::GlsState state); |
| | | static std::string getInspResultText(SERVO::InspResult result); |
| | | }; |
| | | } |
| | | |
| | |
| | | return GetPrivateProfileInt(_T("Master"), _T("CTRound"), 0, m_strFilepath); |
| | | } |
| | | |
| | | char* pszPortSection[] = { "Port1", "Port2", "Port3", "Port4" }; |
| | | int CConfiguration::getPortCassetteSnSeed(int port) |
| | | { |
| | | ASSERT(1 <= port && port <= 4); |
| | | return GetPrivateProfileInt(pszPortSection[port-1], _T("CassetteSnSeed"), 0, m_strFilepath); |
| | | } |
| | | |
| | | void CConfiguration::setPortCassetteSnSeed(int port, int seed) |
| | | { |
| | | ASSERT(1 <= port && port <= 4); |
| | | WritePrivateProfileString(pszPortSection[port - 1], _T("CassetteSnSeed"), |
| | | std::to_string(seed).c_str(), m_strFilepath); |
| | | } |
| | | |
| | |
| | | BOOL isJobMode(); |
| | | void setContinuousTransferCount(int round); |
| | | int getContinuousTransferCount(); |
| | | int getPortCassetteSnSeed(int port); |
| | | void setPortCassetteSnSeed(int port, int seed); |
| | | |
| | | public: |
| | | void setP2RemoteEqReconnectInterval(int second); |
| | |
| | | // TODO: 卿¤æ·»å é¢å¤çåå§å |
| | | SERVO::CEquipment* pEquipment = theApp.m_model.m_master.getEquipment(m_nDeviceID); |
| | | if (nullptr == pEquipment) { |
| | | LOGI("<设å¤IDï¼%d>è·å设å¤å±æ§å¤±è´¥ã", m_nDeviceID); |
| | | LOGE("<设å¤IDï¼%d>è·å设å¤å±æ§å¤±è´¥ã", m_nDeviceID); |
| | | return FALSE; |
| | | } |
| | | |
| | |
| | | Json::Value n(Json::objectValue); |
| | | n["eq_id"] = p->getEqID(); |
| | | n["unit"] = p->getUnit(); |
| | | n["slot"] = p->getUnit(); |
| | | put_ull_as_str(n, "time_in", static_cast<unsigned long long>(p->getInTime())); |
| | | put_ull_as_str(n, "time_out", static_cast<unsigned long long>(p->getOutTime())); |
| | | n["processed"] = p->isProcessEnd() ? true : false; |
| | |
| | | // åºæ¬ |
| | | g.setID(JStr(root, "id").c_str()); |
| | | g.setType(static_cast<MaterialsType>(JInt(root, "materials", 0))); |
| | | g.getBuddyId() = JStr(root, "buddy_id"); |
| | | g.setBuddyId(JStr(root, "buddy_id")); |
| | | g.setScheduledForProcessing(JBool(root, "scheduled") ? TRUE : FALSE); |
| | | g.m_failReason = JStr(root, "fail_reason"); |
| | | g.setOriginPort(JInt(root, "origin_port", 0), JInt(root, "origin_slot", 0)); |
| | |
| | | for (const auto& n : root["path"]) { |
| | | unsigned eq = JUInt(n, "eq_id", 0); |
| | | unsigned unit = JUInt(n, "unit", 0); |
| | | g.addPath(eq, unit); |
| | | unsigned slot = JUInt(n, "slot", 0); |
| | | g.addPath(eq, unit, slot); |
| | | |
| | | CPath* tail = nullptr; |
| | | if (auto head = g.getPath()) tail = head->getTailPath(); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // GlassLogDb.cpp - åä¾å°è£
ï¼SQLite åå
¥/æ¥è¯¢/å页/ç»è®¡/CSV 导åºï¼å·²å¯¹æ¥ SERVO::CGlassï¼ |
| | | #include "stdafx.h" |
| | | #include "GlassLogDb.h" |
| | | #include "sqlite3.h" |
| | | #include <stdexcept> |
| | | #include <sstream> |
| | | #include <iomanip> |
| | | #include <ctime> |
| | | #include <fstream> |
| | | #include "GlassJson.h" |
| | | |
| | | |
| | | using namespace SERVO; |
| | | |
| | | #ifndef GLASS_LOG_TABLE |
| | | #define GLASS_LOG_TABLE "glass_log" |
| | | #endif |
| | | |
| | | // ================== å·¥å
·å½æ° ================== |
| | | static void throwIf(int rc, sqlite3* db, const char* msg) { |
| | | if (rc != SQLITE_OK && rc != SQLITE_DONE && rc != SQLITE_ROW) { |
| | | std::ostringstream oss; |
| | | oss << msg << " (rc=" << rc << "): " << (db ? sqlite3_errmsg(db) : "null db"); |
| | | throw std::runtime_error(oss.str()); |
| | | } |
| | | } |
| | | static inline const char* safe_text(sqlite3_stmt* s, int col) { |
| | | const unsigned char* p = sqlite3_column_text(s, col); |
| | | return p ? reinterpret_cast<const char*>(p) : ""; |
| | | } |
| | | static std::string csvEscape(const std::string& s) { |
| | | bool needQuote = s.find_first_of(",\"\n\r") != std::string::npos; |
| | | if (!needQuote) return s; |
| | | std::string out; out.reserve(s.size() + 2); |
| | | out.push_back('"'); |
| | | for (char c : s) out += (c == '"') ? "\"\"" : std::string(1, c); |
| | | out.push_back('"'); |
| | | return out; |
| | | } |
| | | static std::string toIso8601String(const std::optional<std::chrono::system_clock::time_point>& tp) { |
| | | if (!tp.has_value()) return ""; |
| | | using namespace std::chrono; |
| | | auto t = system_clock::to_time_t(*tp); |
| | | std::tm tm{}; |
| | | #if defined(_WIN32) |
| | | gmtime_s(&tm, &t); |
| | | #else |
| | | gmtime_r(&t, &tm); |
| | | #endif |
| | | std::ostringstream oss; |
| | | oss << std::put_time(&tm, "%Y-%m-%dT%H:%M:%SZ"); |
| | | return oss.str(); |
| | | } |
| | | |
| | | // ================== åä¾éææå ================== |
| | | std::unique_ptr<GlassLogDb> GlassLogDb::s_inst; |
| | | std::mutex GlassLogDb::s_instMtx; |
| | | |
| | | // ================== å便¥å£å®ç° ================== |
| | | void GlassLogDb::Init(const std::string& dbPath) { |
| | | std::lock_guard<std::mutex> g(s_instMtx); |
| | | if (!s_inst) { |
| | | s_inst.reset(new GlassLogDb(dbPath)); |
| | | } |
| | | else if (s_inst->dbPath_ != dbPath) { |
| | | s_inst->reopenInternal(dbPath); |
| | | } |
| | | } |
| | | GlassLogDb& GlassLogDb::Instance() { |
| | | std::lock_guard<std::mutex> g(s_instMtx); |
| | | if (!s_inst) throw std::runtime_error("GlassLogDb::Instance() called before Init()"); |
| | | return *s_inst; |
| | | } |
| | | bool GlassLogDb::IsInitialized() noexcept { |
| | | std::lock_guard<std::mutex> g(s_instMtx); |
| | | return static_cast<bool>(s_inst); |
| | | } |
| | | void GlassLogDb::Reopen(const std::string& dbPath) { |
| | | std::lock_guard<std::mutex> g(s_instMtx); |
| | | if (!s_inst) { |
| | | s_inst.reset(new GlassLogDb(dbPath)); |
| | | } |
| | | else { |
| | | s_inst->reopenInternal(dbPath); |
| | | } |
| | | } |
| | | std::string GlassLogDb::CurrentPath() { |
| | | std::lock_guard<std::mutex> g(s_instMtx); |
| | | return s_inst ? s_inst->dbPath_ : std::string(); |
| | | } |
| | | |
| | | // ================== æé /æå¼/å
³é/éå¼ ================== |
| | | GlassLogDb::GlassLogDb(const std::string& dbPath) { |
| | | openDb(dbPath); |
| | | } |
| | | void GlassLogDb::openDb(const std::string& dbPath) { |
| | | int rc = sqlite3_open_v2(dbPath.c_str(), &db_, |
| | | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, |
| | | nullptr); |
| | | if (rc != SQLITE_OK) { |
| | | std::string err = db_ ? sqlite3_errmsg(db_) : "open failed"; |
| | | if (db_) sqlite3_close(db_); |
| | | db_ = nullptr; |
| | | throw std::runtime_error("Failed to open sqlite DB: " + err + " | path=" + dbPath); |
| | | } |
| | | dbPath_ = dbPath; |
| | | ensureSchema(); |
| | | prepareStatements(); |
| | | } |
| | | void GlassLogDb::closeDb() noexcept { |
| | | finalizeStatements(); |
| | | if (db_) { |
| | | sqlite3_close(db_); |
| | | db_ = nullptr; |
| | | } |
| | | } |
| | | void GlassLogDb::reopenInternal(const std::string& dbPath) { |
| | | std::lock_guard<std::mutex> lk(mtx_); |
| | | if (dbPath == dbPath_) return; |
| | | closeDb(); |
| | | openDb(dbPath); |
| | | } |
| | | |
| | | // ================== ææ ================== |
| | | GlassLogDb::~GlassLogDb() { |
| | | closeDb(); |
| | | } |
| | | |
| | | // ================== DDL & é¢ç¼è¯ ================== |
| | | void GlassLogDb::ensureSchema() { |
| | | const char* ddl = |
| | | "CREATE TABLE IF NOT EXISTS " GLASS_LOG_TABLE " (" |
| | | " id INTEGER PRIMARY KEY AUTOINCREMENT," |
| | | " cassette_seq_no INTEGER," |
| | | " job_seq_no INTEGER," |
| | | " class_id TEXT," |
| | | " material_type INTEGER," |
| | | " state INTEGER," |
| | | " t_start TEXT," // ISO8601 UTCï¼å¯ä¸º NULLï¼ |
| | | " t_end TEXT," // ISO8601 UTCï¼å¯ä¸º NULLï¼ |
| | | " buddy_id TEXT," |
| | | " aoi_result INTEGER," |
| | | " path TEXT," |
| | | " params TEXT," |
| | | " pretty TEXT" |
| | | ");" |
| | | "CREATE INDEX IF NOT EXISTS idx_glass_key " |
| | | " ON " GLASS_LOG_TABLE " (cassette_seq_no, job_seq_no);" |
| | | "CREATE INDEX IF NOT EXISTS idx_class_id " |
| | | " ON " GLASS_LOG_TABLE " (class_id);" |
| | | "CREATE INDEX IF NOT EXISTS idx_t_start " |
| | | " ON " GLASS_LOG_TABLE " (t_start);"; |
| | | |
| | | char* errMsg = nullptr; |
| | | int rc = sqlite3_exec(db_, ddl, nullptr, nullptr, &errMsg); |
| | | if (rc != SQLITE_OK) { |
| | | std::string err = errMsg ? errMsg : "unknown"; |
| | | sqlite3_free(errMsg); |
| | | throw std::runtime_error("Failed to create schema: " + err); |
| | | } |
| | | } |
| | | void GlassLogDb::prepareStatements() { |
| | | const char* sql = |
| | | "INSERT INTO " GLASS_LOG_TABLE " (" |
| | | " cassette_seq_no, job_seq_no, class_id, material_type, state," |
| | | " t_start, t_end, buddy_id, aoi_result, path, params, pretty)" |
| | | " VALUES (?,?,?,?,?,?,?,?,?,?,?,?);"; |
| | | int rc = sqlite3_prepare_v2(db_, sql, -1, &stmtInsert_, nullptr); |
| | | throwIf(rc, db_, "prepare insert"); |
| | | } |
| | | void GlassLogDb::finalizeStatements() noexcept { |
| | | if (stmtInsert_) { |
| | | sqlite3_finalize(stmtInsert_); |
| | | stmtInsert_ = nullptr; |
| | | } |
| | | } |
| | | |
| | | // ================== äºå¡ ================== |
| | | void GlassLogDb::beginTransaction() { |
| | | std::lock_guard<std::mutex> lk(mtx_); |
| | | char* err = nullptr; |
| | | int rc = sqlite3_exec(db_, "BEGIN IMMEDIATE;", nullptr, nullptr, &err); |
| | | if (rc != SQLITE_OK) { |
| | | std::string e = err ? err : "unknown"; |
| | | sqlite3_free(err); |
| | | throw std::runtime_error("BEGIN failed: " + e); |
| | | } |
| | | } |
| | | void GlassLogDb::commit() { |
| | | std::lock_guard<std::mutex> lk(mtx_); |
| | | char* err = nullptr; |
| | | int rc = sqlite3_exec(db_, "COMMIT;", nullptr, nullptr, &err); |
| | | if (rc != SQLITE_OK) { |
| | | std::string e = err ? err : "unknown"; |
| | | sqlite3_free(err); |
| | | throw std::runtime_error("COMMIT failed: " + e); |
| | | } |
| | | } |
| | | void GlassLogDb::rollback() { |
| | | std::lock_guard<std::mutex> lk(mtx_); |
| | | char* err = nullptr; |
| | | sqlite3_exec(db_, "ROLLBACK;", nullptr, nullptr, &err); |
| | | if (err) sqlite3_free(err); |
| | | } |
| | | |
| | | // ================== æ¶é´æ ¼å¼ ================== |
| | | std::string GlassLogDb::toIso8601Utc(std::chrono::system_clock::time_point tp) { |
| | | using namespace std::chrono; |
| | | auto t = system_clock::to_time_t(tp); |
| | | std::tm tm{}; |
| | | #if defined(_WIN32) |
| | | gmtime_s(&tm, &t); |
| | | #else |
| | | gmtime_r(&t, &tm); |
| | | #endif |
| | | std::ostringstream oss; |
| | | oss << std::put_time(&tm, "%Y-%m-%dT%H:%M:%SZ"); |
| | | return oss.str(); |
| | | } |
| | | |
| | | // ================== æå
¥å®ç° ================== |
| | | long long GlassLogDb::doInsert( |
| | | int cassetteSeqNo, |
| | | int jobSeqNo, |
| | | const std::string& classId, |
| | | int materialType, |
| | | int state, |
| | | std::optional<std::chrono::system_clock::time_point> tStart, |
| | | std::optional<std::chrono::system_clock::time_point> tEnd, |
| | | const std::string& buddyId, |
| | | int aoiResult, |
| | | const std::string& pathDesc, |
| | | const std::string& paramsDesc, |
| | | const std::string& prettyString) |
| | | { |
| | | std::lock_guard<std::mutex> lk(mtx_); |
| | | int idx = 1; |
| | | throwIf(sqlite3_reset(stmtInsert_), db_, "reset insert"); |
| | | throwIf(sqlite3_clear_bindings(stmtInsert_), db_, "clear bindings"); |
| | | |
| | | throwIf(sqlite3_bind_int(stmtInsert_, idx++, cassetteSeqNo), db_, "bind cassette"); |
| | | throwIf(sqlite3_bind_int(stmtInsert_, idx++, jobSeqNo), db_, "bind job"); |
| | | throwIf(sqlite3_bind_text(stmtInsert_, idx++, classId.c_str(), -1, SQLITE_TRANSIENT), db_, "bind class_id"); |
| | | throwIf(sqlite3_bind_int(stmtInsert_, idx++, materialType), db_, "bind material_type"); |
| | | throwIf(sqlite3_bind_int(stmtInsert_, idx++, state), db_, "bind state"); |
| | | |
| | | if (tStart.has_value()) { |
| | | auto s = toIso8601Utc(*tStart); |
| | | throwIf(sqlite3_bind_text(stmtInsert_, idx++, s.c_str(), -1, SQLITE_TRANSIENT), db_, "bind t_start"); |
| | | } |
| | | else { |
| | | throwIf(sqlite3_bind_null(stmtInsert_, idx++), db_, "bind t_start null"); |
| | | } |
| | | if (tEnd.has_value()) { |
| | | auto e = toIso8601Utc(*tEnd); |
| | | throwIf(sqlite3_bind_text(stmtInsert_, idx++, e.c_str(), -1, SQLITE_TRANSIENT), db_, "bind t_end"); |
| | | } |
| | | else { |
| | | throwIf(sqlite3_bind_null(stmtInsert_, idx++), db_, "bind t_end null"); |
| | | } |
| | | |
| | | throwIf(sqlite3_bind_text(stmtInsert_, idx++, buddyId.c_str(), -1, SQLITE_TRANSIENT), db_, "bind buddy_id"); |
| | | throwIf(sqlite3_bind_int(stmtInsert_, idx++, aoiResult), db_, "bind aoi_result"); |
| | | throwIf(sqlite3_bind_text(stmtInsert_, idx++, pathDesc.c_str(), -1, SQLITE_TRANSIENT), db_, "bind path"); |
| | | throwIf(sqlite3_bind_text(stmtInsert_, idx++, paramsDesc.c_str(), -1, SQLITE_TRANSIENT), db_, "bind params"); |
| | | throwIf(sqlite3_bind_text(stmtInsert_, idx++, prettyString.c_str(), -1, SQLITE_TRANSIENT), db_, "bind pretty"); |
| | | |
| | | int rc = sqlite3_step(stmtInsert_); |
| | | throwIf(rc, db_, "insert step"); |
| | | return sqlite3_last_insert_rowid(db_); |
| | | } |
| | | |
| | | long long GlassLogDb::insertFromCGlass(CGlass& g) |
| | | { |
| | | const int cassette = static_cast<int>(g.getCassetteSequenceNo()); |
| | | const int job = static_cast<int>(g.getJobSequenceNo()); |
| | | const std::string& classId = g.getID(); |
| | | const int material = static_cast<int>(g.getType()); |
| | | const int state = static_cast<int>(g.state()); |
| | | const std::string& buddy = g.getBuddyId(); |
| | | const int aoiResult = static_cast<int>(g.getAOIInspResult()); |
| | | const std::string pathDesc = g.getPathDescription(); |
| | | const std::string paramsDesc = g.getParamsDescription(); |
| | | const std::string pretty = GlassJson::ToPrettyString(g); |
| | | |
| | | auto tStart = g.tStart(); |
| | | auto tEnd = g.tEnd(); |
| | | |
| | | return doInsert(cassette, job, classId, material, state, |
| | | tStart, tEnd, buddy, aoiResult, pathDesc, paramsDesc, pretty); |
| | | } |
| | | |
| | | long long GlassLogDb::insertExplicit( |
| | | int cassetteSeqNo, |
| | | int jobSeqNo, |
| | | const std::string& classId, |
| | | int materialType, |
| | | int state, |
| | | std::optional<std::chrono::system_clock::time_point> tStart, |
| | | std::optional<std::chrono::system_clock::time_point> tEnd, |
| | | const std::string& buddyId, |
| | | int aoiResult, |
| | | const std::string& pathDesc, |
| | | const std::string& paramsDesc, |
| | | const std::string& prettyString) |
| | | { |
| | | return doInsert(cassetteSeqNo, jobSeqNo, classId, materialType, state, |
| | | tStart, tEnd, buddyId, aoiResult, pathDesc, paramsDesc, prettyString); |
| | | } |
| | | |
| | | // ================== è¿æ»¤æé ï¼where + bindï¼ ================== |
| | | static std::string buildWhereSql(const GlassLogDb::Filters& f) { |
| | | std::ostringstream where; |
| | | bool first = true; |
| | | auto add = [&](const std::string& cond) { |
| | | if (first) { where << " WHERE " << cond; first = false; } |
| | | else { where << " AND " << cond; } |
| | | }; |
| | | if (f.classId) add("class_id = ?"); |
| | | if (f.cassetteSeqNo) add("cassette_seq_no = ?"); |
| | | if (f.jobSeqNo) add("job_seq_no = ?"); |
| | | if (f.keyword) add("(class_id LIKE ? OR buddy_id LIKE ? OR path LIKE ? OR params LIKE ? OR pretty LIKE ?)"); |
| | | if (f.tStartFrom && f.tStartTo) add("(t_start >= ? AND t_start <= ?)"); |
| | | else if (f.tStartFrom) add("t_start >= ?"); |
| | | else if (f.tStartTo) add("t_start <= ?"); |
| | | return where.str(); |
| | | } |
| | | static void bindFilters(sqlite3_stmt* stmt, sqlite3* db, int& idx, const GlassLogDb::Filters& f) { |
| | | if (f.classId) throwIf(sqlite3_bind_text(stmt, idx++, f.classId->c_str(), -1, SQLITE_TRANSIENT), db, "bind classId"); |
| | | if (f.cassetteSeqNo) throwIf(sqlite3_bind_int(stmt, idx++, *f.cassetteSeqNo), db, "bind cassette"); |
| | | if (f.jobSeqNo) throwIf(sqlite3_bind_int(stmt, idx++, *f.jobSeqNo), db, "bind job"); |
| | | if (f.keyword) { |
| | | std::string kw = "%" + *f.keyword + "%"; |
| | | for (int i = 0; i < 5; ++i) |
| | | throwIf(sqlite3_bind_text(stmt, idx++, kw.c_str(), -1, SQLITE_TRANSIENT), db, "bind keyword"); |
| | | } |
| | | if (f.tStartFrom && f.tStartTo) { |
| | | std::string s = toIso8601String(f.tStartFrom); |
| | | std::string e = toIso8601String(f.tStartTo); |
| | | throwIf(sqlite3_bind_text(stmt, idx++, s.c_str(), -1, SQLITE_TRANSIENT), db, "bind tStartFrom"); |
| | | throwIf(sqlite3_bind_text(stmt, idx++, e.c_str(), -1, SQLITE_TRANSIENT), db, "bind tStartTo"); |
| | | } |
| | | else if (f.tStartFrom) { |
| | | std::string s = toIso8601String(f.tStartFrom); |
| | | throwIf(sqlite3_bind_text(stmt, idx++, s.c_str(), -1, SQLITE_TRANSIENT), db, "bind tStartFrom"); |
| | | } |
| | | else if (f.tStartTo) { |
| | | std::string e = toIso8601String(f.tStartTo); |
| | | throwIf(sqlite3_bind_text(stmt, idx++, e.c_str(), -1, SQLITE_TRANSIENT), db, "bind tStartTo"); |
| | | } |
| | | } |
| | | |
| | | // ================== æ¥è¯¢ / ç»è®¡ / å页 ================== |
| | | std::vector<GlassLogDb::Row> GlassLogDb::query( |
| | | const Filters& filters, |
| | | int limit, |
| | | int offset) |
| | | { |
| | | std::lock_guard<std::mutex> lk(mtx_); |
| | | |
| | | std::ostringstream sql; |
| | | sql << "SELECT id, cassette_seq_no, job_seq_no, class_id, material_type, state," |
| | | " IFNULL(strftime('%Y-%m-%d %H:%M:%S', t_start, 'localtime'), '')," |
| | | " IFNULL(strftime('%Y-%m-%d %H:%M:%S', t_end, 'localtime'), '')," |
| | | " buddy_id, aoi_result, path, params, pretty" |
| | | " FROM " GLASS_LOG_TABLE; |
| | | |
| | | std::string where = buildWhereSql(filters); |
| | | sql << where |
| | | << " ORDER BY id DESC" |
| | | << " LIMIT " << (limit < 0 ? 0 : limit) |
| | | << " OFFSET " << (offset < 0 ? 0 : offset); |
| | | |
| | | sqlite3_stmt* stmt = nullptr; |
| | | throwIf(sqlite3_prepare_v2(db_, sql.str().c_str(), -1, &stmt, nullptr), db_, "prepare query"); |
| | | |
| | | int idx = 1; |
| | | bindFilters(stmt, db_, idx, filters); |
| | | |
| | | std::vector<Row> rows; |
| | | for (;;) { |
| | | int rc = sqlite3_step(stmt); |
| | | if (rc == SQLITE_ROW) { |
| | | Row r; |
| | | r.id = sqlite3_column_int64(stmt, 0); |
| | | r.cassetteSeqNo = sqlite3_column_int(stmt, 1); |
| | | r.jobSeqNo = sqlite3_column_int(stmt, 2); |
| | | r.classId = safe_text(stmt, 3); |
| | | r.materialType = sqlite3_column_int(stmt, 4); |
| | | r.state = sqlite3_column_int(stmt, 5); |
| | | r.tStart = safe_text(stmt, 6); |
| | | r.tEnd = safe_text(stmt, 7); |
| | | r.buddyId = safe_text(stmt, 8); |
| | | r.aoiResult = sqlite3_column_int(stmt, 9); |
| | | r.path = safe_text(stmt, 10); |
| | | r.params = safe_text(stmt, 11); |
| | | r.pretty = safe_text(stmt, 12); |
| | | rows.push_back(std::move(r)); |
| | | } |
| | | else if (rc == SQLITE_DONE) { |
| | | break; |
| | | } |
| | | else { |
| | | sqlite3_finalize(stmt); |
| | | throwIf(rc, db_, "query step"); |
| | | } |
| | | } |
| | | sqlite3_finalize(stmt); |
| | | return rows; |
| | | } |
| | | |
| | | long long GlassLogDb::count(const Filters& filters) { |
| | | std::lock_guard<std::mutex> lk(mtx_); |
| | | |
| | | std::ostringstream sql; |
| | | sql << "SELECT COUNT(1) FROM " GLASS_LOG_TABLE; |
| | | |
| | | std::string where = buildWhereSql(filters); |
| | | sql << where; |
| | | |
| | | sqlite3_stmt* stmt = nullptr; |
| | | throwIf(sqlite3_prepare_v2(db_, sql.str().c_str(), -1, &stmt, nullptr), db_, "prepare count"); |
| | | |
| | | int idx = 1; |
| | | bindFilters(stmt, db_, idx, filters); |
| | | |
| | | long long total = 0; |
| | | int rc = sqlite3_step(stmt); |
| | | if (rc == SQLITE_ROW) { |
| | | total = sqlite3_column_int64(stmt, 0); |
| | | } |
| | | else if (rc != SQLITE_DONE) { |
| | | sqlite3_finalize(stmt); |
| | | throwIf(rc, db_, "count step"); |
| | | } |
| | | sqlite3_finalize(stmt); |
| | | return total; |
| | | } |
| | | |
| | | GlassLogDb::Page GlassLogDb::queryPaged( |
| | | const Filters& filters, |
| | | int limit, |
| | | int offset) |
| | | { |
| | | Page p; |
| | | p.limit = (limit < 0 ? 0 : limit); |
| | | p.offset = (offset < 0 ? 0 : offset); |
| | | p.total = count(filters); |
| | | p.items = query(filters, p.limit, p.offset); |
| | | return p; |
| | | } |
| | | |
| | | // ================== å¯¼åº CSVï¼å
¨é¨ç¬¦åæ¡ä»¶ï¼ ================== |
| | | long long GlassLogDb::exportCsv(const std::string& csvPath, const Filters& filters) { |
| | | std::lock_guard<std::mutex> lk(mtx_); |
| | | |
| | | std::ofstream ofs(csvPath, std::ios::binary); |
| | | if (!ofs) { |
| | | throw std::runtime_error("Failed to open csv for write: " + csvPath); |
| | | } |
| | | |
| | | // 表头 |
| | | ofs << "id,cassette_seq_no,job_seq_no,class_id,material_type,state,t_start,t_end," |
| | | "buddy_id,aoi_result,path,params,pretty\n"; |
| | | |
| | | std::ostringstream sql; |
| | | sql << "SELECT id, cassette_seq_no, job_seq_no, class_id, material_type, state," |
| | | " IFNULL(strftime('%Y-%m-%d %H:%M:%S', t_start, 'localtime'), '')," |
| | | " IFNULL(strftime('%Y-%m-%d %H:%M:%S', t_end, 'localtime'), '')," |
| | | " buddy_id, aoi_result, path, params, pretty" |
| | | " FROM " GLASS_LOG_TABLE; |
| | | |
| | | std::string where = buildWhereSql(filters); |
| | | sql << where << " ORDER BY id DESC"; |
| | | |
| | | sqlite3_stmt* stmt = nullptr; |
| | | throwIf(sqlite3_prepare_v2(db_, sql.str().c_str(), -1, &stmt, nullptr), db_, "prepare export"); |
| | | |
| | | int idx = 1; |
| | | bindFilters(stmt, db_, idx, filters); |
| | | |
| | | long long rows = 0; |
| | | for (;;) { |
| | | int rc = sqlite3_step(stmt); |
| | | if (rc == SQLITE_ROW) { |
| | | std::string id = std::to_string(sqlite3_column_int64(stmt, 0)); |
| | | std::string cassette = std::to_string(sqlite3_column_int(stmt, 1)); |
| | | std::string job = std::to_string(sqlite3_column_int(stmt, 2)); |
| | | std::string class_id = safe_text(stmt, 3); |
| | | std::string material = std::to_string(sqlite3_column_int(stmt, 4)); |
| | | std::string state = std::to_string(sqlite3_column_int(stmt, 5)); |
| | | std::string t_start = safe_text(stmt, 6); |
| | | std::string t_end = safe_text(stmt, 7); |
| | | std::string buddy = safe_text(stmt, 8); |
| | | std::string aoi = std::to_string(sqlite3_column_int(stmt, 9)); |
| | | std::string path = safe_text(stmt, 10); |
| | | std::string params = safe_text(stmt, 11); |
| | | std::string pretty = safe_text(stmt, 12); |
| | | |
| | | ofs << id << ',' |
| | | << cassette << ',' |
| | | << job << ',' |
| | | << csvEscape(class_id) << ',' |
| | | << material << ',' |
| | | << state << ',' |
| | | << t_start << ',' |
| | | << t_end << ',' |
| | | << csvEscape(buddy) << ',' |
| | | << aoi << ',' |
| | | << csvEscape(path) << ',' |
| | | << csvEscape(params) << ',' |
| | | << csvEscape(pretty) << '\n'; |
| | | ++rows; |
| | | } |
| | | else if (rc == SQLITE_DONE) { |
| | | break; |
| | | } |
| | | else { |
| | | sqlite3_finalize(stmt); |
| | | throwIf(rc, db_, "export step"); |
| | | } |
| | | } |
| | | sqlite3_finalize(stmt); |
| | | ofs.flush(); |
| | | return rows; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #pragma once |
| | | // GlassLogDb.h - åä¾å°è£
ï¼SQLite åå
¥/æ¥è¯¢/å页/ç»è®¡/CSV 导åºï¼å·²å¯¹æ¥ SERVO::CGlassï¼ |
| | | |
| | | #include <string> |
| | | #include <vector> |
| | | #include <mutex> |
| | | #include <optional> |
| | | #include <chrono> |
| | | #include <cstdint> |
| | | #include <memory> // std::unique_ptr |
| | | |
| | | #include "CGlass.h" // éè¦ SERVO::CGlass |
| | | |
| | | // å¯å¨ç¼è¯å½ä»¤ææ¬å¤´æä»¶åèªå®ä¹è¡¨åï¼#define GLASS_LOG_TABLE "your_table_name" |
| | | #ifndef GLASS_LOG_TABLE |
| | | #define GLASS_LOG_TABLE "glass_log" |
| | | #endif |
| | | |
| | | // å置声æï¼é¿å
头æä»¶ä¾èµ sqlite3.h |
| | | struct sqlite3; |
| | | struct sqlite3_stmt; |
| | | |
| | | class GlassLogDb { |
| | | public: |
| | | // ====== å便¥å£ ====== |
| | | // åå§åï¼æåæ¢ï¼æ°æ®åºæä»¶è·¯å¾ï¼ç¬¬ä¸æ¬¡è°ç¨ä¼å建å®ä¾ |
| | | static void Init(const std::string& dbPath); |
| | | // è·åå
¨å±å®ä¾ï¼è¥æªåå§å伿å¼å¸¸ |
| | | static GlassLogDb& Instance(); |
| | | // æ¯å¦å·²åå§å |
| | | static bool IsInitialized() noexcept; |
| | | // è¿è¡ä¸åæ¢å°å¦ä¸ä»½æ°æ®åºæä»¶ï¼çå Initï¼ä¸åå¨ååå»ºï¼ |
| | | static void Reopen(const std::string& dbPath); |
| | | // å½åæ°æ®åºæä»¶è·¯å¾ï¼æªåå§åè¿åç©ºä¸²ï¼ |
| | | static std::string CurrentPath(); |
| | | |
| | | // ====== äºå¡æ§å¶ ====== |
| | | void beginTransaction(); |
| | | void commit(); |
| | | void rollback(); |
| | | |
| | | // ====== åå
¥ ====== |
| | | // ç´æ¥ä» SERVO::CGlass åå
¥ï¼æ³¨æï¼åæ°ä¸º é const å¼ç¨ï¼å ä¸ºä½ çè¥å¹² getter é constï¼ |
| | | long long insertFromCGlass(SERVO::CGlass& g); |
| | | |
| | | // æ¾å¼åæ°æå
¥ï¼tStart/tEnd å¯ç©ºï¼ååå
¥ UTC ISO8601 ææ¬æ NULLï¼ |
| | | long long insertExplicit( |
| | | int cassetteSeqNo, |
| | | int jobSeqNo, |
| | | const std::string& classId, |
| | | int materialType, |
| | | int state, |
| | | std::optional<std::chrono::system_clock::time_point> tStart, |
| | | std::optional<std::chrono::system_clock::time_point> tEnd, |
| | | const std::string& buddyId, |
| | | int aoiResult, |
| | | const std::string& pathDesc, |
| | | const std::string& paramsDesc, |
| | | const std::string& prettyString); |
| | | |
| | | // ====== æ¥è¯¢è¿åç»æ ====== |
| | | struct Row { |
| | | long long id = 0; |
| | | int cassetteSeqNo = 0; |
| | | int jobSeqNo = 0; |
| | | std::string classId; |
| | | int materialType = 0; |
| | | int state = 0; |
| | | std::string tStart; // ISO8601ï¼åºä¸ä¸º NULL åä¸ºç©ºä¸²ï¼ |
| | | std::string tEnd; // ISO8601ï¼åºä¸ä¸º NULL åä¸ºç©ºä¸²ï¼ |
| | | std::string buddyId; |
| | | int aoiResult = 0; |
| | | std::string path; |
| | | std::string params; |
| | | std::string pretty; |
| | | }; |
| | | |
| | | // ====== è¿æ»¤æ¡ä»¶ ====== |
| | | struct Filters { |
| | | std::optional<std::string> classId; // 精确å¹é
class_id |
| | | std::optional<int> cassetteSeqNo; |
| | | std::optional<int> jobSeqNo; |
| | | |
| | | // å
³é®å模ç³ï¼å¯¹ class_id / buddy_id / path / params / pretty å OR LIKE |
| | | std::optional<std::string> keyword; |
| | | |
| | | // æ¶é´èå´ï¼å¯¹ t_start è¿æ»¤ï¼å«è¾¹çï¼ISO8601 ææ¬æ¯è¾ï¼ |
| | | std::optional<std::chrono::system_clock::time_point> tStartFrom; |
| | | std::optional<std::chrono::system_clock::time_point> tStartTo; |
| | | }; |
| | | |
| | | // ====== æ¥è¯¢ / ç»è®¡ / å页 ====== |
| | | // å页æ¥è¯¢ï¼limit/offsetï¼ï¼æ id DESC |
| | | std::vector<Row> query( |
| | | const Filters& filters = {}, |
| | | int limit = 50, |
| | | int offset = 0); |
| | | |
| | | // ç»è®¡ä¸ filters ç¸åæ¡ä»¶çæ»æ° |
| | | long long count(const Filters& filters = {}); |
| | | |
| | | struct Page { |
| | | std::vector<Row> items; // å½åé¡µæ°æ® |
| | | long long total = 0; // ç¬¦åæ¡ä»¶çæ»è®°å½æ° |
| | | int limit = 0; // æ¬æ¬¡æ¥è¯¢ç页容é |
| | | int offset = 0; // æ¬æ¬¡æ¥è¯¢çèµ·å§åç§» |
| | | }; |
| | | // 䏿¬¡ååå表 + æ»æ° |
| | | Page queryPaged( |
| | | const Filters& filters = {}, |
| | | int limit = 50, |
| | | int offset = 0); |
| | | |
| | | // ====== å¯¼åº ====== |
| | | // å¯¼åºæ»¡è¶³ filters çâå
¨é¨è®°å½âï¼ä¸åå页éå¶ï¼ä¸º CSVï¼UTF-8ï¼ |
| | | // è¿åååºçæ°æ®è¡æ°ï¼ä¸å«è¡¨å¤´ï¼ |
| | | long long exportCsv(const std::string& csvPath, const Filters& filters = {}); |
| | | |
| | | // ====== ææ / æ·è´æ§å¶ ====== |
| | | ~GlassLogDb(); |
| | | GlassLogDb(const GlassLogDb&) = delete; |
| | | GlassLogDb& operator=(const GlassLogDb&) = delete; |
| | | |
| | | private: |
| | | // ä»
å
许éè¿å便¥å£æé |
| | | explicit GlassLogDb(const std::string& dbPath); |
| | | |
| | | // å
鍿å¼/å
³é/éå¼ |
| | | void openDb(const std::string& dbPath); |
| | | void closeDb() noexcept; |
| | | void reopenInternal(const std::string& dbPath); |
| | | |
| | | // 建表 / é¢ç¼è¯ / éæ¾ |
| | | void ensureSchema(); |
| | | void prepareStatements(); |
| | | void finalizeStatements() noexcept; |
| | | |
| | | // å·¥å
·ï¼time_point -> "YYYY-MM-DDTHH:MM:SSZ"ï¼UTCï¼ |
| | | static std::string toIso8601Utc(std::chrono::system_clock::time_point tp); |
| | | |
| | | // å®é
æå
¥æ§è¡ï¼æ¯æå¯ç©ºæ¶é´ï¼ |
| | | long long doInsert( |
| | | int cassetteSeqNo, |
| | | int jobSeqNo, |
| | | const std::string& classId, |
| | | int materialType, |
| | | int state, |
| | | std::optional<std::chrono::system_clock::time_point> tStart, |
| | | std::optional<std::chrono::system_clock::time_point> tEnd, |
| | | const std::string& buddyId, |
| | | int aoiResult, |
| | | const std::string& pathDesc, |
| | | const std::string& paramsDesc, |
| | | const std::string& prettyString); |
| | | |
| | | private: |
| | | // SQLite 奿 |
| | | sqlite3* db_ = nullptr; |
| | | sqlite3_stmt* stmtInsert_ = nullptr; |
| | | |
| | | // å®ä¾å
å¹¶åä¿æ¤ï¼åä¸è¿æ¥ä¸çå/读串è¡åï¼ |
| | | std::mutex mtx_; |
| | | |
| | | // å½åæ°æ®åºæä»¶è·¯å¾ |
| | | std::string dbPath_; |
| | | |
| | | // åä¾éæå¯¹è±¡ä¸å
¶äºæ¥ |
| | | static std::unique_ptr<GlassLogDb> s_inst; |
| | | static std::mutex s_instMtx; |
| | | }; |
| | |
| | | { |
| | | // æ ¹æ®å¨ SetItemColor(DWORD iItem, COLORREF color) 设置ç |
| | | // ITEMå·åCOLORREF 卿¸æ¿ä¸æ¥æ¾ï¼ç¶åè¿è¡é¢è²èµå¼ã |
| | | //LISTITEMEX_9& itemex = m_listItemColor.GetAt(m_listItemColor.FindIndex(nmcd.dwItemSpec)); |
| | | //lplvdr->clrText = itemex.colText; |
| | | //lplvdr->clrTextBk = itemex.colTextBk; |
| | | //*pResult = CDRF_DODEFAULT; |
| | | LISTITEMEX_9& itemex = m_listItemColor.GetAt(m_listItemColor.FindIndex(nmcd.dwItemSpec)); |
| | | lplvdr->clrText = itemex.colText; |
| | | lplvdr->clrTextBk = itemex.colTextBk; |
| | | *pResult = CDRF_DODEFAULT; |
| | | |
| | | /* |
| | | if (nmcd.dwItemSpec % 2 == 0) { |
| | | lplvdr->clrText = RGB(0, 0, 0); |
| | | lplvdr->clrTextBk = RGB(235, 235, 235); |
| | |
| | | lplvdr->clrTextBk = RGB(255, 255, 255); |
| | | *pResult = CDRF_DODEFAULT; |
| | | } |
| | | |
| | | */ |
| | | |
| | | break; |
| | | } |
| | |
| | | #include "CGlassPool.h" |
| | | #include "TransferManager.h" |
| | | #include "RecipeManager.h" |
| | | #include "GlassLogDb.h" |
| | | |
| | | |
| | | CModel::CModel() |
| | |
| | | cassetteType, transferMode, autoChangeEnable); |
| | | m_master.setPortType(i, portEnable, portType, portMode, cassetteType, |
| | | transferMode, autoChangeEnable); |
| | | |
| | | int seed = m_configuration.getPortCassetteSnSeed(i + 1); |
| | | m_master.setPortCassetteSnSeed(i + 1, seed); |
| | | } |
| | | } |
| | | |
| | |
| | | m_hsmsPassive.setVariableValue("PJEndID", ((SERVO::CProcessJob*)pj)->id().c_str()); |
| | | m_hsmsPassive.requestEventReportSend_PJ_End(); |
| | | }; |
| | | masterListener.onPanelStart = [&](void* pMaster, void* pj) { |
| | | m_hsmsPassive.setVariableValue("PanelStartID", ((SERVO::CGlass*)pj)->getID().c_str()); |
| | | masterListener.onPanelStart = [&](void* pMaster, void* pPanel) { |
| | | m_hsmsPassive.setVariableValue("PanelStartID", ((SERVO::CGlass*)pPanel)->getID().c_str()); |
| | | m_hsmsPassive.requestEventReportSend_Panel_Start(); |
| | | }; |
| | | masterListener.onPanelEnd = [&](void* pMaster, void* pj) { |
| | | m_hsmsPassive.setVariableValue("PanelEndID", ((SERVO::CGlass*)pj)->getID().c_str()); |
| | | masterListener.onPanelEnd = [&](void* pMaster, void* pPanel) { |
| | | m_hsmsPassive.setVariableValue("PanelEndID", ((SERVO::CGlass*)pPanel)->getID().c_str()); |
| | | m_hsmsPassive.requestEventReportSend_Panel_End(); |
| | | auto& db = GlassLogDb::Instance(); |
| | | db.insertFromCGlass((*(SERVO::CGlass*)pPanel)); |
| | | SERVO::CGlass* pBuddy = ((SERVO::CGlass*)pPanel)->getBuddy(); |
| | | if (pBuddy != nullptr) { |
| | | db.insertFromCGlass(*pBuddy); |
| | | } |
| | | }; |
| | | m_master.setListener(masterListener); |
| | | m_master.setContinuousTransferCount(m_configuration.getContinuousTransferCount()); |
| | |
| | | alarmManager.readAlarmFile(szBuffer); |
| | | |
| | | |
| | | // Glassæ°æ®åº |
| | | strLogDir.Format(_T("%s\\db\\process.db"), (LPTSTR)(LPCTSTR)m_strWorkDir); |
| | | std::string path((LPTSTR)(LPCTSTR)strLogDir); |
| | | GlassLogDb::Init(path); |
| | | |
| | | |
| | | return 0; |
| | | } |
| | |
| | | void CPageAlarm::UpdatePageData() |
| | | { |
| | | // æ ¹æ®è¿æ»¤æ¡ä»¶å è½½æ°æ®ï¼æä¾æè¿°åæ¶é´èå´æ¥è¯¢ |
| | | auto vecData = AlarmManager::getInstance().getFilteredAlarms("", "", m_strDeviceName, m_strUnitName, m_strKeyword, m_szTimeStart, m_szTimeEnd, m_nCurPage, PAGE_SIZE); |
| | | auto vecData = AlarmManager::getInstance().getFilteredAlarms(m_strKeyword, m_szTimeStart, m_szTimeEnd, m_nCurPage, PAGE_SIZE); |
| | | |
| | | // å¡«å
æ°æ®å°æ§ä»¶ |
| | | CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_ALARM); |
| | |
| | | |
| | | |
| | | // è®¡ç®æ»é¡µæ° |
| | | int totalRecords = AlarmManager::getInstance().getTotalAlarmCount("", "", m_strDeviceName, m_strUnitName, m_strKeyword, m_szTimeStart, m_szTimeEnd); |
| | | int totalRecords = AlarmManager::getInstance().getTotalAlarmCount(m_strKeyword, m_szTimeStart, m_szTimeEnd); |
| | | m_nTotalPages = (totalRecords + PAGE_SIZE - 1) / PAGE_SIZE; |
| | | m_nCurPage = 1; |
| | | |
| | |
| | | } |
| | | |
| | | // è®¡ç®æ»é¡µæ° |
| | | int totalRecords = AlarmManager::getInstance().getTotalAlarmCount("", "", m_strDeviceName, m_strUnitName, m_strKeyword, m_szTimeStart, m_szTimeEnd); |
| | | int totalRecords = AlarmManager::getInstance().getTotalAlarmCount(m_strKeyword, m_szTimeStart, m_szTimeEnd); |
| | | m_nTotalPages = (totalRecords + PAGE_SIZE - 1) / PAGE_SIZE; |
| | | m_nCurPage = 1; |
| | | |
| | |
| | | <ClInclude Include="CPortStatusReport.h" /> |
| | | <ClInclude Include="CRobotTaskDlg.h" /> |
| | | <ClInclude Include="CSVData.h" /> |
| | | <ClInclude Include="CServoUtilsTool.h" /> |
| | | <ClInclude Include="CVariable.h" /> |
| | | <ClInclude Include="DeviceRecipeParamDlg.h" /> |
| | | <ClInclude Include="GlassJson.h" /> |
| | | <ClInclude Include="GlassLogDb.h" /> |
| | | <ClInclude Include="GridControl\CellRange.h" /> |
| | | <ClInclude Include="GridControl\GridCell.h" /> |
| | | <ClInclude Include="GridControl\GridCellBase.h" /> |
| | |
| | | <ClInclude Include="ServoDlg.h" /> |
| | | <ClInclude Include="ServoGraph.h" /> |
| | | <ClInclude Include="ServoMemDC.h" /> |
| | | <ClInclude Include="sqlite3.h" /> |
| | | <ClInclude Include="sqlite3ext.h" /> |
| | | <ClInclude Include="stdafx.h" /> |
| | | <ClInclude Include="SystemLogManager.h" /> |
| | | <ClInclude Include="SystemLogManagerDlg.h" /> |
| | |
| | | <ClCompile Include="CPortStatusReport.cpp" /> |
| | | <ClCompile Include="CRobotTaskDlg.cpp" /> |
| | | <ClCompile Include="CSVData.cpp" /> |
| | | <ClCompile Include="CServoUtilsTool.cpp" /> |
| | | <ClCompile Include="CVariable.cpp" /> |
| | | <ClCompile Include="DeviceRecipeParamDlg.cpp" /> |
| | | <ClCompile Include="GlassJson.cpp" /> |
| | | <ClCompile Include="GlassLogDb.cpp" /> |
| | | <ClCompile Include="GridControl\GridCell.cpp" /> |
| | | <ClCompile Include="GridControl\GridCellBase.cpp" /> |
| | | <ClCompile Include="GridControl\GridCellButton.cpp" /> |
| | |
| | | <ClCompile Include="ServoDlg.cpp" /> |
| | | <ClCompile Include="ServoGraph.cpp" /> |
| | | <ClCompile Include="ServoMemDC.cpp" /> |
| | | <ClCompile Include="sqlite3.c"> |
| | | <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader> |
| | | <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader> |
| | | </ClCompile> |
| | | <ClCompile Include="stdafx.cpp"> |
| | | <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> |
| | | <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> |
| | |
| | | </ClCompile> |
| | | <ClCompile Include="DeviceRecipeParamDlg.cpp" /> |
| | | <ClCompile Include="CSVData.cpp" /> |
| | | <ClCompile Include="CServoUtilsTool.cpp" /> |
| | | <ClCompile Include="GlassLogDb.cpp" /> |
| | | <ClCompile Include="sqlite3.c" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ClInclude Include="AlarmManager.h" /> |
| | |
| | | </ClInclude> |
| | | <ClInclude Include="DeviceRecipeParamDlg.h" /> |
| | | <ClInclude Include="CSVData.h" /> |
| | | <ClInclude Include="CServoUtilsTool.h" /> |
| | | <ClInclude Include="GlassLogDb.h" /> |
| | | <ClInclude Include="sqlite3.h" /> |
| | | <ClInclude Include="sqlite3ext.h" /> |
| | | </ItemGroup> |
| | | <ItemGroup> |
| | | <ResourceCompile Include="Servo.rc" /> |
| | |
| | | m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_ALARM); |
| | | m_pMyStatusbar->setForegroundColor(RGB(0, 0, 0)); |
| | | m_pMyStatusbar->setRunTimeText("å¯å¨å¤±è´¥."); |
| | | m_pTopToolbar->GetBtn(IDC_BUTTON_ALARM)->EnableWindow(TRUE); |
| | | } |
| | | else if (state == SERVO::MASTERSTATE::ATHERERROR) { |
| | | m_pTopToolbar->GetBtn(IDC_BUTTON_RUN)->EnableWindow(TRUE); |
| | | m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_BATCH)->EnableWindow(TRUE); |
| | | m_pTopToolbar->GetBtn(IDC_BUTTON_RUN_CT)->EnableWindow(TRUE); |
| | | m_pTopToolbar->GetBtn(IDC_BUTTON_STOP)->EnableWindow(FALSE); |
| | | m_pMyStatusbar->setBackgroundColor(STATUSBAR_BK_ALARM); |
| | | m_pMyStatusbar->setForegroundColor(RGB(0, 0, 0)); |
| | | m_pMyStatusbar->setRunTimeText(theApp.m_model.getMaster().getLastErrorText().c_str()); |
| | | if (theApp.m_model.getMaster().getLastError() == ER_CODE_AOI_NG) { |
| | | AfxMessageBox(_T("AOIæ£æµå¤±è´¥ï¼è¯·æä½åä»å
¥è§£å³é®é¢ï¼")); |
| | | } |
| | | m_pTopToolbar->GetBtn(IDC_BUTTON_ALARM)->EnableWindow(TRUE); |
| | | } |
| | | else if (state == SERVO::MASTERSTATE::RUNNING || state == SERVO::MASTERSTATE::RUNNING_CONTINUOUS_TRANSFER |
| | | || state == SERVO::MASTERSTATE::RUNNING_BATCH) { |
| | |
| | | |
| | | void CServoDlg::OnMenuHelpAbout() |
| | | { |
| | | theApp.m_model.getMaster().test(); |
| | | CAboutDlg dlgAbout; |
| | | dlgAbout.DoModal(); |
| | | } |
| | |
| | | #include <chrono> |
| | | #include <memory> |
| | | #include <sstream> |
| | | #include <algorithm> |
| | | |
| | | |
| | | CToolUnits::CToolUnits() |
| | |
| | | if (nLength > 0) { |
| | | strOut = std::string(pszBuffer, nLength); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // FILETIME(UTC) -> time_point |
| | | std::chrono::system_clock::time_point CToolUnits::FileTimeToTimePointUTC(const FILETIME& ftUtc) { |
| | | ULARGE_INTEGER ull; |
| | | ull.LowPart = ftUtc.dwLowDateTime; |
| | | ull.HighPart = ftUtc.dwHighDateTime; |
| | | // 1601-01-01 å° 1970-01-01 ç 100ns tick |
| | | constexpr unsigned long long EPOCH_DIFF_100NS = 116444736000000000ULL; |
| | | unsigned long long t100 = ull.QuadPart - EPOCH_DIFF_100NS; // 1970ä»¥æ¥ 100ns |
| | | // é¿å
溢åºï¼100ns -> us |
| | | unsigned long long us = t100 / 10ULL; |
| | | return std::chrono::system_clock::time_point(std::chrono::microseconds(us)); |
| | | } |
| | | |
| | | // ä» CDateTimeCtrl 忬尿¶é´å¹¶è½¬ä¸º UTC time_point |
| | | // è¿å false 表示æ§ä»¶æ¯âæ å¼â(DTS_SHOWNONE / GDT_NONE) æè½¬æ¢å¤±è´¥ |
| | | bool CToolUnits::GetCtrlTimeUtc(const CDateTimeCtrl& ctrl, |
| | | std::chrono::system_clock::time_point& outUtc) |
| | | { |
| | | SYSTEMTIME stLocal{}; |
| | | DWORD rc = const_cast<CDateTimeCtrl&>(ctrl).GetTime(&stLocal); // MFC ååéè¦éconst |
| | | if (rc != GDT_VALID) return false; // GDT_NONE |
| | | |
| | | SYSTEMTIME stUtc{}; |
| | | if (!TzSpecificLocalTimeToSystemTime(nullptr, &stLocal, &stUtc)) return false; |
| | | |
| | | FILETIME ftUtc{}; |
| | | if (!SystemTimeToFileTime(&stUtc, &ftUtc)) return false; |
| | | |
| | | outUtc = FileTimeToTimePointUTC(ftUtc); |
| | | return true; |
| | | } |
| | | |
| | | // è¥ä½ çæ¥ææ§ä»¶åªæ¾ç¤ºâæ¥æä¸æ¾ç¤ºæ¶é´âï¼æ³æ From è°æ´å° 00:00:00 / To è°æ´å° 23:59:59.999ï¼ |
| | | bool CToolUnits::GetCtrlDateRangeUtc_StartOfDay(const CDateTimeCtrl& ctrl, |
| | | std::chrono::system_clock::time_point& outUtc) |
| | | { |
| | | SYSTEMTIME st{}; |
| | | DWORD rc = const_cast<CDateTimeCtrl&>(ctrl).GetTime(&st); |
| | | if (rc != GDT_VALID) return false; |
| | | st.wHour = 0; st.wMinute = 0; st.wSecond = 0; st.wMilliseconds = 0; |
| | | |
| | | SYSTEMTIME stUtc{}; |
| | | if (!TzSpecificLocalTimeToSystemTime(nullptr, &st, &stUtc)) return false; |
| | | FILETIME ftUtc{}; if (!SystemTimeToFileTime(&stUtc, &ftUtc)) return false; |
| | | outUtc = FileTimeToTimePointUTC(ftUtc); |
| | | return true; |
| | | } |
| | | |
| | | bool CToolUnits::GetCtrlDateRangeUtc_EndOfDay(const CDateTimeCtrl& ctrl, |
| | | std::chrono::system_clock::time_point& outUtc) |
| | | { |
| | | SYSTEMTIME st{}; |
| | | DWORD rc = const_cast<CDateTimeCtrl&>(ctrl).GetTime(&st); |
| | | if (rc != GDT_VALID) return false; |
| | | st.wHour = 23; st.wMinute = 59; st.wSecond = 59; st.wMilliseconds = 999; |
| | | |
| | | SYSTEMTIME stUtc{}; |
| | | if (!TzSpecificLocalTimeToSystemTime(nullptr, &st, &stUtc)) return false; |
| | | FILETIME ftUtc{}; if (!SystemTimeToFileTime(&stUtc, &ftUtc)) return false; |
| | | outUtc = FileTimeToTimePointUTC(ftUtc); |
| | | return true; |
| | | } |
| | | |
| | | // ---------- æ¬å° SYSTEMTIME -> UTC time_point ---------- |
| | | std::chrono::system_clock::time_point CToolUnits::LocalSTtoUtcTP(const SYSTEMTIME& stLocal) { |
| | | SYSTEMTIME stUtc{}; |
| | | if (!TzSpecificLocalTimeToSystemTime(nullptr, &stLocal, &stUtc)) |
| | | throw std::runtime_error("TzSpecificLocalTimeToSystemTime failed"); |
| | | FILETIME ftUtc{}; |
| | | if (!SystemTimeToFileTime(&stUtc, &ftUtc)) |
| | | throw std::runtime_error("SystemTimeToFileTime failed"); |
| | | return FileTimeToTimePointUTC(ftUtc); |
| | | } |
| | | |
| | | // çææ¬å° SYSTEMTIME |
| | | SYSTEMTIME CToolUnits::MakeLocalST(int y, int m, int d, int hh, int mi, int ss, int ms) { |
| | | SYSTEMTIME st{}; |
| | | st.wYear = (WORD)y; st.wMonth = (WORD)m; st.wDay = (WORD)d; |
| | | st.wHour = (WORD)hh; st.wMinute = (WORD)mi; st.wSecond = (WORD)ss; st.wMilliseconds = (WORD)ms; |
| | | return st; |
| | | } |
| | | |
| | | // é°å¹´ / æå¤©æ° |
| | | bool CToolUnits::IsLeap(int y) { |
| | | return ((y % 4 == 0) && (y % 100 != 0)) || (y % 400 == 0); |
| | | } |
| | | |
| | | int CToolUnits::DaysInMonth(int y, int m) { |
| | | static const int d[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 }; |
| | | return (m == 2) ? d[m] + (IsLeap(y) ? 1 : 0) : d[m]; |
| | | } |
| | | |
| | | // æ¬å°âä»å¤©âçå¹´ææ¥ |
| | | void CToolUnits::GetTodayYMD_Local(int& y, int& m, int& d) { |
| | | SYSTEMTIME now{}; GetLocalTime(&now); |
| | | y = now.wYear; m = now.wMonth; d = now.wDay; |
| | | } |
| | | |
| | | // æ¬å°æ¥åä¸å n 天ï¼ä»æ¯æ¬å° Y/M/Dï¼ |
| | | void CToolUnits::LocalCalendarMinusDays(int& y, int& m, int& d, int nDays) { |
| | | std::tm t{}; |
| | | t.tm_year = y - 1900; t.tm_mon = m - 1; t.tm_mday = d; |
| | | t.tm_hour = 0; t.tm_min = 0; t.tm_sec = 0; |
| | | t.tm_mday -= nDays; |
| | | (void)std::mktime(&t); // ææ¬å°æ¶åºå½ä¸å |
| | | y = t.tm_year + 1900; m = t.tm_mon + 1; d = t.tm_mday; |
| | | } |
| | | |
| | | // ====== æ ¸å¿ï¼è®¡ç®é¢è®¾åºé´ç UTC [from, to] ====== |
| | | // è¯ä¹ï¼ |
| | | // - Today : æ¬å°âä»å¤©â00:00:00.000 ï½ ä»å¤© 23:59:59.999 |
| | | // - Last7Days : æ¬å°â6 天åâ00:00:00.000 ï½ ä»å¤© 23:59:59.999ï¼å
± 7 个èªç¶æ¥ï¼å«ä»å¤©ï¼ |
| | | // - ThisMonth : æ¬å°â彿 1 å·â00:00:00.000 ï½ æ¬ææ« 23:59:59.999 |
| | | // - ThisYear : æ¬å°âå½å¹´ 1/1â00:00:00.000 ï½ å½å¹´æ« 23:59:59.999 |
| | | std::pair<std::chrono::system_clock::time_point, |
| | | std::chrono::system_clock::time_point> |
| | | CToolUnits::CalcQuickRangeUtc(QuickRange r) |
| | | { |
| | | int y, m, d; |
| | | GetTodayYMD_Local(y, m, d); |
| | | |
| | | SYSTEMTIME stFromLocal{}, stToLocal{}; |
| | | |
| | | switch (r) { |
| | | case QuickRange::Today: |
| | | stFromLocal = MakeLocalST(y, m, d, 0, 0, 0, 0); |
| | | stToLocal = MakeLocalST(y, m, d, 23, 59, 59, 999); |
| | | break; |
| | | case QuickRange::Last7Days: { |
| | | int y2 = y, m2 = m, d2 = d; |
| | | LocalCalendarMinusDays(y2, m2, d2, 6); |
| | | stFromLocal = MakeLocalST(y2, m2, d2, 0, 0, 0, 0); |
| | | stToLocal = MakeLocalST(y, m, d, 23, 59, 59, 999); |
| | | break; |
| | | } |
| | | case QuickRange::ThisMonth: { |
| | | int lastDay = DaysInMonth(y, m); |
| | | stFromLocal = MakeLocalST(y, m, 1, 0, 0, 0, 0); |
| | | stToLocal = MakeLocalST(y, m, lastDay, 23, 59, 59, 999); |
| | | break; |
| | | } |
| | | case QuickRange::ThisYear: |
| | | stFromLocal = MakeLocalST(y, 1, 1, 0, 0, 0, 0); |
| | | stToLocal = MakeLocalST(y, 12, DaysInMonth(y, 12), 23, 59, 59, 999); |
| | | break; |
| | | default: |
| | | throw std::invalid_argument("CalcQuickRangeUtc: unsupported range"); |
| | | } |
| | | |
| | | auto fromUtc = LocalSTtoUtcTP(stFromLocal); |
| | | auto toUtc = LocalSTtoUtcTP(stToLocal); |
| | | return { fromUtc, toUtc }; |
| | | } |
| | | |
| | | // å°å·¥å
·ï¼ASCII ä¸åºå大å°åå
å«ï¼ä¸æçé ASCII ä¸åå½±åï¼ä½ä¹ä¸éè¦å¤§å°å转æ¢ï¼ |
| | | bool CToolUnits::containsCI(const std::string& hay, const std::string& needle) { |
| | | if (needle.empty()) return true; |
| | | auto toLower = [](std::string s) { std::transform(s.begin(), s.end(), s.begin(), |
| | | [](unsigned char c) { return (char)std::tolower(c); }); return s; }; |
| | | std::string h = toLower(hay), n = toLower(needle); |
| | | return h.find(n) != std::string::npos; |
| | | } |
| | | |
| | | // ------- æ¬å°æ¶é´ ------- |
| | | std::string CToolUnits::TimePointToLocalString(const std::optional<TP>& tp, |
| | | const char* fmt/* = "%Y-%m-%d %H:%M:%S"*/) |
| | | { |
| | | if (!tp) return {}; |
| | | std::time_t t = std::chrono::system_clock::to_time_t(*tp); |
| | | std::tm tm{}; |
| | | #if defined(_WIN32) |
| | | localtime_s(&tm, &t); |
| | | #else |
| | | localtime_r(&t, &tm); |
| | | #endif |
| | | char buf[64]{}; |
| | | std::strftime(buf, sizeof(buf), fmt, &tm); |
| | | return buf; |
| | | } |
| | | |
| | | // ------- UTC æ¶é´ ------- |
| | | std::string CToolUnits::TimePointToUtcString(const std::optional<TP>& tp, |
| | | const char* fmt/* = "%Y-%m-%d %H:%M:%S"*/) |
| | | { |
| | | if (!tp) return {}; |
| | | std::time_t t = std::chrono::system_clock::to_time_t(*tp); |
| | | std::tm tm{}; |
| | | #if defined(_WIN32) |
| | | gmtime_s(&tm, &t); |
| | | #else |
| | | gmtime_r(&t, &tm); |
| | | #endif |
| | | char buf[64]{}; |
| | | std::strftime(buf, sizeof(buf), fmt, &tm); |
| | | return buf; |
| | | } |
| | | |
| | | std::string CToolUnits::TimePointToLocalStringMs(const std::optional<TP>& tp) |
| | | { |
| | | if (!tp) return {}; |
| | | using namespace std::chrono; |
| | | auto ms_since_epoch = duration_cast<milliseconds>(tp->time_since_epoch()); |
| | | auto ms = static_cast<int>(ms_since_epoch.count() % 1000); |
| | | |
| | | std::time_t t = system_clock::to_time_t(*tp); |
| | | std::tm tm{}; |
| | | #if defined(_WIN32) |
| | | localtime_s(&tm, &t); |
| | | #else |
| | | localtime_r(&t, &tm); |
| | | #endif |
| | | char date[32]{}; |
| | | std::strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", &tm); |
| | | |
| | | char out[40]{}; |
| | | std::snprintf(out, sizeof(out), "%s.%03d", date, ms); |
| | | return out; |
| | | } |
| | |
| | | #pragma once |
| | | #include <string> |
| | | #include <chrono> |
| | | #include <optional> |
| | | #include <utility> |
| | | |
| | | enum class QuickRange { Today, Last7Days, ThisMonth, ThisYear }; |
| | | using TP = std::chrono::system_clock::time_point; |
| | | class CToolUnits |
| | | { |
| | | public: |
| | |
| | | static bool startsWith(const std::string& str, const std::string& prefix); |
| | | static std::string& toHexString(int value, std::string& strOut); |
| | | static void convertString(const char* pszBuffer, int size, std::string& strOut); |
| | | static inline std::chrono::system_clock::time_point FileTimeToTimePointUTC(const FILETIME& ftUtc); |
| | | static bool GetCtrlTimeUtc(const CDateTimeCtrl& ctrl, |
| | | std::chrono::system_clock::time_point& outUtc); |
| | | static bool GetCtrlDateRangeUtc_StartOfDay(const CDateTimeCtrl& ctrl, |
| | | std::chrono::system_clock::time_point& outUtc); |
| | | static bool GetCtrlDateRangeUtc_EndOfDay(const CDateTimeCtrl& ctrl, |
| | | std::chrono::system_clock::time_point& outUtc); |
| | | static std::chrono::system_clock::time_point CToolUnits::LocalSTtoUtcTP(const SYSTEMTIME& stLocal); |
| | | static SYSTEMTIME CToolUnits::MakeLocalST(int y, int m, int d, int hh, int mi, int ss, int ms); |
| | | static bool IsLeap(int y); |
| | | static int DaysInMonth(int y, int m); |
| | | static void GetTodayYMD_Local(int& y, int& m, int& d); |
| | | static void LocalCalendarMinusDays(int& y, int& m, int& d, int nDays); |
| | | static std::pair<std::chrono::system_clock::time_point, |
| | | std::chrono::system_clock::time_point> |
| | | CalcQuickRangeUtc(QuickRange r); |
| | | static bool containsCI(const std::string& hay, const std::string& needle); |
| | | static std::string TimePointToLocalString(const std::optional<TP>& tp, |
| | | const char* fmt = "%Y-%m-%d %H:%M:%S"); |
| | | static std::string TimePointToUtcString(const std::optional<TP>& tp, |
| | | const char* fmt = "%Y-%m-%d %H:%M:%S"); |
| | | static std::string TimePointToLocalStringMs(const std::optional<TP>& tp); |
| | | }; |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | ** 2006 June 7 |
| | | ** |
| | | ** The author disclaims copyright to this source code. In place of |
| | | ** a legal notice, here is a blessing: |
| | | ** |
| | | ** May you do good and not evil. |
| | | ** May you find forgiveness for yourself and forgive others. |
| | | ** May you share freely, never taking more than you give. |
| | | ** |
| | | ************************************************************************* |
| | | ** This header file defines the SQLite interface for use by |
| | | ** shared libraries that want to be imported as extensions into |
| | | ** an SQLite instance. Shared libraries that intend to be loaded |
| | | ** as extensions by SQLite should #include this file instead of |
| | | ** sqlite3.h. |
| | | */ |
| | | #ifndef SQLITE3EXT_H |
| | | #define SQLITE3EXT_H |
| | | #include "sqlite3.h" |
| | | |
| | | /* |
| | | ** The following structure holds pointers to all of the SQLite API |
| | | ** routines. |
| | | ** |
| | | ** WARNING: In order to maintain backwards compatibility, add new |
| | | ** interfaces to the end of this structure only. If you insert new |
| | | ** interfaces in the middle of this structure, then older different |
| | | ** versions of SQLite will not be able to load each other's shared |
| | | ** libraries! |
| | | */ |
| | | struct sqlite3_api_routines { |
| | | void * (*aggregate_context)(sqlite3_context*,int nBytes); |
| | | int (*aggregate_count)(sqlite3_context*); |
| | | int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*)); |
| | | int (*bind_double)(sqlite3_stmt*,int,double); |
| | | int (*bind_int)(sqlite3_stmt*,int,int); |
| | | int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64); |
| | | int (*bind_null)(sqlite3_stmt*,int); |
| | | int (*bind_parameter_count)(sqlite3_stmt*); |
| | | int (*bind_parameter_index)(sqlite3_stmt*,const char*zName); |
| | | const char * (*bind_parameter_name)(sqlite3_stmt*,int); |
| | | int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*)); |
| | | int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*)); |
| | | int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*); |
| | | int (*busy_handler)(sqlite3*,int(*)(void*,int),void*); |
| | | int (*busy_timeout)(sqlite3*,int ms); |
| | | int (*changes)(sqlite3*); |
| | | int (*close)(sqlite3*); |
| | | int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*, |
| | | int eTextRep,const char*)); |
| | | int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*, |
| | | int eTextRep,const void*)); |
| | | const void * (*column_blob)(sqlite3_stmt*,int iCol); |
| | | int (*column_bytes)(sqlite3_stmt*,int iCol); |
| | | int (*column_bytes16)(sqlite3_stmt*,int iCol); |
| | | int (*column_count)(sqlite3_stmt*pStmt); |
| | | const char * (*column_database_name)(sqlite3_stmt*,int); |
| | | const void * (*column_database_name16)(sqlite3_stmt*,int); |
| | | const char * (*column_decltype)(sqlite3_stmt*,int i); |
| | | const void * (*column_decltype16)(sqlite3_stmt*,int); |
| | | double (*column_double)(sqlite3_stmt*,int iCol); |
| | | int (*column_int)(sqlite3_stmt*,int iCol); |
| | | sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol); |
| | | const char * (*column_name)(sqlite3_stmt*,int); |
| | | const void * (*column_name16)(sqlite3_stmt*,int); |
| | | const char * (*column_origin_name)(sqlite3_stmt*,int); |
| | | const void * (*column_origin_name16)(sqlite3_stmt*,int); |
| | | const char * (*column_table_name)(sqlite3_stmt*,int); |
| | | const void * (*column_table_name16)(sqlite3_stmt*,int); |
| | | const unsigned char * (*column_text)(sqlite3_stmt*,int iCol); |
| | | const void * (*column_text16)(sqlite3_stmt*,int iCol); |
| | | int (*column_type)(sqlite3_stmt*,int iCol); |
| | | sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol); |
| | | void * (*commit_hook)(sqlite3*,int(*)(void*),void*); |
| | | int (*complete)(const char*sql); |
| | | int (*complete16)(const void*sql); |
| | | int (*create_collation)(sqlite3*,const char*,int,void*, |
| | | int(*)(void*,int,const void*,int,const void*)); |
| | | int (*create_collation16)(sqlite3*,const void*,int,void*, |
| | | int(*)(void*,int,const void*,int,const void*)); |
| | | int (*create_function)(sqlite3*,const char*,int,int,void*, |
| | | void (*xFunc)(sqlite3_context*,int,sqlite3_value**), |
| | | void (*xStep)(sqlite3_context*,int,sqlite3_value**), |
| | | void (*xFinal)(sqlite3_context*)); |
| | | int (*create_function16)(sqlite3*,const void*,int,int,void*, |
| | | void (*xFunc)(sqlite3_context*,int,sqlite3_value**), |
| | | void (*xStep)(sqlite3_context*,int,sqlite3_value**), |
| | | void (*xFinal)(sqlite3_context*)); |
| | | int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*); |
| | | int (*data_count)(sqlite3_stmt*pStmt); |
| | | sqlite3 * (*db_handle)(sqlite3_stmt*); |
| | | int (*declare_vtab)(sqlite3*,const char*); |
| | | int (*enable_shared_cache)(int); |
| | | int (*errcode)(sqlite3*db); |
| | | const char * (*errmsg)(sqlite3*); |
| | | const void * (*errmsg16)(sqlite3*); |
| | | int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**); |
| | | int (*expired)(sqlite3_stmt*); |
| | | int (*finalize)(sqlite3_stmt*pStmt); |
| | | void (*free)(void*); |
| | | void (*free_table)(char**result); |
| | | int (*get_autocommit)(sqlite3*); |
| | | void * (*get_auxdata)(sqlite3_context*,int); |
| | | int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**); |
| | | int (*global_recover)(void); |
| | | void (*interruptx)(sqlite3*); |
| | | sqlite_int64 (*last_insert_rowid)(sqlite3*); |
| | | const char * (*libversion)(void); |
| | | int (*libversion_number)(void); |
| | | void *(*malloc)(int); |
| | | char * (*mprintf)(const char*,...); |
| | | int (*open)(const char*,sqlite3**); |
| | | int (*open16)(const void*,sqlite3**); |
| | | int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); |
| | | int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); |
| | | void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*); |
| | | void (*progress_handler)(sqlite3*,int,int(*)(void*),void*); |
| | | void *(*realloc)(void*,int); |
| | | int (*reset)(sqlite3_stmt*pStmt); |
| | | void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*)); |
| | | void (*result_double)(sqlite3_context*,double); |
| | | void (*result_error)(sqlite3_context*,const char*,int); |
| | | void (*result_error16)(sqlite3_context*,const void*,int); |
| | | void (*result_int)(sqlite3_context*,int); |
| | | void (*result_int64)(sqlite3_context*,sqlite_int64); |
| | | void (*result_null)(sqlite3_context*); |
| | | void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*)); |
| | | void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*)); |
| | | void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*)); |
| | | void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*)); |
| | | void (*result_value)(sqlite3_context*,sqlite3_value*); |
| | | void * (*rollback_hook)(sqlite3*,void(*)(void*),void*); |
| | | int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*, |
| | | const char*,const char*),void*); |
| | | void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*)); |
| | | char * (*xsnprintf)(int,char*,const char*,...); |
| | | int (*step)(sqlite3_stmt*); |
| | | int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*, |
| | | char const**,char const**,int*,int*,int*); |
| | | void (*thread_cleanup)(void); |
| | | int (*total_changes)(sqlite3*); |
| | | void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*); |
| | | int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*); |
| | | void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*, |
| | | sqlite_int64),void*); |
| | | void * (*user_data)(sqlite3_context*); |
| | | const void * (*value_blob)(sqlite3_value*); |
| | | int (*value_bytes)(sqlite3_value*); |
| | | int (*value_bytes16)(sqlite3_value*); |
| | | double (*value_double)(sqlite3_value*); |
| | | int (*value_int)(sqlite3_value*); |
| | | sqlite_int64 (*value_int64)(sqlite3_value*); |
| | | int (*value_numeric_type)(sqlite3_value*); |
| | | const unsigned char * (*value_text)(sqlite3_value*); |
| | | const void * (*value_text16)(sqlite3_value*); |
| | | const void * (*value_text16be)(sqlite3_value*); |
| | | const void * (*value_text16le)(sqlite3_value*); |
| | | int (*value_type)(sqlite3_value*); |
| | | char *(*vmprintf)(const char*,va_list); |
| | | /* Added ??? */ |
| | | int (*overload_function)(sqlite3*, const char *zFuncName, int nArg); |
| | | /* Added by 3.3.13 */ |
| | | int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**); |
| | | int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**); |
| | | int (*clear_bindings)(sqlite3_stmt*); |
| | | /* Added by 3.4.1 */ |
| | | int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*, |
| | | void (*xDestroy)(void *)); |
| | | /* Added by 3.5.0 */ |
| | | int (*bind_zeroblob)(sqlite3_stmt*,int,int); |
| | | int (*blob_bytes)(sqlite3_blob*); |
| | | int (*blob_close)(sqlite3_blob*); |
| | | int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64, |
| | | int,sqlite3_blob**); |
| | | int (*blob_read)(sqlite3_blob*,void*,int,int); |
| | | int (*blob_write)(sqlite3_blob*,const void*,int,int); |
| | | int (*create_collation_v2)(sqlite3*,const char*,int,void*, |
| | | int(*)(void*,int,const void*,int,const void*), |
| | | void(*)(void*)); |
| | | int (*file_control)(sqlite3*,const char*,int,void*); |
| | | sqlite3_int64 (*memory_highwater)(int); |
| | | sqlite3_int64 (*memory_used)(void); |
| | | sqlite3_mutex *(*mutex_alloc)(int); |
| | | void (*mutex_enter)(sqlite3_mutex*); |
| | | void (*mutex_free)(sqlite3_mutex*); |
| | | void (*mutex_leave)(sqlite3_mutex*); |
| | | int (*mutex_try)(sqlite3_mutex*); |
| | | int (*open_v2)(const char*,sqlite3**,int,const char*); |
| | | int (*release_memory)(int); |
| | | void (*result_error_nomem)(sqlite3_context*); |
| | | void (*result_error_toobig)(sqlite3_context*); |
| | | int (*sleep)(int); |
| | | void (*soft_heap_limit)(int); |
| | | sqlite3_vfs *(*vfs_find)(const char*); |
| | | int (*vfs_register)(sqlite3_vfs*,int); |
| | | int (*vfs_unregister)(sqlite3_vfs*); |
| | | int (*xthreadsafe)(void); |
| | | void (*result_zeroblob)(sqlite3_context*,int); |
| | | void (*result_error_code)(sqlite3_context*,int); |
| | | int (*test_control)(int, ...); |
| | | void (*randomness)(int,void*); |
| | | sqlite3 *(*context_db_handle)(sqlite3_context*); |
| | | int (*extended_result_codes)(sqlite3*,int); |
| | | int (*limit)(sqlite3*,int,int); |
| | | sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*); |
| | | const char *(*sql)(sqlite3_stmt*); |
| | | int (*status)(int,int*,int*,int); |
| | | int (*backup_finish)(sqlite3_backup*); |
| | | sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*); |
| | | int (*backup_pagecount)(sqlite3_backup*); |
| | | int (*backup_remaining)(sqlite3_backup*); |
| | | int (*backup_step)(sqlite3_backup*,int); |
| | | const char *(*compileoption_get)(int); |
| | | int (*compileoption_used)(const char*); |
| | | int (*create_function_v2)(sqlite3*,const char*,int,int,void*, |
| | | void (*xFunc)(sqlite3_context*,int,sqlite3_value**), |
| | | void (*xStep)(sqlite3_context*,int,sqlite3_value**), |
| | | void (*xFinal)(sqlite3_context*), |
| | | void(*xDestroy)(void*)); |
| | | int (*db_config)(sqlite3*,int,...); |
| | | sqlite3_mutex *(*db_mutex)(sqlite3*); |
| | | int (*db_status)(sqlite3*,int,int*,int*,int); |
| | | int (*extended_errcode)(sqlite3*); |
| | | void (*log)(int,const char*,...); |
| | | sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64); |
| | | const char *(*sourceid)(void); |
| | | int (*stmt_status)(sqlite3_stmt*,int,int); |
| | | int (*strnicmp)(const char*,const char*,int); |
| | | int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*); |
| | | int (*wal_autocheckpoint)(sqlite3*,int); |
| | | int (*wal_checkpoint)(sqlite3*,const char*); |
| | | void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*); |
| | | int (*blob_reopen)(sqlite3_blob*,sqlite3_int64); |
| | | int (*vtab_config)(sqlite3*,int op,...); |
| | | int (*vtab_on_conflict)(sqlite3*); |
| | | /* Version 3.7.16 and later */ |
| | | int (*close_v2)(sqlite3*); |
| | | const char *(*db_filename)(sqlite3*,const char*); |
| | | int (*db_readonly)(sqlite3*,const char*); |
| | | int (*db_release_memory)(sqlite3*); |
| | | const char *(*errstr)(int); |
| | | int (*stmt_busy)(sqlite3_stmt*); |
| | | int (*stmt_readonly)(sqlite3_stmt*); |
| | | int (*stricmp)(const char*,const char*); |
| | | int (*uri_boolean)(const char*,const char*,int); |
| | | sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64); |
| | | const char *(*uri_parameter)(const char*,const char*); |
| | | char *(*xvsnprintf)(int,char*,const char*,va_list); |
| | | int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*); |
| | | /* Version 3.8.7 and later */ |
| | | int (*auto_extension)(void(*)(void)); |
| | | int (*bind_blob64)(sqlite3_stmt*,int,const void*,sqlite3_uint64, |
| | | void(*)(void*)); |
| | | int (*bind_text64)(sqlite3_stmt*,int,const char*,sqlite3_uint64, |
| | | void(*)(void*),unsigned char); |
| | | int (*cancel_auto_extension)(void(*)(void)); |
| | | int (*load_extension)(sqlite3*,const char*,const char*,char**); |
| | | void *(*malloc64)(sqlite3_uint64); |
| | | sqlite3_uint64 (*msize)(void*); |
| | | void *(*realloc64)(void*,sqlite3_uint64); |
| | | void (*reset_auto_extension)(void); |
| | | void (*result_blob64)(sqlite3_context*,const void*,sqlite3_uint64, |
| | | void(*)(void*)); |
| | | void (*result_text64)(sqlite3_context*,const char*,sqlite3_uint64, |
| | | void(*)(void*), unsigned char); |
| | | int (*strglob)(const char*,const char*); |
| | | /* Version 3.8.11 and later */ |
| | | sqlite3_value *(*value_dup)(const sqlite3_value*); |
| | | void (*value_free)(sqlite3_value*); |
| | | int (*result_zeroblob64)(sqlite3_context*,sqlite3_uint64); |
| | | int (*bind_zeroblob64)(sqlite3_stmt*, int, sqlite3_uint64); |
| | | /* Version 3.9.0 and later */ |
| | | unsigned int (*value_subtype)(sqlite3_value*); |
| | | void (*result_subtype)(sqlite3_context*,unsigned int); |
| | | /* Version 3.10.0 and later */ |
| | | int (*status64)(int,sqlite3_int64*,sqlite3_int64*,int); |
| | | int (*strlike)(const char*,const char*,unsigned int); |
| | | int (*db_cacheflush)(sqlite3*); |
| | | /* Version 3.12.0 and later */ |
| | | int (*system_errno)(sqlite3*); |
| | | /* Version 3.14.0 and later */ |
| | | int (*trace_v2)(sqlite3*,unsigned,int(*)(unsigned,void*,void*,void*),void*); |
| | | char *(*expanded_sql)(sqlite3_stmt*); |
| | | /* Version 3.18.0 and later */ |
| | | void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64); |
| | | /* Version 3.20.0 and later */ |
| | | int (*prepare_v3)(sqlite3*,const char*,int,unsigned int, |
| | | sqlite3_stmt**,const char**); |
| | | int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int, |
| | | sqlite3_stmt**,const void**); |
| | | int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*)); |
| | | void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*)); |
| | | void *(*value_pointer)(sqlite3_value*,const char*); |
| | | int (*vtab_nochange)(sqlite3_context*); |
| | | int (*value_nochange)(sqlite3_value*); |
| | | const char *(*vtab_collation)(sqlite3_index_info*,int); |
| | | /* Version 3.24.0 and later */ |
| | | int (*keyword_count)(void); |
| | | int (*keyword_name)(int,const char**,int*); |
| | | int (*keyword_check)(const char*,int); |
| | | sqlite3_str *(*str_new)(sqlite3*); |
| | | char *(*str_finish)(sqlite3_str*); |
| | | void (*str_appendf)(sqlite3_str*, const char *zFormat, ...); |
| | | void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list); |
| | | void (*str_append)(sqlite3_str*, const char *zIn, int N); |
| | | void (*str_appendall)(sqlite3_str*, const char *zIn); |
| | | void (*str_appendchar)(sqlite3_str*, int N, char C); |
| | | void (*str_reset)(sqlite3_str*); |
| | | int (*str_errcode)(sqlite3_str*); |
| | | int (*str_length)(sqlite3_str*); |
| | | char *(*str_value)(sqlite3_str*); |
| | | /* Version 3.25.0 and later */ |
| | | int (*create_window_function)(sqlite3*,const char*,int,int,void*, |
| | | void (*xStep)(sqlite3_context*,int,sqlite3_value**), |
| | | void (*xFinal)(sqlite3_context*), |
| | | void (*xValue)(sqlite3_context*), |
| | | void (*xInv)(sqlite3_context*,int,sqlite3_value**), |
| | | void(*xDestroy)(void*)); |
| | | /* Version 3.26.0 and later */ |
| | | const char *(*normalized_sql)(sqlite3_stmt*); |
| | | /* Version 3.28.0 and later */ |
| | | int (*stmt_isexplain)(sqlite3_stmt*); |
| | | int (*value_frombind)(sqlite3_value*); |
| | | /* Version 3.30.0 and later */ |
| | | int (*drop_modules)(sqlite3*,const char**); |
| | | /* Version 3.31.0 and later */ |
| | | sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64); |
| | | const char *(*uri_key)(const char*,int); |
| | | const char *(*filename_database)(const char*); |
| | | const char *(*filename_journal)(const char*); |
| | | const char *(*filename_wal)(const char*); |
| | | /* Version 3.32.0 and later */ |
| | | const char *(*create_filename)(const char*,const char*,const char*, |
| | | int,const char**); |
| | | void (*free_filename)(const char*); |
| | | sqlite3_file *(*database_file_object)(const char*); |
| | | /* Version 3.34.0 and later */ |
| | | int (*txn_state)(sqlite3*,const char*); |
| | | /* Version 3.36.1 and later */ |
| | | sqlite3_int64 (*changes64)(sqlite3*); |
| | | sqlite3_int64 (*total_changes64)(sqlite3*); |
| | | /* Version 3.37.0 and later */ |
| | | int (*autovacuum_pages)(sqlite3*, |
| | | unsigned int(*)(void*,const char*,unsigned int,unsigned int,unsigned int), |
| | | void*, void(*)(void*)); |
| | | /* Version 3.38.0 and later */ |
| | | int (*error_offset)(sqlite3*); |
| | | int (*vtab_rhs_value)(sqlite3_index_info*,int,sqlite3_value**); |
| | | int (*vtab_distinct)(sqlite3_index_info*); |
| | | int (*vtab_in)(sqlite3_index_info*,int,int); |
| | | int (*vtab_in_first)(sqlite3_value*,sqlite3_value**); |
| | | int (*vtab_in_next)(sqlite3_value*,sqlite3_value**); |
| | | /* Version 3.39.0 and later */ |
| | | int (*deserialize)(sqlite3*,const char*,unsigned char*, |
| | | sqlite3_int64,sqlite3_int64,unsigned); |
| | | unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*, |
| | | unsigned int); |
| | | const char *(*db_name)(sqlite3*,int); |
| | | /* Version 3.40.0 and later */ |
| | | int (*value_encoding)(sqlite3_value*); |
| | | /* Version 3.41.0 and later */ |
| | | int (*is_interrupted)(sqlite3*); |
| | | /* Version 3.43.0 and later */ |
| | | int (*stmt_explain)(sqlite3_stmt*,int); |
| | | /* Version 3.44.0 and later */ |
| | | void *(*get_clientdata)(sqlite3*,const char*); |
| | | int (*set_clientdata)(sqlite3*, const char*, void*, void(*)(void*)); |
| | | }; |
| | | |
| | | /* |
| | | ** This is the function signature used for all extension entry points. It |
| | | ** is also defined in the file "loadext.c". |
| | | */ |
| | | typedef int (*sqlite3_loadext_entry)( |
| | | sqlite3 *db, /* Handle to the database. */ |
| | | char **pzErrMsg, /* Used to set error string on failure. */ |
| | | const sqlite3_api_routines *pThunk /* Extension API function pointers. */ |
| | | ); |
| | | |
| | | /* |
| | | ** The following macros redefine the API routines so that they are |
| | | ** redirected through the global sqlite3_api structure. |
| | | ** |
| | | ** This header file is also used by the loadext.c source file |
| | | ** (part of the main SQLite library - not an extension) so that |
| | | ** it can get access to the sqlite3_api_routines structure |
| | | ** definition. But the main library does not want to redefine |
| | | ** the API. So the redefinition macros are only valid if the |
| | | ** SQLITE_CORE macros is undefined. |
| | | */ |
| | | #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) |
| | | #define sqlite3_aggregate_context sqlite3_api->aggregate_context |
| | | #ifndef SQLITE_OMIT_DEPRECATED |
| | | #define sqlite3_aggregate_count sqlite3_api->aggregate_count |
| | | #endif |
| | | #define sqlite3_bind_blob sqlite3_api->bind_blob |
| | | #define sqlite3_bind_double sqlite3_api->bind_double |
| | | #define sqlite3_bind_int sqlite3_api->bind_int |
| | | #define sqlite3_bind_int64 sqlite3_api->bind_int64 |
| | | #define sqlite3_bind_null sqlite3_api->bind_null |
| | | #define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count |
| | | #define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index |
| | | #define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name |
| | | #define sqlite3_bind_text sqlite3_api->bind_text |
| | | #define sqlite3_bind_text16 sqlite3_api->bind_text16 |
| | | #define sqlite3_bind_value sqlite3_api->bind_value |
| | | #define sqlite3_busy_handler sqlite3_api->busy_handler |
| | | #define sqlite3_busy_timeout sqlite3_api->busy_timeout |
| | | #define sqlite3_changes sqlite3_api->changes |
| | | #define sqlite3_close sqlite3_api->close |
| | | #define sqlite3_collation_needed sqlite3_api->collation_needed |
| | | #define sqlite3_collation_needed16 sqlite3_api->collation_needed16 |
| | | #define sqlite3_column_blob sqlite3_api->column_blob |
| | | #define sqlite3_column_bytes sqlite3_api->column_bytes |
| | | #define sqlite3_column_bytes16 sqlite3_api->column_bytes16 |
| | | #define sqlite3_column_count sqlite3_api->column_count |
| | | #define sqlite3_column_database_name sqlite3_api->column_database_name |
| | | #define sqlite3_column_database_name16 sqlite3_api->column_database_name16 |
| | | #define sqlite3_column_decltype sqlite3_api->column_decltype |
| | | #define sqlite3_column_decltype16 sqlite3_api->column_decltype16 |
| | | #define sqlite3_column_double sqlite3_api->column_double |
| | | #define sqlite3_column_int sqlite3_api->column_int |
| | | #define sqlite3_column_int64 sqlite3_api->column_int64 |
| | | #define sqlite3_column_name sqlite3_api->column_name |
| | | #define sqlite3_column_name16 sqlite3_api->column_name16 |
| | | #define sqlite3_column_origin_name sqlite3_api->column_origin_name |
| | | #define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16 |
| | | #define sqlite3_column_table_name sqlite3_api->column_table_name |
| | | #define sqlite3_column_table_name16 sqlite3_api->column_table_name16 |
| | | #define sqlite3_column_text sqlite3_api->column_text |
| | | #define sqlite3_column_text16 sqlite3_api->column_text16 |
| | | #define sqlite3_column_type sqlite3_api->column_type |
| | | #define sqlite3_column_value sqlite3_api->column_value |
| | | #define sqlite3_commit_hook sqlite3_api->commit_hook |
| | | #define sqlite3_complete sqlite3_api->complete |
| | | #define sqlite3_complete16 sqlite3_api->complete16 |
| | | #define sqlite3_create_collation sqlite3_api->create_collation |
| | | #define sqlite3_create_collation16 sqlite3_api->create_collation16 |
| | | #define sqlite3_create_function sqlite3_api->create_function |
| | | #define sqlite3_create_function16 sqlite3_api->create_function16 |
| | | #define sqlite3_create_module sqlite3_api->create_module |
| | | #define sqlite3_create_module_v2 sqlite3_api->create_module_v2 |
| | | #define sqlite3_data_count sqlite3_api->data_count |
| | | #define sqlite3_db_handle sqlite3_api->db_handle |
| | | #define sqlite3_declare_vtab sqlite3_api->declare_vtab |
| | | #define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache |
| | | #define sqlite3_errcode sqlite3_api->errcode |
| | | #define sqlite3_errmsg sqlite3_api->errmsg |
| | | #define sqlite3_errmsg16 sqlite3_api->errmsg16 |
| | | #define sqlite3_exec sqlite3_api->exec |
| | | #ifndef SQLITE_OMIT_DEPRECATED |
| | | #define sqlite3_expired sqlite3_api->expired |
| | | #endif |
| | | #define sqlite3_finalize sqlite3_api->finalize |
| | | #define sqlite3_free sqlite3_api->free |
| | | #define sqlite3_free_table sqlite3_api->free_table |
| | | #define sqlite3_get_autocommit sqlite3_api->get_autocommit |
| | | #define sqlite3_get_auxdata sqlite3_api->get_auxdata |
| | | #define sqlite3_get_table sqlite3_api->get_table |
| | | #ifndef SQLITE_OMIT_DEPRECATED |
| | | #define sqlite3_global_recover sqlite3_api->global_recover |
| | | #endif |
| | | #define sqlite3_interrupt sqlite3_api->interruptx |
| | | #define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid |
| | | #define sqlite3_libversion sqlite3_api->libversion |
| | | #define sqlite3_libversion_number sqlite3_api->libversion_number |
| | | #define sqlite3_malloc sqlite3_api->malloc |
| | | #define sqlite3_mprintf sqlite3_api->mprintf |
| | | #define sqlite3_open sqlite3_api->open |
| | | #define sqlite3_open16 sqlite3_api->open16 |
| | | #define sqlite3_prepare sqlite3_api->prepare |
| | | #define sqlite3_prepare16 sqlite3_api->prepare16 |
| | | #define sqlite3_prepare_v2 sqlite3_api->prepare_v2 |
| | | #define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 |
| | | #define sqlite3_profile sqlite3_api->profile |
| | | #define sqlite3_progress_handler sqlite3_api->progress_handler |
| | | #define sqlite3_realloc sqlite3_api->realloc |
| | | #define sqlite3_reset sqlite3_api->reset |
| | | #define sqlite3_result_blob sqlite3_api->result_blob |
| | | #define sqlite3_result_double sqlite3_api->result_double |
| | | #define sqlite3_result_error sqlite3_api->result_error |
| | | #define sqlite3_result_error16 sqlite3_api->result_error16 |
| | | #define sqlite3_result_int sqlite3_api->result_int |
| | | #define sqlite3_result_int64 sqlite3_api->result_int64 |
| | | #define sqlite3_result_null sqlite3_api->result_null |
| | | #define sqlite3_result_text sqlite3_api->result_text |
| | | #define sqlite3_result_text16 sqlite3_api->result_text16 |
| | | #define sqlite3_result_text16be sqlite3_api->result_text16be |
| | | #define sqlite3_result_text16le sqlite3_api->result_text16le |
| | | #define sqlite3_result_value sqlite3_api->result_value |
| | | #define sqlite3_rollback_hook sqlite3_api->rollback_hook |
| | | #define sqlite3_set_authorizer sqlite3_api->set_authorizer |
| | | #define sqlite3_set_auxdata sqlite3_api->set_auxdata |
| | | #define sqlite3_snprintf sqlite3_api->xsnprintf |
| | | #define sqlite3_step sqlite3_api->step |
| | | #define sqlite3_table_column_metadata sqlite3_api->table_column_metadata |
| | | #define sqlite3_thread_cleanup sqlite3_api->thread_cleanup |
| | | #define sqlite3_total_changes sqlite3_api->total_changes |
| | | #define sqlite3_trace sqlite3_api->trace |
| | | #ifndef SQLITE_OMIT_DEPRECATED |
| | | #define sqlite3_transfer_bindings sqlite3_api->transfer_bindings |
| | | #endif |
| | | #define sqlite3_update_hook sqlite3_api->update_hook |
| | | #define sqlite3_user_data sqlite3_api->user_data |
| | | #define sqlite3_value_blob sqlite3_api->value_blob |
| | | #define sqlite3_value_bytes sqlite3_api->value_bytes |
| | | #define sqlite3_value_bytes16 sqlite3_api->value_bytes16 |
| | | #define sqlite3_value_double sqlite3_api->value_double |
| | | #define sqlite3_value_int sqlite3_api->value_int |
| | | #define sqlite3_value_int64 sqlite3_api->value_int64 |
| | | #define sqlite3_value_numeric_type sqlite3_api->value_numeric_type |
| | | #define sqlite3_value_text sqlite3_api->value_text |
| | | #define sqlite3_value_text16 sqlite3_api->value_text16 |
| | | #define sqlite3_value_text16be sqlite3_api->value_text16be |
| | | #define sqlite3_value_text16le sqlite3_api->value_text16le |
| | | #define sqlite3_value_type sqlite3_api->value_type |
| | | #define sqlite3_vmprintf sqlite3_api->vmprintf |
| | | #define sqlite3_vsnprintf sqlite3_api->xvsnprintf |
| | | #define sqlite3_overload_function sqlite3_api->overload_function |
| | | #define sqlite3_prepare_v2 sqlite3_api->prepare_v2 |
| | | #define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2 |
| | | #define sqlite3_clear_bindings sqlite3_api->clear_bindings |
| | | #define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob |
| | | #define sqlite3_blob_bytes sqlite3_api->blob_bytes |
| | | #define sqlite3_blob_close sqlite3_api->blob_close |
| | | #define sqlite3_blob_open sqlite3_api->blob_open |
| | | #define sqlite3_blob_read sqlite3_api->blob_read |
| | | #define sqlite3_blob_write sqlite3_api->blob_write |
| | | #define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2 |
| | | #define sqlite3_file_control sqlite3_api->file_control |
| | | #define sqlite3_memory_highwater sqlite3_api->memory_highwater |
| | | #define sqlite3_memory_used sqlite3_api->memory_used |
| | | #define sqlite3_mutex_alloc sqlite3_api->mutex_alloc |
| | | #define sqlite3_mutex_enter sqlite3_api->mutex_enter |
| | | #define sqlite3_mutex_free sqlite3_api->mutex_free |
| | | #define sqlite3_mutex_leave sqlite3_api->mutex_leave |
| | | #define sqlite3_mutex_try sqlite3_api->mutex_try |
| | | #define sqlite3_open_v2 sqlite3_api->open_v2 |
| | | #define sqlite3_release_memory sqlite3_api->release_memory |
| | | #define sqlite3_result_error_nomem sqlite3_api->result_error_nomem |
| | | #define sqlite3_result_error_toobig sqlite3_api->result_error_toobig |
| | | #define sqlite3_sleep sqlite3_api->sleep |
| | | #define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit |
| | | #define sqlite3_vfs_find sqlite3_api->vfs_find |
| | | #define sqlite3_vfs_register sqlite3_api->vfs_register |
| | | #define sqlite3_vfs_unregister sqlite3_api->vfs_unregister |
| | | #define sqlite3_threadsafe sqlite3_api->xthreadsafe |
| | | #define sqlite3_result_zeroblob sqlite3_api->result_zeroblob |
| | | #define sqlite3_result_error_code sqlite3_api->result_error_code |
| | | #define sqlite3_test_control sqlite3_api->test_control |
| | | #define sqlite3_randomness sqlite3_api->randomness |
| | | #define sqlite3_context_db_handle sqlite3_api->context_db_handle |
| | | #define sqlite3_extended_result_codes sqlite3_api->extended_result_codes |
| | | #define sqlite3_limit sqlite3_api->limit |
| | | #define sqlite3_next_stmt sqlite3_api->next_stmt |
| | | #define sqlite3_sql sqlite3_api->sql |
| | | #define sqlite3_status sqlite3_api->status |
| | | #define sqlite3_backup_finish sqlite3_api->backup_finish |
| | | #define sqlite3_backup_init sqlite3_api->backup_init |
| | | #define sqlite3_backup_pagecount sqlite3_api->backup_pagecount |
| | | #define sqlite3_backup_remaining sqlite3_api->backup_remaining |
| | | #define sqlite3_backup_step sqlite3_api->backup_step |
| | | #define sqlite3_compileoption_get sqlite3_api->compileoption_get |
| | | #define sqlite3_compileoption_used sqlite3_api->compileoption_used |
| | | #define sqlite3_create_function_v2 sqlite3_api->create_function_v2 |
| | | #define sqlite3_db_config sqlite3_api->db_config |
| | | #define sqlite3_db_mutex sqlite3_api->db_mutex |
| | | #define sqlite3_db_status sqlite3_api->db_status |
| | | #define sqlite3_extended_errcode sqlite3_api->extended_errcode |
| | | #define sqlite3_log sqlite3_api->log |
| | | #define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64 |
| | | #define sqlite3_sourceid sqlite3_api->sourceid |
| | | #define sqlite3_stmt_status sqlite3_api->stmt_status |
| | | #define sqlite3_strnicmp sqlite3_api->strnicmp |
| | | #define sqlite3_unlock_notify sqlite3_api->unlock_notify |
| | | #define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint |
| | | #define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint |
| | | #define sqlite3_wal_hook sqlite3_api->wal_hook |
| | | #define sqlite3_blob_reopen sqlite3_api->blob_reopen |
| | | #define sqlite3_vtab_config sqlite3_api->vtab_config |
| | | #define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict |
| | | /* Version 3.7.16 and later */ |
| | | #define sqlite3_close_v2 sqlite3_api->close_v2 |
| | | #define sqlite3_db_filename sqlite3_api->db_filename |
| | | #define sqlite3_db_readonly sqlite3_api->db_readonly |
| | | #define sqlite3_db_release_memory sqlite3_api->db_release_memory |
| | | #define sqlite3_errstr sqlite3_api->errstr |
| | | #define sqlite3_stmt_busy sqlite3_api->stmt_busy |
| | | #define sqlite3_stmt_readonly sqlite3_api->stmt_readonly |
| | | #define sqlite3_stricmp sqlite3_api->stricmp |
| | | #define sqlite3_uri_boolean sqlite3_api->uri_boolean |
| | | #define sqlite3_uri_int64 sqlite3_api->uri_int64 |
| | | #define sqlite3_uri_parameter sqlite3_api->uri_parameter |
| | | #define sqlite3_uri_vsnprintf sqlite3_api->xvsnprintf |
| | | #define sqlite3_wal_checkpoint_v2 sqlite3_api->wal_checkpoint_v2 |
| | | /* Version 3.8.7 and later */ |
| | | #define sqlite3_auto_extension sqlite3_api->auto_extension |
| | | #define sqlite3_bind_blob64 sqlite3_api->bind_blob64 |
| | | #define sqlite3_bind_text64 sqlite3_api->bind_text64 |
| | | #define sqlite3_cancel_auto_extension sqlite3_api->cancel_auto_extension |
| | | #define sqlite3_load_extension sqlite3_api->load_extension |
| | | #define sqlite3_malloc64 sqlite3_api->malloc64 |
| | | #define sqlite3_msize sqlite3_api->msize |
| | | #define sqlite3_realloc64 sqlite3_api->realloc64 |
| | | #define sqlite3_reset_auto_extension sqlite3_api->reset_auto_extension |
| | | #define sqlite3_result_blob64 sqlite3_api->result_blob64 |
| | | #define sqlite3_result_text64 sqlite3_api->result_text64 |
| | | #define sqlite3_strglob sqlite3_api->strglob |
| | | /* Version 3.8.11 and later */ |
| | | #define sqlite3_value_dup sqlite3_api->value_dup |
| | | #define sqlite3_value_free sqlite3_api->value_free |
| | | #define sqlite3_result_zeroblob64 sqlite3_api->result_zeroblob64 |
| | | #define sqlite3_bind_zeroblob64 sqlite3_api->bind_zeroblob64 |
| | | /* Version 3.9.0 and later */ |
| | | #define sqlite3_value_subtype sqlite3_api->value_subtype |
| | | #define sqlite3_result_subtype sqlite3_api->result_subtype |
| | | /* Version 3.10.0 and later */ |
| | | #define sqlite3_status64 sqlite3_api->status64 |
| | | #define sqlite3_strlike sqlite3_api->strlike |
| | | #define sqlite3_db_cacheflush sqlite3_api->db_cacheflush |
| | | /* Version 3.12.0 and later */ |
| | | #define sqlite3_system_errno sqlite3_api->system_errno |
| | | /* Version 3.14.0 and later */ |
| | | #define sqlite3_trace_v2 sqlite3_api->trace_v2 |
| | | #define sqlite3_expanded_sql sqlite3_api->expanded_sql |
| | | /* Version 3.18.0 and later */ |
| | | #define sqlite3_set_last_insert_rowid sqlite3_api->set_last_insert_rowid |
| | | /* Version 3.20.0 and later */ |
| | | #define sqlite3_prepare_v3 sqlite3_api->prepare_v3 |
| | | #define sqlite3_prepare16_v3 sqlite3_api->prepare16_v3 |
| | | #define sqlite3_bind_pointer sqlite3_api->bind_pointer |
| | | #define sqlite3_result_pointer sqlite3_api->result_pointer |
| | | #define sqlite3_value_pointer sqlite3_api->value_pointer |
| | | /* Version 3.22.0 and later */ |
| | | #define sqlite3_vtab_nochange sqlite3_api->vtab_nochange |
| | | #define sqlite3_value_nochange sqlite3_api->value_nochange |
| | | #define sqlite3_vtab_collation sqlite3_api->vtab_collation |
| | | /* Version 3.24.0 and later */ |
| | | #define sqlite3_keyword_count sqlite3_api->keyword_count |
| | | #define sqlite3_keyword_name sqlite3_api->keyword_name |
| | | #define sqlite3_keyword_check sqlite3_api->keyword_check |
| | | #define sqlite3_str_new sqlite3_api->str_new |
| | | #define sqlite3_str_finish sqlite3_api->str_finish |
| | | #define sqlite3_str_appendf sqlite3_api->str_appendf |
| | | #define sqlite3_str_vappendf sqlite3_api->str_vappendf |
| | | #define sqlite3_str_append sqlite3_api->str_append |
| | | #define sqlite3_str_appendall sqlite3_api->str_appendall |
| | | #define sqlite3_str_appendchar sqlite3_api->str_appendchar |
| | | #define sqlite3_str_reset sqlite3_api->str_reset |
| | | #define sqlite3_str_errcode sqlite3_api->str_errcode |
| | | #define sqlite3_str_length sqlite3_api->str_length |
| | | #define sqlite3_str_value sqlite3_api->str_value |
| | | /* Version 3.25.0 and later */ |
| | | #define sqlite3_create_window_function sqlite3_api->create_window_function |
| | | /* Version 3.26.0 and later */ |
| | | #define sqlite3_normalized_sql sqlite3_api->normalized_sql |
| | | /* Version 3.28.0 and later */ |
| | | #define sqlite3_stmt_isexplain sqlite3_api->stmt_isexplain |
| | | #define sqlite3_value_frombind sqlite3_api->value_frombind |
| | | /* Version 3.30.0 and later */ |
| | | #define sqlite3_drop_modules sqlite3_api->drop_modules |
| | | /* Version 3.31.0 and later */ |
| | | #define sqlite3_hard_heap_limit64 sqlite3_api->hard_heap_limit64 |
| | | #define sqlite3_uri_key sqlite3_api->uri_key |
| | | #define sqlite3_filename_database sqlite3_api->filename_database |
| | | #define sqlite3_filename_journal sqlite3_api->filename_journal |
| | | #define sqlite3_filename_wal sqlite3_api->filename_wal |
| | | /* Version 3.32.0 and later */ |
| | | #define sqlite3_create_filename sqlite3_api->create_filename |
| | | #define sqlite3_free_filename sqlite3_api->free_filename |
| | | #define sqlite3_database_file_object sqlite3_api->database_file_object |
| | | /* Version 3.34.0 and later */ |
| | | #define sqlite3_txn_state sqlite3_api->txn_state |
| | | /* Version 3.36.1 and later */ |
| | | #define sqlite3_changes64 sqlite3_api->changes64 |
| | | #define sqlite3_total_changes64 sqlite3_api->total_changes64 |
| | | /* Version 3.37.0 and later */ |
| | | #define sqlite3_autovacuum_pages sqlite3_api->autovacuum_pages |
| | | /* Version 3.38.0 and later */ |
| | | #define sqlite3_error_offset sqlite3_api->error_offset |
| | | #define sqlite3_vtab_rhs_value sqlite3_api->vtab_rhs_value |
| | | #define sqlite3_vtab_distinct sqlite3_api->vtab_distinct |
| | | #define sqlite3_vtab_in sqlite3_api->vtab_in |
| | | #define sqlite3_vtab_in_first sqlite3_api->vtab_in_first |
| | | #define sqlite3_vtab_in_next sqlite3_api->vtab_in_next |
| | | /* Version 3.39.0 and later */ |
| | | #ifndef SQLITE_OMIT_DESERIALIZE |
| | | #define sqlite3_deserialize sqlite3_api->deserialize |
| | | #define sqlite3_serialize sqlite3_api->serialize |
| | | #endif |
| | | #define sqlite3_db_name sqlite3_api->db_name |
| | | /* Version 3.40.0 and later */ |
| | | #define sqlite3_value_encoding sqlite3_api->value_encoding |
| | | /* Version 3.41.0 and later */ |
| | | #define sqlite3_is_interrupted sqlite3_api->is_interrupted |
| | | /* Version 3.43.0 and later */ |
| | | #define sqlite3_stmt_explain sqlite3_api->stmt_explain |
| | | /* Version 3.44.0 and later */ |
| | | #define sqlite3_get_clientdata sqlite3_api->get_clientdata |
| | | #define sqlite3_set_clientdata sqlite3_api->set_clientdata |
| | | #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ |
| | | |
| | | #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) |
| | | /* This case when the file really is being compiled as a loadable |
| | | ** extension */ |
| | | # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; |
| | | # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; |
| | | # define SQLITE_EXTENSION_INIT3 \ |
| | | extern const sqlite3_api_routines *sqlite3_api; |
| | | #else |
| | | /* This case when the file is being statically linked into the |
| | | ** application */ |
| | | # define SQLITE_EXTENSION_INIT1 /*no-op*/ |
| | | # define SQLITE_EXTENSION_INIT2(v) (void)v; /* unused parameter */ |
| | | # define SQLITE_EXTENSION_INIT3 /*no-op*/ |
| | | #endif |
| | | |
| | | #endif /* SQLITE3EXT_H */ |