| | |
| | | #define LOG_DEBUG(msg) |
| | | #endif |
| | | |
| | | // åå§åéææååé |
| | | // åå§åéææååé |
| | | std::unordered_map<int, std::string> CPerformanceMelsec::m_mapError = { |
| | | // æ¿åSDKé误ç |
| | | // æ¿å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."}, |
| | |
| | | {-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."}, |
| | |
| | | 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 å¹¶å°æ¯ä¸ªé误信æ¯åå
¥æä»¶ |
| | | // éåéææååé m_mapError å¹¶å°æ¯ä¸ªé误信æ¯åå
¥æä»¶ |
| | | for (const auto& entry : m_mapError) { |
| | | const int nCode = entry.first; |
| | | const std::string& strMessage = entry.second; |
| | |
| | | return true; |
| | | } |
| | | |
| | | // å è½½éè¯¯ä¿¡æ¯ |
| | | // å è½½éè¯¯ä¿¡æ¯ |
| | | bool CPerformanceMelsec::LoadErrorInfoFromFile(const std::string& filename) { |
| | | std::ifstream inFile(filename); |
| | | if (!inFile.is_open()) { |
| | |
| | | std::string strToken; |
| | | std::string strMessage; |
| | | |
| | | // 使ç¨åé符 "|" è§£ææ¯ä¸è¡ |
| | | // 使ç¨åé符 "|" è§£ææ¯ä¸è¡ |
| | | if (std::getline(iss, strToken, '|')) { |
| | | nCode = std::stoi(strToken); |
| | | } |
| | |
| | | return true; |
| | | } |
| | | |
| | | // è¿æ¥å°PLC |
| | | // è¿æ¥å°PLC |
| | | int CPerformanceMelsec::Connect(const short nChannel, const short nMode) { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | |
| | |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | // è¿æ¥PLCï¼æ¾å¼ç±»å转æ¢ä»¥å¹é
mdOpen çç¾å |
| | | // è¿æ¥PLCï¼æ¾å¼ç±»å转æ¢ä»¥å¹é
mdOpen çç¾å |
| | | const short nRet = mdOpen(nChannel, nMode, &m_nPath); |
| | | if (nRet == 0) { |
| | | m_bConnected.store(true); |
| | |
| | | return nRet; |
| | | } |
| | | |
| | | // æå¼è¿æ¥ |
| | | // æå¼è¿æ¥ |
| | | int CPerformanceMelsec::Disconnect() { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | |
| | |
| | | return nRet; |
| | | } |
| | | |
| | | // å¯ç¼ç¨æ§å¶å¨è½¯å
ä»¶ä¿¡æ¯è¡¨çåå§å |
| | | // å¯ç¼ç¨æ§å¶å¨è½¯å
ä»¶ä¿¡æ¯è¡¨çåå§å |
| | | int CPerformanceMelsec::InitializeController() { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | |
| | |
| | | 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) { |
| | |
| | | return nRet; |
| | | } |
| | | |
| | | // å¡«å
çæ¬ä¿¡æ¯å°ç»æä½ |
| | | // å¡«å
çæ¬ä¿¡æ¯å°ç»æä½ |
| | | version.fixedValue[0] = static_cast<char>(buf[0] & 0xFF); |
| | | version.fixedValue[1] = static_cast<char>((buf[0] >> 8) & 0xFF); |
| | | |
| | |
| | | return nRet; |
| | | } |
| | | |
| | | // 读åç®æ ç«ç¹CPUç±»å |
| | | // 读åç®æ ç«ç¹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); |
| | |
| | | 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); |
| | |
| | | return nRet; |
| | | } |
| | | |
| | | // è·åæ¿æ¨¡å¼ |
| | | // è·åæ¿æ¨¡å¼ |
| | | int CPerformanceMelsec::GetBoardMode(short& nMode) { |
| | | // æ£æ¥æ¯å¦å·²ç»è¿æ¥ |
| | | // æ£æ¥æ¯å¦å·²ç»è¿æ¥ |
| | | if (!m_bConnected.load()) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | |
| | | return 0; |
| | | } |
| | | |
| | | // æ¿å¤ä½ |
| | | // æ¿å¤ä½ |
| | | int CPerformanceMelsec::BoardReset() { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | if (!m_bConnected.load()) { |
| | |
| | | return nRet; |
| | | } |
| | | |
| | | // æ¿LED读å |
| | | // æ¿LED读å |
| | | int CPerformanceMelsec::ReadBoardLed(std::vector<short>& vecLedBuffer) { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | if (!m_bConnected.load()) { |
| | |
| | | return ERROR_CODE_NOT_CONNECTED; |
| | | } |
| | | |
| | | // æ¸
空 LED ç¼å²åº |
| | | // æ¸
空 LED ç¼å²åº |
| | | vecLedBuffer.clear(); |
| | | vecLedBuffer.resize(16, 0); |
| | | |
| | | // è°ç¨ SDK 彿°è¯»å LED æ°æ® |
| | | // è°ç¨ SDK 彿°è¯»å LED æ°æ® |
| | | const short nRet = mdBdLedRead(m_nPath, vecLedBuffer.data()); |
| | | if (nRet != 0) { |
| | | UpdateLastError(ERROR_CODE_NOT_CONNECTED); |
| | |
| | | return nRet; |
| | | } |
| | | |
| | | // è·åæ¿ç¶æ |
| | | // è·åæ¿ç¶æ |
| | | int CPerformanceMelsec::GetBoardStatus(BoardStatus& status) { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | if (!m_bConnected) { |
| | |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | |
| | | // å° buf æ å°å°ç»æä½ |
| | | // å° buf æ å°å°ç»æä½ |
| | | status = BoardStatus::fromBuffer(buf); |
| | | return 0; |
| | | } |
| | | |
| | | // éç¨è¯»æ°æ® |
| | | // éç¨è¯»æ°æ® |
| | | int CPerformanceMelsec::ReadData(const StationIdentifier& station, const short nDevType, const short nDevNo, short nSize, std::vector<short>& vecData) { |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int nRet = ValidateStationAndSize(station, 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(); |
| | |
| | | } |
| | | |
| | | if (nRet != 0) { |
| | | vecData.clear(); // å¦æè¯»åå¤±è´¥ï¼æ¸
空ç¼å²åº |
| | | 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); |
| | |
| | | } |
| | | |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const auto nSize = static_cast<short>((static_cast<int>(nBitCount) + 15) / 16); // 计ç®éè¦è¯»åçåæ°éï¼åä¸åæ´ï¼ |
| | | 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 ä¸çæ¯ä¸ä½ |
| | | // éåå½å 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 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 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); // 线ç¨å®å
¨ä¿æ¤ |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertShortToUint32(vecTempBuffer, vecData); |
| | | } |
| | | |
| | | return nRet; |
| | | } |
| | | |
| | | // éç¨åæ°æ® |
| | | // éç¨åæ°æ® |
| | | int CPerformanceMelsec::WriteData(const StationIdentifier& station, const short nDevType, const short nDevNo, short 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); |
| | |
| | | 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); |
| | |
| | | } |
| | | |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | const auto nSize = static_cast<short>((static_cast<int>(vecData.size()) + 15) / 16); // 计ç®éè¦åå
¥çåæ°éï¼åä¸åæ´ï¼ |
| | | const auto nSize = static_cast<short>((static_cast<int>(vecData.size()) + 15) / 16); // 计ç®éè¦åå
¥çåæ°éï¼åä¸åæ´ï¼ |
| | | |
| | | // åå¤ä¸´æ¶ç¼å²åºæ¥åå¨è½¬æ¢åç 16 使°æ® |
| | | // åå¤ä¸´æ¶ç¼å²åºæ¥åå¨è½¬æ¢åç 16 使°æ® |
| | | std::vector<short> vecTempBuffer(nSize, 0); |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | // å°ä½æ°æ®æåæå
å°ä¸´æ¶ç¼å²åº |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | // å°ä½æ°æ®æåæå
å°ä¸´æ¶ç¼å²åº |
| | | for (int i = 0; i < vecData.size(); ++i) { |
| | | if (vecData[i]) { |
| | | // ä½¿ç¨ & 0xFFFF ä¿è¯ä¸ä¼è¶
è¿ 16 ä½ï¼é²æ¢æº¢åº |
| | | // ä½¿ç¨ & 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 åèï¼ |
| | | // 计ç®éè¦åå
¥çåèæ°ï¼æ¯ä¸ªåå 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 åèï¼ |
| | | // 计ç®éè¦åå
¥çåèæ°ï¼æ¯ä¸ªååå 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); // 线ç¨å®å
¨ä¿æ¤ |
| | | 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); |
| | |
| | | std::vector<short> vecBuffer(nSize / 2, 0); |
| | | |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | nRet = mdReceiveEx(m_nPath, station.nNetNo, station.nStNo, nDevType, nDevNo, &nSize, vecBuffer.data()); |
| | | } |
| | | |
| | |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | else { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | vecData.resize(nSize); |
| | | ConvertShortToChar(vecBuffer, vecData); |
| | | } |
| | |
| | | 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 ç±»åçç¼å²åº |
| | | // å° 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); // 线ç¨å®å
¨ä¿æ¤ |
| | | 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::ReadRandomDataEx(const StationIdentifier& station, const std::vector<SoftElement>& vecSoftElements, std::vector<char>& vecData) { |
| | | if (vecSoftElements.empty()) { |
| | | UpdateLastError(ERROR_INVALID_PARAMETER); |
| | |
| | | return ERROR_INVALID_PARAMETER; |
| | | } |
| | | |
| | | // åå¤ dev æ°æ® |
| | | std::vector<short> devBuffer(vecSoftElements.size() * 3 + 1, 0); // æ¯ä¸ªè½¯å
ä»¶éè¦ 3 个 shortï¼å¤å ä¸ä¸ªè®¡æ°å¨ |
| | | devBuffer[0] = static_cast<short>(vecSoftElements.size()); // 第ä¸ä¸ªå
ç´ æ¯è½¯å
ä»¶æ°é |
| | | // åå¤ 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; // ç¹æ° |
| | | 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 个åè |
| | | nBufferSize += element.nElementCount * 2; // æ¯ä¸ªç¹å ç¨ 2 个åè |
| | | } |
| | | |
| | | // éä¿æ¤åè°ç¨ mdRandREx |
| | | // éä¿æ¤åè°ç¨ mdRandREx |
| | | long nRet = 0; |
| | | std::vector<short> vecBuffer(nBufferSize / 2, 0); |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // ç¡®ä¿çº¿ç¨å®å
¨ |
| | | 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 æ°æ® |
| | | // å°è¯»åå°ç 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); // é«åè |
| | | 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); |
| | |
| | | return ERROR_INVALID_PARAMETER; |
| | | } |
| | | |
| | | // åå¤ dev æ°æ® |
| | | std::vector<long> devBuffer(vecSoftElements.size() * 3 + 1, 0); // æ¯ä¸ªè½¯å
ä»¶éè¦ 3 个 longï¼å¤å ä¸ä¸ªè®¡æ°å¨ |
| | | devBuffer[0] = static_cast<long>(vecSoftElements.size()); // 第ä¸ä¸ªå
ç´ æ¯è½¯å
ä»¶æ°é |
| | | // åå¤ 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); // ç¹æ° |
| | | 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 |
| | | // éä¿æ¤åè°ç¨ mdRandWEx |
| | | long nRet = 0; |
| | | std::vector<short> vecBuffer(vecData.size() / 2, 0); |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // ç¡®ä¿çº¿ç¨å®å
¨ |
| | | 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); |
| | |
| | | long nActualSize = (nSize + 1) / 2; |
| | | std::vector<short> vecBuffer(nActualSize, 0); |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | 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); // æ´æ°é误ç |
| | | UpdateLastError(nRet); // æ´æ°é误ç |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | else { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | 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 ç±»åçç¼å²åº |
| | | // å° 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); // 线ç¨å®å
¨ä¿æ¤ |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertCharToShort(vecData, vecBuffer); |
| | | nRet = mdRemBufWriteEx(m_nPath, station.nNetNo, station.nStNo, nOffset, &nSize, vecBuffer.data()); |
| | | } |
| | |
| | | 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)) { |
| | |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | // å°ç¼å²åºå¤§å°è°æ´ä¸º nSize |
| | | // å°ç¼å²åºå¤§å°è°æ´ä¸º nSize |
| | | vecData.resize(nSize, 0); |
| | | std::vector<short> vecBuffer((nSize + 1) / 2, 0); // 转æ¢ä¸º short ç±»å |
| | | std::vector<short> vecBuffer((nSize + 1) / 2, 0); // 转æ¢ä¸º short ç±»å |
| | | |
| | | // è°ç¨åºå± SDK |
| | | // è°ç¨åºå± SDK |
| | | long nRet = 0; |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | nRet = mdRemBufReadIPEx(m_nPath, static_cast<long>(nAddress), nOffset, &nSize, vecBuffer.data()); |
| | | } |
| | | |
| | |
| | | LOG_ERROR(m_strLastError); |
| | | } |
| | | else { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ä¿æ¤ |
| | | ConvertShortToChar(vecBuffer, vecData); |
| | | } |
| | | |
| | | 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)) { |
| | |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | // è½¬æ¢ vecData 为 short ç±»åçç¼å²åº |
| | | // è½¬æ¢ 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); // 线ç¨å®å
¨ |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ |
| | | ConvertCharToShort(vecData, vecBuffer); |
| | | nRet = mdRemBufWriteIPEx(m_nPath, static_cast<long>(nAddress), nOffset, &nSize, vecBuffer.data()); |
| | | } |
| | |
| | | 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; |
| | | } |
| | | |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ |
| | | std::lock_guard<std::mutex> lock(m_mtx); // 线ç¨å®å
¨ |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | | nRet = mdDevSet(m_nPath, CombineStation(station), nDevType, nDevNo); |
| | | } |
| | |
| | | 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; |
| | | } |
| | | |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | // ç¡®ä¿çº¿ç¨å®å
¨çæå°éå®èå´ |
| | | { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | const short nDevType = CalculateDeviceType(station, enDevType); |
| | |
| | | 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; |
| | | } |
| | | |
| | | // æ©å±ä½è½¯å
ä»¶å¤ä½ |
| | | // æ©å±ä½è½¯å
ä»¶å¤ä½ |
| | | 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; |
| | | } |
| | | |
| | | // æ§è¡å¯¹è±¡ç«çCPU |
| | | // æ§è¡å¯¹è±¡ç«ç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); // åæ°é误 |
| | | 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); |
| | |
| | | return nRet; |
| | | } |
| | | |
| | | // äºä»¶çå¾
|
| | | // äºä»¶çå¾
|
| | | int CPerformanceMelsec::WaitForBoardEvent(std::vector<short> vecEventNumbers, const int nTimeoutMs, EventDetails& details) { |
| | | std::lock_guard<std::mutex> lock(m_mtx); |
| | | |
| | |
| | | return ERROR_CODE_INVALID_PARAM; |
| | | } |
| | | |
| | | // 第 0 个å
ç´ å卿°éï¼æå¤§æ¯æ 64 个äºä»¶ |
| | | // 第 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); |
| | | |
| | |
| | | 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 ç³»ç»æ£æµåºçé误 |
| | | // CC-Link ç³»ç»æ£æµåºçé误 |
| | | m_strLastError = "Error detected in the CC-Link system."; |
| | | } |
| | | |
| | | if (nCode >= -12288 && nCode <= -8193) { |
| | | // CC-Link IE TSN ç³»ç»æ£æµåºçé误 |
| | | // CC-Link IE TSN ç³»ç»æ£æµåºçé误 |
| | | m_strLastError = "Error detected in the CC-Link IE TSN system."; |
| | | } |
| | | |
| | | if (nCode >= -8192 && nCode <= -4097) { |
| | | // CC-Link IE æ§å¶ç½ç»ç³»ç»æ£æµåºçé误 |
| | | // CC-Link IE æ§å¶ç½ç»ç³»ç»æ£æµåºçé误 |
| | | m_strLastError = "Error detected in the CC-Link IE control network system."; |
| | | } |
| | | |
| | | if (nCode >= -4096 && nCode <= -257) { |
| | | // MELSECNET/10 æ MELSECNET/ç½ç»ç³»ç»é误èå´ |
| | | // MELSECNET/10 æ MELSECNET/ç½ç»ç³»ç»é误èå´ |
| | | m_strLastError = "Errors detected in MELSECNET/10 or MELSECNET/network system."; |
| | | } |
| | | |
| | | if (nCode >= 4096 && nCode <= 16383) { |
| | | // MELSEC æ°æ®é¾æ¥åºèå´ |
| | | // 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 æ£æµèå´ |
| | | // 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; // åæ°ææ |
| | | return 0; // åæ°ææ |
| | | } |
| | | |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | // éªè¯ç«ç¹åæ°åæ°æ®æææ§ |
| | | int CPerformanceMelsec::ValidateStationAndSize(const StationIdentifier& station, const short nCount) const { |
| | | // éªè¯ç«ç¹åæ° |
| | | // éªè¯ç«ç¹åæ° |
| | | const int nRet = ValidateStation(station); |
| | | if (nRet != 0) { |
| | | return nRet; // 妿ç«ç¹éªè¯å¤±è´¥ï¼è¿å对åºé误ç |
| | | return nRet; // 妿ç«ç¹éªè¯å¤±è´¥ï¼è¿å对åºé误ç |
| | | } |
| | | |
| | | 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); |
| | |
| | | return true; |
| | | } |
| | | |
| | | //============================================éæè¾
å©å½æ°==================================================== |
| | | // å»¶æ¶ï¼å¹¶ä¸è½¬åçªå£æ¶æ¯ |
| | | //============================================éæè¾
å©å½æ°==================================================== |
| | | // å»¶æ¶ï¼å¹¶ä¸è½¬åçªå£æ¶æ¯ |
| | | void CPerformanceMelsec::Delay(const unsigned int nDelayMs) { |
| | | MSG message; |
| | | // å¦æå»¶è¿æ¶é´ä¸º 0ï¼ä»
å¤ç䏿¬¡æ¶æ¯éå |
| | | // å¦æå»¶è¿æ¶é´ä¸º 0ï¼ä»
å¤ç䏿¬¡æ¶æ¯éå |
| | | if (nDelayMs == 0) { |
| | | // éé»å¡çæ£æ¥æ¶æ¯éå |
| | | // éé»å¡çæ£æ¥æ¶æ¯éå |
| | | if (PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { |
| | | TranslateMessage(&message); // å°æ¶æ¯è½¬å为ææççªå£æ¶æ¯ |
| | | DispatchMessage(&message); // æ´¾åæ¶æ¯ç»ç¸åºççªå£è¿ç¨ |
| | | TranslateMessage(&message); // å°æ¶æ¯è½¬å为ææççªå£æ¶æ¯ |
| | | DispatchMessage(&message); // æ´¾åæ¶æ¯ç»ç¸åºççªå£è¿ç¨ |
| | | } |
| | | return; |
| | | } |
| | | |
| | | DWORD finish; |
| | | const DWORD start = GetTickCount(); // è·åå½åçæ¶é´æ³ï¼ä»ç³»ç»å¯å¨ä»¥æ¥çæ¯«ç§æ°ï¼ |
| | | const DWORD start = GetTickCount(); // è·åå½åçæ¶é´æ³ï¼ä»ç³»ç»å¯å¨ä»¥æ¥çæ¯«ç§æ°ï¼ |
| | | do { |
| | | if (PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) { |
| | | TranslateMessage(&message); // è½¬æ¢æ¶æ¯ |
| | | DispatchMessage(&message); // å¤çæ¶æ¯ |
| | | TranslateMessage(&message); // è½¬æ¢æ¶æ¯ |
| | | DispatchMessage(&message); // å¤çæ¶æ¯ |
| | | } |
| | | Sleep(1); // æå 1 毫ç§ï¼é²æ¢è¿åº¦å ç¨ CPU |
| | | finish = GetTickCount(); // è·åå½åçæ¶é´æ³ |
| | | } while ((finish - start) < nDelayMs); // 循ç¯ç´å°ç»è¿çæ¶é´å¤§äºæå®çå»¶è¿æ¶é´ |
| | | Sleep(1); // æå 1 毫ç§ï¼é²æ¢è¿åº¦å ç¨ CPU |
| | | finish = GetTickCount(); // è·åå½åçæ¶é´æ³ |
| | | } while ((finish - start) < nDelayMs); // 循ç¯ç´å°ç»è¿çæ¶é´å¤§äºæå®çå»¶è¿æ¶é´ |
| | | } |
| | | |
| | | BoardType CPerformanceMelsec::FindBoardTypeByChannel(const int nChannel) { |
| | |
| | | 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 çå¼ |
| | | // èµ·å§ I/O No. ÷ 16 çå¼ |
| | | nDevType += 0 / 16; |
| | | } |
| | | |
| | | 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 容å¨å¤§å° |
| | | 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]); // ä½åè |
| | | vecShort[i / 2] = static_cast<unsigned char>(vecChar[i]); // ä½åè |
| | | } |
| | | else { |
| | | vecShort[i / 2] |= static_cast<unsigned char>(vecChar[i]) << 8; // é«åè |
| | | 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 容å¨å¤§å° |
| | | 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[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 容å¨å¤§å° |
| | | 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]); // ä½åè |
| | | vecShort[i / 2] = static_cast<short>(vecUint8[i]); // ä½åè |
| | | } |
| | | else { |
| | | vecShort[i / 2] |= static_cast<short>(vecUint8[i] << 8); // é«åè |
| | | 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 容å¨å¤§å° |
| | | 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[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 |
| | | 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[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 |
| | | 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[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; // 妿ç«ç¹éªè¯å¤±è´¥ï¼è¿å对åºé误ç |
| | | return nRet; // 妿ç«ç¹éªè¯å¤±è´¥ï¼è¿å对åºé误ç |
| | | } |
| | | |
| | | // éªè¯æ°æ®æ¯å¦ä¸ºç©º |
| | | // éªè¯æ°æ®æ¯å¦ä¸ºç©º |
| | | 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"); |
| | | |
| | | // èªå¨è®¡ç® nGroupSize |
| | | // èªå¨è®¡ç® nGroupSize |
| | | constexpr size_t nGroupSize = sizeof(U) / sizeof(T); |
| | | |
| | | // 妿 T å U ç大å°ç¸çï¼ç´æ¥è½¬æ¢ |
| | | // 妿 T å U ç大å°ç¸çï¼ç´æ¥è½¬æ¢ |
| | | if (sizeof(T) == sizeof(U)) { |
| | | vecHigh.assign(vecLow.begin(), vecLow.end()); |
| | | return; |
| | | } |
| | | |
| | | // 妿 U ç大尿¯ 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; // åä¸åæ´ |
| | | // 计ç®å®æ´ç»çæ°é |
| | | 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 |
| | | // èªå¨è®¡ç® nGroupSize |
| | | constexpr size_t nGroupSize = sizeof(T) / sizeof(U); |
| | | |
| | | // 妿 T å U ç大å°ç¸çï¼ç´æ¥è½¬æ¢ |
| | | // 妿 T å U ç大å°ç¸çï¼ç´æ¥è½¬æ¢ |
| | | if (sizeof(T) == sizeof(U)) { |
| | | vecLow.assign(vecHigh.begin(), vecHigh.end()); |
| | | return; |
| | | } |
| | | |
| | | // 妿 T ç大尿¯ 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; // ä½å®¹å¨çå¤§å° |
| | | 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)); |