| ¶Ô±ÈÐÂÎļþ |
| | |
| | | // PerformanceMelsec.cpp: implementation of the CPerformanceMelsec class. |
| | | // |
| | | ////////////////////////////////////////////////////////////////////// |
| | | #include "pch.h" |
| | | #include "PerformanceMelsec.h" |
| | | #include <windows.h> |
| | | #include <iostream> |
| | | #include <fstream> |
| | | |
| | | #ifdef _DEBUG |
| | | #undef THIS_FILE |
| | | static char* THIS_FILE = __FILE__; |
| | | #define new DEBUG_NEW |
| | | #endif |
| | | |
| | | #ifdef _DEBUG |
| | | #define LOG_ERROR(msg) \ |
| | | std::cerr << "[ERROR] " << __FILE__ << ":" << __LINE__ << " (" << __FUNCTION__ << ") - " << msg << std::endl; |
| | | #define LOG_DEBUG(msg) \ |
| | | std::cout << "[DEBUG] " << __FILE__ << ":" << __LINE__ << " (" << __FUNCTION__ << ") - " << msg << std::endl; |
| | | #else |
| | | #define LOG_ERROR(msg) |
| | | #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."}, |
| | | |
| | | // èªå®ä¹é误ç |
| | | {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); |
| | | } |
| | | |
| | | // ææå½æ° |
| | | CPerformanceMelsec::~CPerformanceMelsec() { |
| | | Disconnect(); |
| | | } |
| | | |
| | | // è·åæè¿çéè¯¯ä¿¡æ¯ |
| | | std::string CPerformanceMelsec::GetLastError() const { |
| | | 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; |
| | | } |
| | | |
| | | // éåéææååé 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; |
| | | } |
| | | |
| | | // å è½½éè¯¯ä¿¡æ¯ |
| | | 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; |
| | | } |
| | | |
| | | 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)) { |
| | | strMessage = strToken; |
| | | } |
| | | |
| | | if (!strMessage.empty()) { |
| | | m_mapError[nCode] = strMessage; |
| | | } |
| | | } |
| | | |
| | | return true; |
| | | } |
| | | |
| | | // è¿æ¥å°PLC |
| | | int CPerformanceMelsec::Connect(const short nChannel, const short nMode) { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | |
| | | 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; |
| | | } |
| | | |
| | | // è¿æ¥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; |
| | | } |
| | | |
| | | // æå¼è¿æ¥ |
| | | int CPerformanceMelsec::Disconnect() { |
| | | 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; |
| | | } |
| | | |
| | | UpdateLastError(nRet); |
| | | LOG_DEBUG("Close connect."); |
| | | |
| | | return nRet; |
| | | } |
| | | |
| | | // å¯ç¼ç¨æ§å¶å¨è½¯å
ä»¶ä¿¡æ¯è¡¨çåå§å |
| | | int CPerformanceMelsec::InitializeController() { |
| | | 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 = mdInit(m_nPath); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | | |
| | | // è·åçæ¬ä¿¡æ¯ |
| | | int CPerformanceMelsec::GetBoardVersion(BoardVersion& version) { |
| | | 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; |
| | | } |
| | | |
| | | // å¡«å
çæ¬ä¿¡æ¯å°ç»æä½ |
| | | 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.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); |
| | | |
| | | 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); |
| | | |
| | | 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.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); |
| | | |
| | | return nRet; |
| | | } |
| | | |
| | | // 读åç®æ ç«ç¹CPUç±»å |
| | | int CPerformanceMelsec::ReadCPUCode(const StationIdentifier& station, short& nCPUCode) { |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | 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); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | | |
| | | // æ¿æ¨¡å¼è®¾ç½® |
| | | int CPerformanceMelsec::SetBoardMode(const short nMode) { |
| | | // æ£æ¥æ¯å¦å·²ç»è¿æ¥ |
| | | 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); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | | |
| | | // è·åæ¿æ¨¡å¼ |
| | | int CPerformanceMelsec::GetBoardMode(short& nMode) { |
| | | // æ£æ¥æ¯å¦å·²ç»è¿æ¥ |
| | | 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); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_DEBUG("Raw Mode: " << nMode); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | const short nRet = mdBdRst(m_nPath); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | | |
| | | // æ¿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; |
| | | } |
| | | |
| | | // æ¸
空 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); |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | // éç¨è¯»æ°æ® |
| | | 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; |
| | | } |
| | | |
| | | // åå§å读åç¼å²åº |
| | | 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); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | vecData.clear(); // å¦æè¯»åå¤±è´¥ï¼æ¸
空ç¼å²åº |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | 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); // 计ç®éè¦è¯»åçåæ°éï¼åä¸åæ´ï¼ |
| | | |
| | | std::vector<short> vecTempBuffer(nSize, 0); |
| | | nRet = ReadData(station, nDevType, nDevNo, nSize, vecTempBuffer); |
| | | |
| | | 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; // 妿已ç»è¯»å宿éç使°ï¼æåéåº |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | 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()); |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | 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); |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | // æ°æ®æææ§ |
| | | 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); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | 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); // 计ç®éè¦åå
¥çåæ°éï¼åä¸åæ´ï¼ |
| | | |
| | | // åå¤ä¸´æ¶ç¼å²åºæ¥åå¨è½¬æ¢åç 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()); |
| | | } |
| | | |
| | | // ååæ°æ® |
| | | 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; |
| | | } |
| | | |
| | | // 计ç®éè¦åå
¥çåèæ°ï¼æ¯ä¸ªåå 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); |
| | | } |
| | | |
| | | // åååæ°æ® |
| | | 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; |
| | | } |
| | | |
| | | // 计ç®éè¦åå
¥çåèæ°ï¼æ¯ä¸ªååå 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()); |
| | | } |
| | | |
| | | // æ©å±è¯»æ°æ® |
| | | 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; |
| | | } |
| | | |
| | | 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); |
| | | |
| | | { |
| | | 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); |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | if (nDevNo % 8 != 0) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const long nWordCount = (nBitCount + 15) / 16; |
| | | const long nByteSize = nWordCount * sizeof(short); |
| | | |
| | | 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 word = static_cast<unsigned char>(vecRaw[i * 2]) | |
| | | (static_cast<unsigned char>(vecRaw[i * 2 + 1]) << 8); |
| | | for (int j = 0; j < 16; ++j) { |
| | | vecData.push_back((word & (1 << j)) != 0); |
| | | if (vecData.size() >= static_cast<size_t>(nBitCount)) { |
| | | 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; |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | // æ©å±è¯»åååæ°æ® |
| | | 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; |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | // æ©å±åæ°æ® |
| | | 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; |
| | | } |
| | | |
| | | // å° 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()); |
| | | } |
| | | |
| | | // é误å¤ç忥å¿è®°å½ |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | if (nDevNo % 8 != 0) { |
| | | UpdateLastError(ERROR_CODE_INVALID_PARAM); |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const size_t nWordCount = (vecData.size() + 15) / 16; |
| | | |
| | | std::vector<short> vecWordBuffer(nWordCount, 0); |
| | | for (size_t i = 0; i < vecData.size(); ++i) { |
| | | if (vecData[i]) { |
| | | vecWordBuffer[i / 16] |= (1 << (i % 16)); |
| | | } |
| | | } |
| | | |
| | | // è½¬æ¢ short -> char |
| | | std::vector<char> vecByteBuffer; |
| | | vecByteBuffer.resize(nWordCount * sizeof(short)); |
| | | 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, nDevNo, 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; |
| | | } |
| | | |
| | | 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); |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | 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); |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | // åå¤ 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 个åè |
| | | } |
| | | |
| | | // éä¿æ¤åè°ç¨ 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; |
| | | } |
| | | |
| | | // å°è¯»åå°ç 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; |
| | | } |
| | | |
| | | // æ©å±è½¯å
ä»¶éæºåå
¥ï¼æ¯æå¤ä¸ªè½¯å
ä»¶ï¼ |
| | | 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; |
| | | } |
| | | |
| | | // åå¤ 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())); |
| | | } |
| | | |
| | | // é误å¤ç忥å¿è®°å½ |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | 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()); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); // æ´æ°é误ç |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | else { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertShortToChar(vecBuffer, vecData); |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | // å° 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()); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | | |
| | | // è¿ç¨ç«çç¼å²åå¨å¨è¯»å 对象ç«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; |
| | | } |
| | | |
| | | // å°ç¼å²åºå¤§å°è°æ´ä¸º 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()); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | else { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertShortToChar(vecBuffer, vecData); |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | | |
| | | // è¿ç¨ç«çç¼å²åå¨å¨åå
¥ 对象ç«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; |
| | | } |
| | | |
| | | // è½¬æ¢ 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()); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | | |
| | | // 设置(ON)对象ç«çæå®ä½è½¯å
ä»¶ |
| | | int CPerformanceMelsec::SetBitDevice(const StationIdentifier& station, const DeviceType enDevType, const short nDevNo) { |
| | | // éªè¯ç«ç¹åæ° |
| | | 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); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | | |
| | | // å¤ä½(OFF)对象ç«çæå®ä½è½¯å
ä»¶ |
| | | int CPerformanceMelsec::ResetBitDevice(const StationIdentifier& station, const DeviceType enDevType, const short enDevNo) { |
| | | // éªè¯ç«ç¹åæ° |
| | | 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); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | | |
| | | // æ©å±ä½è½¯å
件设置 |
| | | long CPerformanceMelsec::SetBitDeviceEx(const StationIdentifier& station, long nDevType, long nDevNo) { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | |
| | | // æ£æ¥åæ°æææ§ |
| | | long nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | nRet = mdDevSetEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | | |
| | | // æ©å±ä½è½¯å
ä»¶å¤ä½ |
| | | long CPerformanceMelsec::ResetBitDeviceEx(const StationIdentifier& station, long nDevType, long nDevNo) { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | |
| | | // æ£æ¥åæ°æææ§ |
| | | long nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | return nRet; |
| | | } |
| | | |
| | | nRet = mdDevRstEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo); |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | | |
| | | // æ§è¡å¯¹è±¡ç«çCPU |
| | | int CPerformanceMelsec::ControlCPU(const StationIdentifier& station, ControlCode enControlCode) { |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | 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; |
| | | } |
| | | |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | nRet = mdControl(m_nPath, CombineStation(station), nControlCode); |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | UpdateLastError(nRet); |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | | |
| | | // äºä»¶çå¾
|
| | | int CPerformanceMelsec::WaitForBoardEvent(std::vector<short> vecEventNumbers, const int nTimeoutMs, EventDetails& details) { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | |
| | | 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; |
| | | } |
| | | |
| | | // 第 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); |
| | | |
| | | 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; |
| | | } |
| | | |
| | | //============================================è¾
å©å½æ°======================================================= |
| | | // æ´æ°æè¿çéè¯¯ä¿¡æ¯ |
| | | void CPerformanceMelsec::UpdateLastError(const int nCode) { |
| | | 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."; |
| | | } |
| | | |
| | | 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 >= -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 <= 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 >= 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."; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // æ£æ¥è¿æ¥ç¶æåç«ç¹åæ°æææ§ |
| | | int CPerformanceMelsec::ValidateStation(const StationIdentifier& station) const { |
| | | // æ£æ¥æ¯å¦å·²è¿æ¥ |
| | | 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; |
| | | } |
| | | |
| | | return 0; // åæ°ææ |
| | | } |
| | | |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int CPerformanceMelsec::ValidateStationAndSize(const StationIdentifier& station, const short nCount) const { |
| | | // éªè¯ç«ç¹åæ° |
| | | const int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | return nRet; // 妿ç«ç¹éªè¯å¤±è´¥ï¼è¿å对åºé误ç |
| | | } |
| | | |
| | | if (nCount <= 0) { |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | return 0; // éªè¯éè¿ |
| | | } |
| | | |
| | | // 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; |
| | | |
| | | 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; |
| | | } |
| | | |
| | | //============================================éæè¾
å©å½æ°==================================================== |
| | | // å»¶æ¶ï¼å¹¶ä¸è½¬åçªå£æ¶æ¯ |
| | | 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; |
| | | } |
| | | |
| | | 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; |
| | | } |
| | | |
| | | // åå¹¶ç½ç»å·åç«ç¹å· |
| | | short CPerformanceMelsec::CombineStation(const StationIdentifier& station) { |
| | | return static_cast<short>(station.nStNo | ((station.nNetNo << 8) & 0xFF00)); |
| | | } |
| | | |
| | | // 计ç®è½¯å
ä»¶ç±»å |
| | | short CPerformanceMelsec::CalculateDeviceType(const StationIdentifier& station, DeviceType 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; |
| | | } |
| | | |
| | | return static_cast<short>(nDevType); |
| | | } |
| | | |
| | | // 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; // é«åè |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 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); // é«åè |
| | | } |
| | | } |
| | | |
| | | // 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); // é«åè |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 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); // é«åè |
| | | } |
| | | } |
| | | |
| | | // 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ä½ |
| | | } |
| | | } |
| | | |
| | | // 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ä½ |
| | | } |
| | | } |
| | | |
| | | //============================================模æ¿è¾
å©å½æ°==================================================== |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | template <typename T> |
| | | int CPerformanceMelsec::ValidateStationAndData(const StationIdentifier& station, const std::vector<T>& vecData) { |
| | | // éªè¯ç«ç¹åæ° |
| | | const int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | return nRet; // 妿ç«ç¹éªè¯å¤±è´¥ï¼è¿å对åºé误ç |
| | | } |
| | | |
| | | // éªè¯æ°æ®æ¯å¦ä¸ºç©º |
| | | if (vecData.empty()) { |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | 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"); |
| | | |
| | | // èªå¨è®¡ç® nGroupSize |
| | | constexpr size_t nGroupSize = sizeof(U) / sizeof(T); |
| | | |
| | | // 妿 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"); |
| | | |
| | | // 计ç®å®æ´ç»çæ°é |
| | | 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))); |
| | | } |
| | | |
| | | 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"); |
| | | |
| | | // èªå¨è®¡ç® 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 çåæ°ï¼æ£å¸¸åè§£ |
| | | 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); |
| | | |
| | | // åè§£é«ä½æ°æ®å°ä½ä½æ°æ® |
| | | 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; |
| | | } |