#include "ModuleDevice.h" #include "PacketAnalizer.h" #include "common_api.h" #include "LocalConfig.h" #include "Base64.h" #include "SystemLogger.hpp" #include #include #include #include #include ModuleDevice::ModuleDevice() { m_pSendConn = nullptr; m_bSendIndependently = false; //if (//mLog::gLogger == nullptr) //{ // string strLogPath = GetProcessDirectory() + R"(\Conf\Log4CPP.Config.xml)"; // string LogHost = ((string)getLogRootpath()).c_str(); // //if (LogHost.length() <= 1) // //{ // // char szName[256]; // // sprintf(szName, "/LogicDevice_%08d", GetCurrentProcessId()); // // LogHost = szName; // //} // Log4CPP::ThreadContext::Map::Set(ECOM::Utility::Hash("LogFileName"), "Platform"); // //Log4CPP::GlobalContext::Map::Set("LogHost", LogHost.c_str()); // Log4CPP::ThreadContext::Map::Set(ECOM::Utility::Hash("LogHost"), LogHost.c_str() + 1); // auto rc = Log4CPP::LogManager::LoadConfigFile(strLogPath.c_str()); // //mLog::gLogger = Log4CPP::LogManager::GetLogger("Platform"); //} } ModuleDevice::~ModuleDevice() { } std::wstring mb2wc_a(const char* mbstr) { // 保存当前 locale 设置 std::string old_locale = std::setlocale(LC_CTYPE, nullptr); try { // 设置 UTF-8 环境(Linux 宽字符转换依赖 locale) if (!std::setlocale(LC_CTYPE, "en_US.UTF-8")) { throw std::runtime_error("Failed to set UTF-8 locale"); } // 计算所需宽字符缓冲区大小 std::size_t size = std::mbstowcs(nullptr, mbstr, 0); if (size == static_cast(-1)) { throw std::runtime_error("Invalid multibyte sequence"); } // 创建宽字符缓冲区 (+1 给空终止符) wchar_t* wcstr = new wchar_t[size + 1]; // 执行实际转换 if (std::mbstowcs(wcstr, mbstr, size + 1) == static_cast(-1)) { delete[] wcstr; throw std::runtime_error("Conversion failed"); } std::wstring result(wcstr); delete[] wcstr; // 恢复原始 locale std::setlocale(LC_CTYPE, old_locale.c_str()); return result; } catch (...) { // 确保异常时恢复 locale std::setlocale(LC_CTYPE, old_locale.c_str()); throw; } } RET_STATUS ModuleDevice::IoSystemLog(int Level, const char* pCode, const char* pContext, size_t ContextSize, const char* pAppId) { std::string strResult = ""; //组Context包 //if (m_pLogger) { wstring wContect = mb2wc_a(pContext); CBase64::Encode((const unsigned char*)wContect.c_str(), (unsigned long)wContect.size() * sizeof(wchar_t), strResult); } //Thread_Lock(); //if (NULL != fmt) //{ // va_list marker = NULL; // va_start(marker, fmt); // size_t nLength = _vscprintf(fmt, marker) + 1; // std::vector vBuffer(nLength, '\0'); // int nWritten = vsnprintf_s(&vBuffer[0], vBuffer.size(), nLength, fmt, marker); // if (nWritten > 0) // { // strResult = &vBuffer[0]; // } // va_end(marker); //} //Thread_UnLock(); ResDataObject SysLogNode; string guidstr; GUID DeviceGuid; //组Log包 if (GetDeviceType(DeviceGuid)) { guid_2_string(DeviceGuid, guidstr); SysLogNode.add("Module", guidstr.c_str()); SysLogNode.add("AppId", pAppId); SysLogNode.add("ThreadId", GetCurrentThreadId()); if (pCode) { SysLogNode.add("BusinessKey", pCode); } else { SysLogNode.add("BusinessKey", ""); } SysLogNode.add("IP", (const char*)getLocalIpAddress()); struct timeval tv; gettimeofday(&tv, nullptr); struct tm tm_time; localtime_r(&tv.tv_sec, &tm_time); string TimeTag = FormatstdString("%04d-%02d-%02d %02d:%02d:%02d.%03ld", tm_time.tm_year + 1900, // 年份 tm_time.tm_mon + 1, // 月份 tm_time.tm_mday, // 日 tm_time.tm_hour, // 时 tm_time.tm_min, // 分 tm_time.tm_sec, // 秒 tv.tv_usec / 1000); SysLogNode.add("CreationTime", TimeTag.c_str()); string strLevel = SysLogLevel2str(Level); SysLogNode.add("Level", strLevel.c_str()); SysLogNode.add("HostName", (const char*)getLocalMachineId()); SysLogNode.add("ProcessName", (const char*)GetModuleTitle()); SysLogNode.add("FreeText", strResult.c_str()); SysLogNode.add("Context", pCode); ResDataObject NotifyData; PacketAnalizer::MakeNotify(NotifyData, PACKET_CMD_MSG, "Syslog", SysLogNode); SendNotify(&NotifyData); //PublishAction(&NotifyData, (m_strEBusRoot + "/Notify").c_str(), m_pMqttConntion); } else { //mLog::FINFO("no Guid??"); return RET_FAILED; } //打印LOG switch (Level) { case Syslog_Debug: //RES_PRINTA_DEBUG(m_pLogger, SysLogNode, "SysLog"); //mLog::FDEBUG("SysLog {$} ", SysLogNode.encode()); break; case Syslog_Information: ///RES_PRINTA_INFO(m_pLogger, SysLogNode, "SysLog"); //mLog::FINFO("SysLog {$} ", SysLogNode.encode()); break; case Syslog_Warning: //RES_PRINTA_WARN(m_pLogger, SysLogNode, "SysLog"); //mLog::Warn("SysLog {$} ", SysLogNode.encode()); break; case Syslog_Error: //RES_PRINTA_ERROR(m_pLogger, SysLogNode, "SysLog"); //mLog::FERROR("SysLog {$} ", SysLogNode.encode()); break; case Syslog_Fatal: //RES_PRINTA_FATAL(m_pLogger, SysLogNode, "SysLog"); //mLog::FINFO("SysLog {$} ", SysLogNode.encode()); break; default: //mLog::FINFO("SysLog {$} ", SysLogNode.encode()); break; } return RET_SUCCEED; } RET_STATUS ModuleDevice::SystemLog(SYSLOGLEVEL Level, const char* pCode, const char* fmt, ...) { std::string strResult = ""; //组Context包 //if (m_pLogger) //{ // m_pLogger->Thread_Lock(); // if (NULL != fmt) // { // va_list marker = NULL; // va_start(marker, fmt); // size_t nLength = _vscprintf(fmt, marker) + 1; // std::vector vBuffer(nLength, '\0'); // int nWritten = vsnprintf_s(&vBuffer[0], vBuffer.size(), nLength, fmt, marker); // if (nWritten > 0) // { // strResult = &vBuffer[0]; // } // va_end(marker); // } // m_pLogger->Thread_UnLock(); //} //else { Thread_Lock(); if (fmt != nullptr) // 使用 nullptr 代替 NULL { va_list marker; va_start(marker, fmt); // 计算格式化字符串所需长度(不包括终止空字符) va_list args_copy; va_copy(args_copy, marker); // 复制参数列表 int nLength = vsnprintf(nullptr, 0, fmt, args_copy); // Linux下获取长度的方法 va_end(args_copy); if (nLength < 0) { // 处理错误:格式化失败 va_end(marker); // 这里可以添加错误处理逻辑 } else { // 分配足够空间(包括终止空字符) std::vector vBuffer(nLength + 1, '\0'); // 实际执行格式化 int nWritten = vsnprintf(vBuffer.data(), vBuffer.size(), fmt, marker); if (nWritten >= 0 && static_cast(nWritten) < vBuffer.size()) { strResult = vBuffer.data(); // 直接赋值给结果字符串 } // 如果 nWritten 无效则保持 strResult 不变 } va_end(marker); } Thread_UnLock(); } ResDataObject SysLogNode; string guidstr; GUID DeviceGuid; //组Log包 if (GetDeviceType(DeviceGuid)) { guid_2_string(DeviceGuid, guidstr); SysLogNode.add("Module", guidstr.c_str()); SysLogNode.add("AppId", ""); SysLogNode.add("ThreadId", GetCurrentThreadId()); if (pCode) { SysLogNode.add("BusinessKey", pCode); } else { SysLogNode.add("BusinessKey", ""); } SysLogNode.add("IP", (const char*)getLocalIpAddress()); struct timeval tv; gettimeofday(&tv, nullptr); struct tm tm_time; localtime_r(&tv.tv_sec, &tm_time); string TimeTag = FormatstdString("%04d-%02d-%02d %02d:%02d:%02d.%03ld", tm_time.tm_year + 1900, // 年份 tm_time.tm_mon + 1, // 月份 tm_time.tm_mday, // 日 tm_time.tm_hour, // 时 tm_time.tm_min, // 分 tm_time.tm_sec, // 秒 tv.tv_usec / 1000); SysLogNode.add("CreationTime", TimeTag.c_str()); SysLogNode.add("Level", Level); SysLogNode.add("HostName", (const char*)getLocalMachineId()); SysLogNode.add("ProcessName", (const char*)GetModuleTitle()); SysLogNode.add("FreeText", strResult.c_str()); ResDataObject NotifyData; PacketAnalizer::MakeNotify(NotifyData, PACKET_CMD_MSG, "Syslog", SysLogNode); SendNotify(&NotifyData); //PublishAction(&NotifyData, (m_strEBusRoot + "/Notify").c_str(), m_pMqttConntion); if (m_pParent != nullptr) NotifyParent(&NotifyData, "/Notify"); } else { //mLog::FERROR("no Guid??"); return RET_FAILED; } //打印LOG switch (Level) { case Syslog_Debug: //RES_PRINTA_DEBUG(m_pLogger, SysLogNode, "SysLog"); //mLog::FDEBUG("SysLog {$}", SysLogNode.encode()); break; case Syslog_Information: //RES_PRINTA_INFO(m_pLogger, SysLogNode, "SysLog"); //mLog::FINFO("SysLog {$}", SysLogNode.encode()); break; case Syslog_Warning: //RES_PRINTA_WARN(m_pLogger, SysLogNode, "SysLog"); //mLog::Warn("SysLog {$}", SysLogNode.encode()); break; case Syslog_Error: //RES_PRINTA_ERROR(m_pLogger, SysLogNode, "SysLog"); //mLog::FERROR("SysLog {$}", SysLogNode.encode()); break; case Syslog_Fatal: //RES_PRINTA_FATAL(m_pLogger, SysLogNode, "SysLog"); //mLog::FINFO("SysLog {$}", SysLogNode.encode()); break; default: //mLog::FINFO("SysLog {$}", SysLogNode.encode()); break; } return RET_SUCCEED; } RET_STATUS ModuleDevice::Request(ResDataObject PARAM_IN* pRequest, ResDataObject PARAM_OUT* pResponse) { INT ret = RET_NOSUPPORT; PACKET_CMD cmd = PacketAnalizer::GetPacketCmd(pRequest); PACKET_TYPE type = PacketAnalizer::GetPacketType(pRequest); string keystr = PacketAnalizer::GetPacketKey(pRequest); ResDataObject Context; if (PacketAnalizer::GetPacketContext(pRequest, Context) == false) { return RET_FAILED; } ResDataObject resReponse; if (type == PACKET_TYPE_NOTIFY) { //通知类,不需要答复 return RET_SUCCEED; } else if (type == PACKET_TYPE_RES) { //收到了应答包。。。 return RET_SUCCEED; } if (cmd == PACKET_CMD_EXE) { string req, res; req = (const char*)Context.encode(); //mLog::FINFO("Action[{$}].req:{$}", keystr.c_str(), req.c_str()); ret = DevAction("", keystr.c_str(), req.c_str(), resReponse); pResponse->update("CONTEXT", resReponse); //mLog::FINFO("Action res packet done"); } else if (cmd == PACKET_CMD_GET) { string res; //mLog::FINFO("get CMD_GET req:{$}", keystr.c_str()); ret = DevGet(m_strCCOSDevicePath.c_str(), keystr.c_str(), resReponse); pResponse->update("CONTEXT", resReponse); } else if (cmd == PACKET_CMD_UPDATE) { //mLog::FINFO("get CMD_UPDATE req:{$}", keystr.c_str()); ret = DevUpdate(m_strCCOSDevicePath.c_str(), keystr.c_str(), Context, resReponse); pResponse->update("CONTEXT", resReponse); } else if (cmd == PACKET_CMD_SET) { //mLog::FINFO("get CMD_UPDATE req:{$}", keystr.c_str()); ret = DevSet(m_strCCOSDevicePath.c_str(), keystr.c_str(), Context, resReponse); pResponse->update("CONTEXT", resReponse); } else if (cmd == PACKET_CMD_MSG) { //mLog::FINFO("get CMD_UPDATE req:{$}", keystr.c_str()); ret = DevMessage(m_strCCOSDevicePath.c_str(), keystr.c_str(), Context, resReponse); pResponse->update("CONTEXT", resReponse); } else if (cmd == PACKET_CMD_ADD) { //mLog::FINFO("get CMD_ADD req:{$}", keystr.c_str()); ret = DevAdd(m_strCCOSDevicePath.c_str(), keystr.c_str(), Context, resReponse); pResponse->update("CONTEXT", resReponse); } else if (cmd == PACKET_CMD_DEL) { //mLog::FINFO("get CMD_DEL req:{$}", keystr.c_str()); ret = DevDel(m_strCCOSDevicePath.c_str(), keystr.c_str(), Context, resReponse); pResponse->update("CONTEXT", resReponse); } else { //wtf?? 忽略掉 return RET_SUCCEED; } PacketAnalizer::MakeRetCode((RET_STATUS)ret, pResponse); return (RET_STATUS)ret; } RET_STATUS ModuleDevice::CmdToLogicDev(ResDataObject PARAM_IN* pCmd) { return RET_SUCCEED; } bool ModuleDevice::GetDeviceType(GUID& DevType) { return true; } void ModuleDevice::SubscribeSelf() { LogicDevice::SubscribeSelf(); } bool ModuleDevice::CheckSubDevice() { //mLog::FINFO("Begin"); //mLog::FINFO("{$} have {$} SubDevices", m_strCCOSDevicePath, m_subCcosDevices.size()); if (m_subCcosDevices.size() > 0) { //有子设备,则构建模型设备树 ResDataObject resSub; ResDataObject subList; for (int y = 0; y < m_subCcosDevices.size(); y++) { subList.add(m_subCcosDevices[y]->GetCcosRootPath().c_str(), ""); //mLog::FINFO("{$} devpath {$}", y, m_subCcosDevices[y]->GetCcosRootPath()); } resSub.add("Value", subList); resSub.add("DescKey", "SubDevice"); m_resProperties.update("SubDevice", resSub); return true; } return false; } void ModuleDevice::OnSetClientID() { //这里根据 CCOS设备 路径决定加载什么配置 LogicDevice::OnSetClientID(); string configName; if (m_strModuleFileName.length() <= 0) { //标准设备 string devicePath = m_strCCOSDevicePath; //CCOS/DEVICE, 11个字符 if (devicePath.substr(0, 11) == "CCOS/DEVICE") { //是设备 //todo 要生成模型文件名 string module = devicePath.substr(12); configName = module; int x, moduleLen,spCount = 0; for (x = 0; x < module.length(); x++) { if (module[x] == '/') { if(spCount <= 3) module[x] = '_'; configName[x] = '_'; spCount++; if (spCount == 3) { moduleLen = x; } } } module = module.substr(0, moduleLen); module += ".json"; m_strModuleFileName = module; configName += ".json"; } } else { configName = m_strModuleFileName; } if (m_strModuleFileName.length() <= 0) { //没有取到模型名 return; } if (m_bSendIndependently) { m_strSendClientID = m_strClientID + "_Sender"; std::cout << " ModuleDevice::OnSetClientID New Connection.." << endl; m_pSendConn = NewConnection(m_strServer.c_str(), m_strServerPort.c_str(), m_strMqttUser.c_str(), m_strMqttPassword.c_str(), m_strSendClientID.c_str(), [this](ResDataObject* req, const char* topic, void* conn) { //mLog::FINFO("Got msg from [$] body: {$}", topic, req->encode()); //CmdToLogicDev(req); }); } string tmplPath, modulePath = GetProcessDirectory(); modulePath += "/DriverDefine/"; tmplPath = modulePath; string configPath = modulePath ; modulePath += m_strModuleFileName; configPath += "Config/"; mkdir(configPath.c_str(), 0755); configPath += configName; try { m_resModuleConfig.loadFile(modulePath.c_str()); m_strModuleFilePath = modulePath; //mLog::FINFO("Got module file [{$}] Read file path [{$}] ok.", m_strModuleFileName, modulePath); } catch (...) { //mLog::FINFO("Got module file [{$}] but Read file path [{$}] failed.", m_strModuleFileName, modulePath); //没有配置模型文件,尝试寻找通用模型文件 std::vector devVec; SplitCcosDevicePath(m_strCCOSDevicePath, devVec); if (devVec.size() >= 3) { string type = devVec[2]; tmplPath += type; tmplPath += ".json"; try { ResDataObject resTest; resTest.loadFile(tmplPath.c_str()); std::filesystem::copy_file( tmplPath, // 源文件路径 modulePath, // 目标文件路径 std::filesystem::copy_options::overwrite_existing // 覆盖已存在文件 ); // mLog::FINFO("Copied template module file from {$} to {$}", tmplPath, modulePath); m_resModuleConfig.loadFile(modulePath.c_str()); m_strModuleFilePath = modulePath; } catch (const std::exception& e) { // 捕获标准异常 // mLog::FERROR("File operation failed: {$}", e.what()); // mLog::FINFO("There is still no template module file {$}", tmplPath); return; } catch (...) { // 保留捕获所有异常的兜底逻辑 // mLog::FINFO("There is still no template module file {$}", tmplPath); return; } } else return; } if (configName.length() > 0) { try { ResDataObject resConfig; resConfig.loadFile(configPath.c_str()); m_resProperties = resConfig[0]; m_strConfigFilePath = configPath; if (CheckSubDevice()) { SaveToConfigFile(); } //mLog::FINFO("Got config file path [{$}] Read content ok. [{$}]", m_strConfigFilePath, m_resProperties.encode()); } catch (...) { //没有取到配置,则保存默认配置 m_strConfigFilePath = configPath; ResDataObject resConfig; m_resProperties = m_resModuleConfig["Get"]; CheckSubDevice(); resConfig.add("CONFIGURATION", m_resProperties); resConfig.SaveFile(m_strConfigFilePath.c_str()); //mLog::FINFO("No config file at path [{$}] Save content ok. [{$}]", m_strConfigFilePath, m_resProperties.encode()); } } else { m_resProperties = m_resModuleConfig["Get"]; } //mLog::FINFO("Module Content: {$}", m_resModuleConfig.encode()); //{ // ResDataObject points = m_resProperties["ABSCurve"]["Value"]["Curve1"]["Points"]; // for (int x = 0; x < points.size(); x++) // { // //mLog::FINFO("Array ? [{$}] value {$}", points.GetKey(x), points[x].encode()); // } //} if(m_resModuleConfig.GetKeyCount("Get") > 0) m_resGets = m_resModuleConfig["Get"]; if (m_resModuleConfig.GetKeyCount("Set") > 0) m_resSets = m_resModuleConfig["Set"]; if (m_resModuleConfig.GetKeyCount("Add") > 0) m_resAdds = m_resModuleConfig["Add"]; if (m_resModuleConfig.GetKeyCount("Del") > 0) m_resDels = m_resModuleConfig["Del"]; if (m_resModuleConfig.GetKeyCount("Update") > 0) { //mLog::FINFO("WHAT ? {$}", m_resModuleConfig["Update"].encode()); m_resUpdates = m_resModuleConfig["Update"]; } if (m_resModuleConfig.GetKeyCount("Action") > 0) m_resActions = m_resModuleConfig["Action"]; } RET_STATUS ModuleDevice::SendNotify(ResDataObject* pCmd) { RET_STATUS ret = RET_FAILED; if (m_bSendIndependently && m_pSendConn != nullptr) { PACKET_CMD cmd = PacketAnalizer::GetPacketCmd(pCmd); PACKET_TYPE type = PacketAnalizer::GetPacketType(pCmd); if (type == PACKET_TYPE_NOTIFY) { CcosDevFileHandle* pHandle = new CcosDevFileHandle; PacketAnalizer::UpdateNotifyHandle(*pCmd, *pHandle); //mLog::FINFO("Notify Transaction: {$}", m_strCurTransaction); PacketAnalizer::UpdatePacketTransaction(*pCmd, m_strCurTransaction); ; if (m_strEBusRoot.length() <= 0) { //mLog::FINFO("EBusRoot is null"); } //服务使用 m_pMqttConntion 区分子系统设备 PacketAnalizer::UpdateDeviceNotifyResponse(*pCmd, getLocalMachineId(), getLocalEbusId(), (UINT64)getpid(), (UINT64)m_pMqttConntion); //mLog::FINFO("[{$}] Notify: {$}", m_strSendClientID, pCmd->encode()); //printf("--> %s \n", pCmd->encode()); PacketAnalizer::UpdatePacketTopic(pCmd, (m_strEBusRoot + "/Notify").c_str(), m_strSendClientID.c_str()); PublishAction(pCmd, (m_strEBusRoot + "/Notify").c_str(), m_pSendConn); string strNotifyPath = "/Notify/" + PacketAnalizer::GetPacketKey(pCmd); PacketAnalizer::UpdatePacketTopic(pCmd, (m_strCCOSDevicePath + strNotifyPath).c_str(), m_strSendClientID.c_str()); PublishAction(pCmd, (m_strCCOSDevicePath + strNotifyPath).c_str(), m_pSendConn); if (m_strAbstractPath.length() > 0) { PublishAction(pCmd, (m_strAbstractPath + strNotifyPath).c_str(), m_pSendConn); string realPath, devPath; devPath = m_strAbstractPath.substr(((string)"CCOS/DEVICE").length()); for (int x = 0; x < m_rsOnlineGroup.size(); x++) { if ((int)m_rsOnlineGroup[x] == 1) { realPath = "CCOS/" + (string)m_rsOnlineGroup.GetKey(x) + devPath + strNotifyPath; PublishAction(pCmd, realPath.c_str(), m_pSendConn); } } } //m_pPacketSendingQue->InQueue(*pCmd); delete pHandle; } return RET_SUCCEED; } else { CmdFromLogicDev(pCmd); } return ret; } RET_STATUS ModuleDevice::NotifyProperty(const char* property) { RET_STATUS ret = RET_SUCCEED; ResDataObject resValue; if (m_resProperties.GetKeyCount(property) > 0 && m_resProperties[property].GetKeyCount("Value") > 0) { resValue = m_resProperties[property]["Value"]; ResDataObject notify; PacketAnalizer::MakeNotify(notify, PACKET_CMD_UPDATE, property, resValue.encode()); PacketAnalizer::UpdatePacketContext(notify, resValue); SendNotify(¬ify); return ret; } return RET_NOSUPPORT; } RET_STATUS ModuleDevice::GetDeviceResource(ResDataObject PARAM_OUT* pDeviceResource) { //父类会生成Ations LogicDevice::GetDeviceResource(pDeviceResource); //ResDataObject getPerp = m_resModuleConfig["Get"]; for (int x = 0; x < m_resProperties.size(); x++) { (*pDeviceResource)["Attribute"].update(m_resProperties.GetKey(x), m_resProperties[x]["Value"]); } /*/ { ResDataObject resAll; DevGet("", "", resAll); for (int x = 0; x < resAll.size(); x++) (*pDeviceResource)["Attribute"].update(resAll.GetKey(x), resAll[x]["Value"]); } //*/ pDeviceResource->update("ClientType", DPC_UnitClient); pDeviceResource->add("Get", m_resProperties); ResDataObject setPerp, updatePerp, addPerp, delPerp, actionPerp, msgPerp; if (m_resSets.size() <= 0) setPerp = m_resModuleConfig["Set"]; else setPerp = m_resSets; pDeviceResource->add("Set", setPerp); if (m_resUpdates.size() <= 0) updatePerp = m_resModuleConfig["Update"]; else updatePerp = m_resUpdates; pDeviceResource->add("Update", updatePerp); if (m_resAdds.size() <= 0) addPerp = m_resModuleConfig["Add"]; else addPerp = m_resAdds; pDeviceResource->add("Add", addPerp); if (m_resDels.size() <= 0) delPerp = m_resModuleConfig["Del"]; else delPerp = m_resDels; pDeviceResource->add("Del", delPerp); actionPerp = m_resModuleConfig["Action"]; for (int x = 0; x < actionPerp.size(); x++) { (*pDeviceResource)["Action"].update(actionPerp.GetKey(x), actionPerp[x]); } //msgPerp = m_resModuleConfig["Message"]; return RET_SUCCEED; } /// /// 枚举配置项,level == "Public" ,仅返回Pulic /// level == "E-COM" ,返回 Public 和 E-COM /// level == "Private" , 返回所有 /// /// 三个固定常量字符串 "Public"/"E-COM"/"Private" /// /// RET_STATUS ModuleDevice::GetUpdatableItems(string level, ResDataObject& resItems) { ResDataObject resUpdate; resUpdate = m_resModuleConfig["Update"]; bool bOutput = false; for (int x = 0; x < resUpdate.size(); x++) { bOutput = false; string itemLevel; if (resUpdate[x].GetKeyCount("Level") > 0) { itemLevel = (const char*)resUpdate[x]["Level"]; if (itemLevel == level) bOutput = true; else { if (level == "Private") { bOutput = true; } else if (level == "E-COM") { if (itemLevel == "Public" || itemLevel == "E-COM") { bOutput = true; } } } } else { //没有配置Level是Private if (level == "Private") bOutput = true; } if (bOutput) { resItems.update(resUpdate.GetKey(x), resUpdate[x]); } } return RET_SUCCEED; } /// /// 标准模型 是整体更新,如果是局部更新,需要重载自己写逻辑 /// /// /// /// /// RET_STATUS ModuleDevice::UpdateItem(const char* pszProperty, const char* pszValueUpdate, ResDataObject& resRespons) { //保存到配置文件 // ResDataObject resNewValue = m_resProperties[pszProperty]; ResDataObject resUpdate; try { resUpdate.decode(pszValueUpdate); } catch (...) { resUpdate = pszValueUpdate; } if (resUpdate.size() > 0) { //是个对象字典 for (int x = 0; x < resUpdate.size(); x++) { ResDataObject resv = resUpdate[x]; if (resv.size() > 0) { //key: value (有值)更新 resNewValue["Value"].update(resUpdate.GetKey(x), resUpdate[x]); } else { string value = (const char*)resv; if (value.length() > 0) { resNewValue["Value"].update(resUpdate.GetKey(x), resUpdate[x]); } else { //if (value == "Remove") //{ resNewValue["Value"].eraseAllOf(resUpdate.GetKey(x)); //} } } //resNewValue["Value"].update(resUpdate.GetKey(x), resUpdate[x]); } //mLog::FINFO("Save Object [{$}] new value {$}", pszProperty, resNewValue.encode()); m_resProperties.update(pszProperty, resNewValue); //通知模型对象,值更新了 return OnUpdate(pszProperty, m_resProperties[pszProperty]["Value"].encode(), resRespons); } else { resNewValue.update("Value", pszValueUpdate); //mLog::FINFO("Save [{$}] new value {$}", pszProperty, pszValueUpdate); m_resProperties[pszProperty].update("Value", pszValueUpdate); //通知模型对象,值更新了 return OnUpdate(pszProperty, pszValueUpdate, resRespons); } } RET_STATUS ModuleDevice::OnMessage(const char* pszTopic, const char* pszMessageValue, ResDataObject& resResponse) { //mLog::FINFO("Message to {$} with {$}", pszTopic, pszMessageValue); return RET_SUCCEED; } RET_STATUS ModuleDevice::DevGet(const char* pszDevUri, const char* pszProperty, ResDataObject& resRespons) { string property = pszProperty; if (property.length() <= 0) { string key; for (int x = 0; x < m_resProperties.size(); x++) { key = m_resProperties.GetKey(x); if (GetItem(key.c_str(), resRespons) == RET_SUCCEED) { if (m_resProperties[x].GetKeyCount("Type") > 0 && string((const char*)m_resProperties[x]["Type"]) == "Switch") { string v = (const char*)resRespons; if (v == "YES" || v == "NO") { m_resProperties[key.c_str()].update("Value", v=="YES"?"1":"0"); } else { m_resProperties[key.c_str()].update("Value", resRespons); } } else { m_resProperties[key.c_str()].update("Value", resRespons); } } } resRespons = m_resProperties; ResDataObject resMa,resMa2; //"": "Public", // "DescKey" : "TUBEHEAT", // "Value" : "0" resMa.add("Level", "Public"); resMa.update("DescKey", "Manufacturer"); resMa.update("Value", m_resModuleConfig["Manufacturer"]); resRespons.update("Manufacturer", resMa); resMa2.clear(); resMa2.add("Level", "Public"); resMa2.update("DescKey", "Model"); resMa2.update("Value", m_resModuleConfig["Model"]); resRespons.update("Model", resMa2); resMa2.clear(); resMa2.add("Level", "Public"); resMa2.update("DescKey", "Modality"); resMa2.update("Value", m_resModuleConfig["Modality"]); resRespons.update("Modality", resMa2); return RET_SUCCEED; } bool canGet = m_resGets.GetKeyCount(pszProperty) > 0; canGet &= m_resProperties.GetKeyCount(pszProperty) > 0; if (!canGet) return RET_NOSUPPORT; if (GetItem(pszProperty, resRespons) == RET_SUCCEED) { m_resProperties[pszProperty].update("Value", resRespons); } resRespons = m_resProperties[pszProperty]["Value"]; return RET_SUCCEED; } RET_STATUS ModuleDevice::DevSet(const char* pszDevUri, const char* pszProperty, const char* pszValueSet, ResDataObject& resRespons) { bool canGet = m_resSets.GetKeyCount(pszProperty) > 0; canGet &= m_resProperties.GetKeyCount(pszProperty) > 0; if (!canGet) return RET_NOSUPPORT; ResDataObject resNewValue; resNewValue.decode(pszValueSet); RET_STATUS ret = SetItem(pszProperty, resNewValue, resRespons); if (ret == RET_SUCCEED) { m_resProperties[pszProperty].update("Value", resNewValue); NotifyProperty(pszProperty); } //通知模型对象,值更新了 return ret; } RET_STATUS ModuleDevice::SaveToConfigFile() { RET_STATUS ret = RET_FAILED; if (m_strConfigFilePath.length() > 0) { ResDataObject resConfig; //m_resProperties = m_resModuleConfig["Get"]; resConfig.add("CONFIGURATION", m_resProperties); if (resConfig.SaveFile(m_strConfigFilePath.c_str())) { //mLog::FINFO("Save Module Config file [{$}] content {$}", m_strConfigFilePath, resConfig.encode()); } else { //mLog::FINFO("Failed Save Module Config file [{$}] content {$}", m_strConfigFilePath, resConfig.encode()); } ret = RET_SUCCEED; } return ret; } RET_STATUS ModuleDevice::DevUpdate(const char* pszDevUri, const char* pszProperty, const char* pszValueUpdate, ResDataObject& resRespons) { string strProperty = pszProperty; if (strProperty.length() == 0) { //查询可以更新的属性 string level = pszValueUpdate; if (level.length() <= 0) level = "Public"; if (level == "Public" || level == "E-COM" || level == "Private") { // return GetUpdatableItems(level, resRespons); } level = "Public"; return GetUpdatableItems(level, resRespons); } bool canGet = m_resUpdates.GetKeyCount(pszProperty) > 0; canGet &= m_resProperties.GetKeyCount(pszProperty) > 0; if (!canGet) return RET_NOSUPPORT; if (strProperty == "RestoreConfig") { //恢复出厂设置 } RET_STATUS ret = UpdateItem(pszProperty, pszValueUpdate, resRespons); //mLog::FINFO("UpdateItem to Device [{$}] ret [{$}]", pszProperty, (int)ret); m_resModuleConfig.update("Get", m_resProperties); SaveToConfigFile(); return ret; } RET_STATUS ModuleDevice::DevAdd(const char* pszDevUri, const char* pszProperty, const char* pszValueAdd, ResDataObject& resRespons) { bool canGet = m_resAdds.GetKeyCount(pszProperty) > 0; canGet &= m_resProperties.GetKeyCount(pszProperty) > 0; if (!canGet) return RET_NOSUPPORT; ResDataObject resNewValue; resNewValue.decode(pszValueAdd); for (int x = 0; x < resNewValue.size(); x++) { m_resProperties[pszProperty].update(resNewValue.GetKey(x), resNewValue[x]); } //m_resProperties.update(pszProperty, resNewValue); return OnAdd(pszProperty, resNewValue, resRespons); } RET_STATUS ModuleDevice::DevDel(const char* pszDevUri, const char* pszProperty, const char* pszValueDel, ResDataObject& resRespons) { bool canGet = m_resDels.GetKeyCount(pszProperty) > 0; canGet &= m_resProperties.GetKeyCount(pszProperty) > 0; if (!canGet) return RET_NOSUPPORT; ResDataObject resDelValue; string strDel = pszValueDel; if (strDel.length() < 0) { //什么参数都没有,清除所有数据 m_resProperties[pszProperty].clear(); return OnDel(pszProperty, resDelValue, resRespons); } resDelValue.decode(pszValueDel); string key = pszProperty; if (key == "ErrorList") { //如果是ErrorList,提供单独删除某类错误的能力 int nIndex = resDelValue.GetFirstOf("ErrorIndex"); if (nIndex >= 0) { nIndex = (int)resDelValue["ErrorIndex"]; if (nIndex >= 0 && nIndex < (m_resProperties[key.c_str()]).size()) { //m_resProperties[key.c_str()].eraseOneOf() } } } if (RET_SUCCEED == OnDel(pszProperty, resDelValue, resRespons)) { m_resProperties.update(pszProperty, resRespons); return RET_SUCCEED; } return RET_SUCCEED; } RET_STATUS ModuleDevice::DevAction(const char* pszDevUri, const char* pszActionName, const char* pszParams, ResDataObject& resRespons) { cout << "ModuleDevice::DevAction - Entering. pszDevUri: " << (pszDevUri ? pszDevUri : "nullptr") << ", pszActionName: " << (pszActionName ? pszActionName : "nullptr") << ", pszParams: " << (pszParams ? pszParams : "nullptr") << endl; bool canGet = m_resActions.GetKeyCount(pszActionName) > 0; if (!canGet) return RET_NOSUPPORT; RET_STATUS ret = OnAction(pszActionName, pszParams, resRespons); //mLog::FINFO("Got Action {$} with param {$} to {$} ret {$} Result {$}", pszActionName, pszDevUri, pszParams, (int)ret, resRespons.encode()); return ret; } RET_STATUS ModuleDevice::DevMessage(const char* pszDevUri, const char* pszTopic, const char* pszMessageValue, ResDataObject& resRespons) { return OnMessage(pszTopic, pszMessageValue, resRespons); } RET_STATUS ModuleDevice::OnUpdate(const char* pszProperty, const char* pszValueUpdate, ResDataObject& resRespons) { RET_STATUS ret = RET_NOSUPPORT; return ret; } RET_STATUS ModuleDevice::OnDel(const char* pszPropery, ResDataObject& resDelValue, ResDataObject& resResponse) { RET_STATUS ret = RET_NOSUPPORT; return ret; } RET_STATUS ModuleDevice::OnAdd(const char* pszPropery, ResDataObject& reAddValue, ResDataObject& resResponse) { RET_STATUS ret = RET_NOSUPPORT; return ret; } RET_STATUS ModuleDevice::SetItem(const char* pszPropery, ResDataObject& resSetValue, ResDataObject& resResponse) { RET_STATUS ret = RET_NOSUPPORT; return ret; } RET_STATUS ModuleDevice::GetItem(const char* pszPropery, ResDataObject& resResponse) { RET_STATUS ret = RET_NOSUPPORT; return ret; } RET_STATUS ModuleDevice::OnAction(const char* pszActionName, const char* pszParams, ResDataObject& resResponse) { RET_STATUS ret = RET_NOSUPPORT; string strAction = pszActionName; if (strAction == "RestoreConfig") { //恢复出厂设置 m_resProperties = m_resModuleConfig["Get"]; SaveToConfigFile(); ret = RET_SUCCEED; } return ret; }