// DIOS.Dev.DME.NormalDME.cpp : 定义 DLL 应用程序的导出函数。 // #include "stdafx.h" #include #include #include "common_api.h" using namespace std::placeholders; #include "DIOS.Dev.DME.NormalDME.h" #include "Helper.JSON.hpp" using namespace DIOS::Dev::Detail::DME; namespace nsDME = DIOS::Dev::Detail::DME; #pragma warning (disable:4244) // warning C4244: “初始化”: 从“double”转换到“float”,可能丢失数据 #pragma warning (disable:4305) // warning C4305: “参数”: 从“double”到“float”截断 #pragma warning (disable:4267) // warning C4267 : “初始化”: 从“size_t”转换到“int”,可能丢失数据 static const int msTimeOut_Lock = 500; #ifdef _WIN64 #ifdef _DEBUG static const auto COM_SCFDllName = "Dios.Dev.SerialSCFX64D.dll"; #else static const auto COM_SCFDllName = "Dios.Dev.SerialSCFX64.dll"; #endif #endif #ifdef _WIN64 #ifdef _DEBUG static const auto TCP_SCFDllName = "Dios.Dev.TcpipSCFX64D.dll"; #else static const auto TCP_SCFDllName = "Dios.Dev.TcpipSCFX64.dll"; #endif #endif //----------------------------------------------------------------------------- // DMEDevice //----------------------------------------------------------------------------- nsDME::DMENormalDMEDevice::DMENormalDMEDevice(std::shared_ptr center, nsSCF::SCF SCF, string configfile) : super(center, SCF) { assert(EventCenter); ResDataObject temp; temp.loadFile(configfile.c_str()); m_DMEConfig = temp["CONFIGURATION"]; TransJsonText(m_DMEConfig); if (m_DMEConfig.GetKeyCount("CalibrateValue") > 0) { m_nCalibrateValue = (int)m_DMEConfig["CalibrateValue"]; } else { m_nCalibrateValue = 0; } if (m_DMEConfig.GetKeyCount("MeasurementInterval") > 0) { m_nMeasurementInterval = (int)m_DMEConfig["MeasurementInterval"]; } else { m_nMeasurementInterval = 1; } if (m_DMEConfig.GetKeyCount("Position") > 0) { m_nPosition = (int)m_DMEConfig["Position"]; } else { m_nPosition = 0; } if (m_DMEConfig.GetKeyCount("Range") > 0) { m_nRange = (int)m_DMEConfig["Range"];//Range : 05,10,30,50,80m } else { m_nRange = 5; } if (m_DMEConfig.GetKeyCount("Frequency") > 0) { m_nFrequency = (int)m_DMEConfig["Frequency"];//Freq : 05 10 20 } else { m_nFrequency = 5; } if (m_DMEConfig.GetKeyCount("Resolution") > 0) { m_nResolution = (int)m_DMEConfig["Resolution"];//1(1mm),2(0.1mm) } else { m_nResolution = 1; } if (m_DMEConfig.GetKeyCount("MeasureSID") > 0) { m_nMeasureSID = (int)m_DMEConfig["MeasureSID"]; } else { m_nMeasureSID = 180; } if (m_DMEConfig.GetKeyCount("MeasureAngle") > 0) { m_nMeasureAngle = (int)m_DMEConfig["MeasureAngle"]; } else { m_nMeasureAngle = 0; } m_DMEUnit.m_Distance.reset(new DistanceMould(0.0f, 0.0f, 5000.0f, 0.1)); m_DMEUnit.m_LaserState.reset(new LaserStateMould(0, 0, 1, 1)); m_DMEUnit.m_ConnectionStatus.reset(new ConnectionStatusMould(0, 0, 1, 1)); m_MSGUnit.reset(new nsDetail::MSGUnit(center, nsDME::DMEUnitType)); Register(); } nsDME::DMENormalDMEDevice::~DMENormalDMEDevice() { } std::string nsDME::DMENormalDMEDevice::GetGUID() const { mLog::FINFO("\n===============GetGUID : {$} ===================\n", DMEUnitType); return DMEUnitType; } RET_STATUS nsDME::DMENormalDMEDevice::FetchDistance() { char szCmdBuf[4]; szCmdBuf[0] = 0x80; szCmdBuf[1] = 0x06; szCmdBuf[2] = 0x02; szCmdBuf[3] = 0x78; mLog::FINFO("Fetching distance with command: {$}", std::string(szCmdBuf, 4).c_str()); // Log the command buffer return HWSend(szCmdBuf, 4); } RET_STATUS nsDME::DMENormalDMEDevice::SetCalibrateValue(int pParams) { char szCmdBuf[6]; szCmdBuf[0] = 0xFA; szCmdBuf[1] = 0x04; szCmdBuf[2] = 0x06; if (pParams > 0) { szCmdBuf[3] = 0x2B; } else if (pParams < 0) { szCmdBuf[3] = 0x2D; } else { //=0 do nonthing.. mLog::FINFO("calibrate value = 0,so directly return ."); return RET_STATUS::RET_SUCCEED; } szCmdBuf[4] = pParams; char checksum = (char)(~(char)(szCmdBuf[0] + szCmdBuf[1] + szCmdBuf[2] + szCmdBuf[3] + szCmdBuf[4]) + 1); szCmdBuf[5] = checksum; mLog::FINFO("Setting calibration value: {$} with command: {$}", pParams, std::string(szCmdBuf, 6).c_str()); // Log calibration command return HWSend(szCmdBuf, 6); } RET_STATUS nsDME::DMENormalDMEDevice::SetMeasurementInterval(int pParams) { char szCmdBuf[5]; szCmdBuf[0] = 0xFA; szCmdBuf[1] = 0x04; szCmdBuf[2] = 0x05; szCmdBuf[3] = pParams; char checksum = (char)(~((char)(szCmdBuf[0] + szCmdBuf[1] + szCmdBuf[2] + szCmdBuf[3])) + 1); szCmdBuf[4] = checksum; mLog::FINFO("Setting measurement interval: {$} with command: {$}", pParams, std::string(szCmdBuf, 5).c_str()); // Log interval setting return HWSend(szCmdBuf, 5); } RET_STATUS nsDME::DMENormalDMEDevice::SetStartEndPoints(int pParams) { char szCmdBuf[5]; szCmdBuf[0] = 0xFA; szCmdBuf[1] = 0x04; szCmdBuf[2] = 0x08; szCmdBuf[3] = pParams; char checksum = (char)(~((char)(szCmdBuf[0] + szCmdBuf[1] + szCmdBuf[2] + szCmdBuf[3])) + 1); szCmdBuf[4] = checksum; mLog::FINFO("Setting start-end points: {$} with command: {$}", pParams, std::string(szCmdBuf, 5).c_str()); // Log points setting return HWSend(szCmdBuf, 5); } RET_STATUS nsDME::DMENormalDMEDevice::SetRange(int pParams) { char szCmdBuf[5]; szCmdBuf[0] = 0xFA; szCmdBuf[1] = 0x04; szCmdBuf[2] = 0x09; szCmdBuf[3] = pParams; char checksum = (char)(~((char)(szCmdBuf[0] + szCmdBuf[1] + szCmdBuf[2] + szCmdBuf[3])) + 1); szCmdBuf[4] = checksum; mLog::FINFO("Setting range: {$} with command: {$}", pParams, std::string(szCmdBuf, 5).c_str()); return HWSend(szCmdBuf, 5); } RET_STATUS nsDME::DMENormalDMEDevice::SetFrequency(int pParams) { char szCmdBuf[5]; szCmdBuf[0] = 0xFA; szCmdBuf[1] = 0x04; szCmdBuf[2] = 0x0A; szCmdBuf[3] = pParams; char checksum = (char)(~((char)(szCmdBuf[0] + szCmdBuf[1] + szCmdBuf[2] + szCmdBuf[3])) + 1); szCmdBuf[4] = checksum; mLog::FINFO("Setting frequency: {$} with command: {$}", pParams, std::string(szCmdBuf, 5).c_str()); // Log frequency setting return HWSend(szCmdBuf, 5); } RET_STATUS nsDME::DMENormalDMEDevice::SetResolution(int pParams) { char szCmdBuf[5]; szCmdBuf[0] = 0xFA; szCmdBuf[1] = 0x04; szCmdBuf[2] = 0x0C; szCmdBuf[3] = pParams; char checksum = (char)(~((char)(szCmdBuf[0] + szCmdBuf[1] + szCmdBuf[2] + szCmdBuf[3])) + 1); szCmdBuf[4] = checksum; mLog::FINFO("Setting resolution: {$} with command: {$}", pParams, std::string(szCmdBuf, 5).c_str()); // Log resolution setting return HWSend(szCmdBuf, 5); } RET_STATUS nsDME::DMENormalDMEDevice::SetLaserState(int pParams) { char szCmdBuf[5]; szCmdBuf[0] = 0x80; szCmdBuf[1] = 0x06; szCmdBuf[2] = 0x05; szCmdBuf[3] = (char)pParams; char checksum = (char)(~(char)(szCmdBuf[0] + szCmdBuf[1] + szCmdBuf[2] + szCmdBuf[3]) + 1); szCmdBuf[4] = checksum; mLog::FINFO("Setting laser state: {$} with command: {$}", pParams, std::string(szCmdBuf, 5).c_str()); // Log laser state setting return HWSend(szCmdBuf, 5); } RET_STATUS nsDME::DMENormalDMEDevice::ShutDown() { char szCmdBuf[4]; szCmdBuf[0] = 0x80; szCmdBuf[1] = 0x04; szCmdBuf[2] = 0x02; szCmdBuf[3] = 0x7A; mLog::FINFO("Shutting down device with command: {$}", std::string(szCmdBuf, 4).c_str()); // Log shutdown command return HWSend(szCmdBuf, 4); } void nsDME::DMENormalDMEDevice::Register() { auto Disp = &Dispatch; superGen::Register(Disp); Disp->Get.Push(m_MSGUnit->GetKey().c_str(), [this](std::string& out) { out = m_MSGUnit->JSGet(); return RET_STATUS::RET_SUCCEED; }); } bool nsDME::DMENormalDMEDevice::isChecksumValid(const char* str, size_t len) { int sum = 0; for (size_t i = 0; i < len - 1; ++i) { sum += str[i]; // 累加每个字符的 ASCII 值 } char checksum = ~(char)(sum)+1; return static_cast(checksum) == str[len - 1]; } void nsDME::DMENormalDMEDevice::SendNextCommand() { if (!commandQueue.empty()) { std::string command = commandQueue.front(); SetCommand(command); commandQueue.pop(); std::this_thread::sleep_for(std::chrono::milliseconds(50)); // 命令节流的延迟 } } RET_STATUS nsDME::DMENormalDMEDevice::HWSend(const char* strCommand,int length,int nTimeOut) { if (!m_SCF) return RET_STATUS::RET_FAILED; int ret = 0; m_SCF.Lock(msTimeOut_Lock) .SendPacket(strCommand, length, nTimeOut, ret); Sleep(nTimeOut); return RET_STATUS::RET_SUCCEED; } RET_STATUS nsDME::DMENormalDMEDevice::SetCommand(std::string& cmd) { int nlen = cmd.length(); return HWSend(cmd.c_str(), static_cast(cmd.length())); } //----------------------------------------------------------------------------- // ProcessCmd //----------------------------------------------------------------------------- void nsDME::DMENormalDMEDevice::FireNotify(std::string key, std::string content) { EventCenter->OnNotify(1, key, content); } void nsDME::DMENormalDMEDevice::OnCallBack(const char* strPackage, DWORD Length) { if (m_DMEUnit.m_ConnectionStatus->Update(true)) FireNotify(m_DMEUnit.m_ConnectionStatus->GetKey(), m_DMEUnit.m_ConnectionStatus->JSGet());; // 打印日志 std::string hexString; for (DWORD j = 0; j < Length; ++j) { char buffer[3]; snprintf(buffer, sizeof(buffer), "%02X", static_cast(strPackage[j])); hexString += buffer; } mLog::FINFO("==IN==: {$}", hexString.c_str()); std::string str; size_t packageLength = Length; // 提取处理函数 auto handlePackage = [&](size_t offset, size_t length) { if (isChecksumValid(strPackage, packageLength)) { str.assign(strPackage + offset, length); } }; switch (strPackage[0]) { case char(0x80) : if (strPackage[1] == (char)0x06 && (strPackage[2] == (char)0x82 || strPackage[2] == (char)0x85)) { handlePackage(2, packageLength - 3); // 处理有效数据 } break; case char(0xFA) : if (strPackage[1] == (char)0x04 || strPackage[1] == (char)0x84) { handlePackage(1, packageLength - 2); // 处理有效数据 } break; default: break; } const char* chdigital = str.c_str() + 1; float _fDistance = 0.0f; switch (str[0]) { case (char)0x82: // Case 0x82 { mLog::FINFO("enter 0x82 branch --2"); _fDistance = atof(chdigital); // 单位:m mLog::FINFO("distance from hard to obj front is {$} ,unit: m", _fDistance); // 计算 m_nDistance int nDistance = static_cast((_fDistance * 100) * cos(m_nMeasureAngle / 180 * 3.1415926)); mLog::FINFO("sid= {$} cm, subtraction m_ndistance is {$} cm. obj's height is {$} cm.", m_nMeasureSID, nDistance, (m_nMeasureSID - nDistance)); m_DMEUnit.m_Distance->Update(nDistance); FireNotify(m_DMEUnit.m_Distance->GetKey(), m_DMEUnit.m_Distance->JSGet()); break; } case (char)0x04: // Case 0x04 { switch (str[1]) { case (char)0x8C: // set resolution ratio mLog::FINFO("set resolution ratio success. type is {$}", m_nResolution); break; case (char)0x8B: // set calibrate value mLog::FINFO("set calibrate value success."); break; default: break; } break; } case (char)0x84: // Case 0x84 (Error case) { mLog::FINFO("something wrong"); switch (str[1]) { case (char)0x8B: mLog::FINFO("set calibrate value failed."); break; case (char)0x8C: mLog::FINFO("set resolution ratio failed."); break; default: break; } break; } case (char)0x85: // Case 0x85 mLog::FINFO("{$}",str[1] == 0x01 ? "set laser cmd, success" : "set laser cmd, failed."); break; case 'E': // Error case { mLog::FERROR("error"); break; } case 'D': // Calibration value case { chdigital = str.c_str() + 2; int _nCalibrateValue = atoi(chdigital); mLog::FINFO("Calibrate value = {$} mm.", _nCalibrateValue); m_nCalibrateValue = _nCalibrateValue / 10; break; } case 'L': // Distance case { chdigital = str.c_str() + 2; int _nDistance = atoi(chdigital); mLog::FINFO("distance from hard to obj front is {$} ,unit: mm", _nDistance); // 计算 nDistance int nDistance = static_cast((_fDistance * 100) * cos(m_nMeasureAngle / 180 * 3.1415926)); mLog::FINFO("height of obj is {$} cm.", nDistance); m_DMEUnit.m_Distance->Update(nDistance); FireNotify(m_DMEUnit.m_Distance->GetKey(), m_DMEUnit.m_Distance->JSGet()); break; } case 'M': // Data mode or max len case { if (str[1] == '=') { chdigital = str.c_str() + 2; int nDataMode = atoi(chdigital); mLog::FINFO("data mode : {$}", nDataMode); } else { chdigital = str.c_str() + 4; int nMaxLen = atoi(chdigital); mLog::FINFO("max len = {$}", nMaxLen); } break; } case 'S': // Distance send mode case { chdigital = str.c_str() + 2; int nDistanceSendMode = atoi(chdigital); mLog::FINFO("distance send mode : {$}", nDistanceSendMode); break; } case 'T': // Send interval case { chdigital = str.c_str() + 2; int nSendInterval = atoi(chdigital); mLog::FINFO("send interval : {$}", nSendInterval); break; } default: break; } } nsDME::DMENormalDMEDriver::DMENormalDMEDriver() { } nsDME::DMENormalDMEDriver::~DMENormalDMEDriver() { mLog::Close(); mLog::gLogger = nullptr; } auto nsDME::DMENormalDMEDriver::CreateDevice(int index) -> std::unique_ptr { mLog::FINFO("CreateDevice in"); m_pDevice = new DMENormalDMEDevice(EventCenter, m_SCF, m_ConfigFileName); auto dev = std::unique_ptr (new IODevice(m_pDevice)); mLog::FINFO("CreateDevice in m_pDevice :{$}", m_pDevice); //m_pDevice->Register(); return dev; } void nsDME::DMENormalDMEDriver::FireNotify(int code, std::string key, std::string content) { EventCenter->OnNotify(code, key, content); } Log4CPP::Logger* mLog::gLogger = nullptr; void nsDME::DMENormalDMEDriver::Prepare() { mLog::FINFO("Prepare in"); ResDataObject r_config; if (r_config.loadFile(m_ConfigFileName.c_str())) { string strLogPath = GetProcessDirectory() + R"(\OEMDrivers\DME\Conf\Log4CPP.Config.DME.xml)"; Log4CPP::GlobalContext::Map::Set(ECOM::Utility::Hash("LogFileName"), "DME.NormalDME"); auto rc = Log4CPP::LogManager::LoadConfigFile(strLogPath.c_str()); mLog::gLogger = Log4CPP::LogManager::GetLogger("DME.NormalDME"); m_SCFDllName = GetConnectDLL(m_ConfigFileName); } super::Prepare(); } bool DATA_ACTION nsDME::DMENormalDMEDriver::Connect() { super::Disconnect(); m_SCF.Disconnect(); mLog::FINFO("Connect in"); ResDataObject Connection = GetConnectParam(m_ConfigFileName); mLog::FINFO("connections:{$}", Connection.encode()); auto erCode = m_SCF.Connect(Connection.encode(), &nsDME::DMENormalDMEDriver::callbackPackageProcess, SCF_PACKET_TRANSFER, 3000); if (erCode != SCF_ERR::SCF_SUCCEED) { mLog::FINFO("erCode != SCF_ERR::SCF_SUCCEED:{$}", erCode); return false; } auto rc = super::Connect(); if (!rc) { mLog::FINFO("super::Connect failed"); return false; } return true; } void nsDME::DMENormalDMEDriver::Disconnect() { super::Disconnect(); m_SCF.Disconnect(); } bool nsDME::DMENormalDMEDriver::isConnected() const { return super::isConnected(); } std::string nsDME::DMENormalDMEDriver::DriverProbe() { mLog::FINFO("DriverProbe in"); ResDataObject r_config, HardwareInfo; if (r_config.loadFile(m_ConfigFileName.c_str())) { HardwareInfo.add("MajorID", r_config["CONFIGURATION"]["MajorID"]); HardwareInfo.add("MinorID", r_config["CONFIGURATION"]["MinorID"]); HardwareInfo.add("VendorID", r_config["CONFIGURATION"]["VendorID"]); HardwareInfo.add("ProductID", r_config["CONFIGURATION"]["ProductID"]); HardwareInfo.add("SerialID", r_config["CONFIGURATION"]["SerialID"]); } else { HardwareInfo.add("MajorID", "DME"); HardwareInfo.add("MinorID", "Dr"); HardwareInfo.add("VendorID", "NormalDME"); HardwareInfo.add("ProductID", "HF"); HardwareInfo.add("SerialID", "Drv"); } string ret = HardwareInfo.encode(); return ret; } std::string nsDME::DMENormalDMEDriver::GetResource() { mLog::FINFO("GetResource in"); ResDataObject temp; if (!temp.loadFile(m_ConfigFileName.c_str())) return std::string(); auto r_config = temp["CONFIGURATION"]; for (auto& Item : m_ConfigInfo) { string key = Item.GetKey(); if (key == ConfKey::DiosType) { Item.SetCurrentValue(((string)r_config["VendorID"]).c_str()); } else if (key == ConfKey::DiosModel) { Item.SetCurrentValue(((string)r_config["ProductID"]).c_str()); } else if (key == ConfKey::DiosSCFType) { Item.SetCurrentValue(((string)r_config["connections"][0]["type"]).c_str()); } else if (key == ConfKey::DiosSCFPort || key == ConfKey::DiosSCFBaudrate || key == ConfKey::DiosSCFBytesize || key == ConfKey::DiosSCFParity || key == ConfKey::DiosSCFStopbits || key == ConfKey::DiosSCFIP) { if (r_config["connections"][0].GetFirstOf(key.c_str()) >= 0) { Item.SetCurrentValue(((string)r_config["connections"][0][key.c_str()]).c_str()); } } } ResDataObject resAttr, resDescription; for (auto Item : m_ConfigInfo) { resAttr.add(Item.GetKey(), Item.GetCurrentValue()); resDescription.add(Item.GetKey(), Item.GetDescription()); } ResDataObject resDeviceResource; resDeviceResource.add(ConfKey::DiosAttribute, resAttr); resDeviceResource.add(ConfKey::DiosDescription, resDescription); string res = resDeviceResource.encode(); mLog::FINFO("sresDeviceResource : {$}", resDeviceResource.encode()); //printf("resDeviceResource :%s \n", resDeviceResource.encode()); return res; } std::string nsDME::DMENormalDMEDriver::DeviceProbe() { mLog::FINFO("DeviceProbe in"); ResDataObject r_config, HardwareInfo; if (r_config.loadFile(m_ConfigFileName.c_str())) { HardwareInfo.add("MajorID", r_config["CONFIGURATION"]["MajorID"]); HardwareInfo.add("MinorID", r_config["CONFIGURATION"]["MinorID"]); HardwareInfo.add("VendorID", r_config["CONFIGURATION"]["VendorID"]); HardwareInfo.add("ProductID", r_config["CONFIGURATION"]["ProductID"]); HardwareInfo.add("SerialID", r_config["CONFIGURATION"]["SerialID"]); } else { HardwareInfo.add("MajorID", "DME"); HardwareInfo.add("MinorID", "Dr"); HardwareInfo.add("VendorID", "NormalDME"); HardwareInfo.add("ProductID", "HF"); HardwareInfo.add("SerialID", "1234"); } string ret = HardwareInfo.encode(); return ret; } void nsDME::DMENormalDMEDriver::Dequeue(const char* Packet, DWORD Length) { mLog::FINFO("Dequeue in m_pDevice :{$}", m_pDevice); m_pDevice->OnCallBack(Packet, Length); } PACKET_RET nsDME::DMENormalDMEDriver::callbackPackageProcess(const char* RecData, DWORD nLength, DWORD& PacketLength) { // 判断是否是整包 /* 这个是回调函数,我收到的数据会需要这个回调函数帮我判断是否是整个的包; 如果有整个的包,返回值为true,在PacketLength处返回给我整个包的长度,我再截取后放入缓存供上层使用; 如果缓存中的数据没有整个的数据包,那么返回false */ if (nLength < 1) { mLog::Warn("nLength < 1, nLength=={$}", nLength); return PACKET_USELESS; } // 查找包的结束标志(0x0d 0x0a) for (DWORD i = 0; i < nLength - 1; i++) { if (RecData[i] == (char)0xFA || RecData[i] == (char)0x80) { // 找到了完整的包 PacketLength = nLength; // 将包的长度设置为结束标志之后的位置 std::string hexString; for (DWORD j = 0; j < nLength; ++j) { char buffer[3]; snprintf(buffer, sizeof(buffer), "%02X", static_cast(RecData[j])); hexString += buffer; } mLog::FINFO("callbackPackageProcess, Packet content: {$}", hexString.c_str()); return PACKET_ISPACKET; // 返回整个包 } } // 未找到包的结束标志,返回无效包 return PACKET_NOPACKET; } //----------------------------------------------------------------------------- // GetIODriver & CreateIODriver //----------------------------------------------------------------------------- static nsDME::DMENormalDMEDriver gIODriver; extern "C" DIOS::Dev::IODriver * __cdecl GetIODriver() // 返回静态对象的引用, 调用者不能删除 ! { return &gIODriver; } extern "C" DIOS::Dev::IODriver * __cdecl CreateIODriver() // 返回新对象, 调用者必须自行删除此对象 ! { return new nsDME::DMENormalDMEDriver(); } #if 0 #endif