\mainpage OneNetPost应用 \section note1 整体说明 本应用实现: - 监控主机采集原始数据及报警数据上传onenet移动云平台 - 传感器在OneNet平台注册设备。 - Http请求数据上传 \section note2 功能模块 本应用划分为以下模块: - 应用框架模块 - 授权检查 - 检查设备注册状态 - 注册设备 - 数据上传 \section note3 修改日志 \page pageLog 修改日志 \section log2 20170508 修正 20170508 \section log1 20170508 \page pageApp 应用框架模块 \section app1-1 基本功能 检查设备配置,授权处理,注册设备 \section app1-2 设计 - 通用上传数据基类-》应用实现类 - 配置管理对象 读取ini文件形式,可随时扩展修改。 - 工作线程 - 消息机制 支持消息响应 - 守护机制 定时发消息到守护进程,异常中断阻塞或退出,由守护进程自动运行 - 日志记录 支持日志记录,通过global.h文件全局变量打开/关闭或日志模式 \section app1-3 流程 \page post OneNeT授权模块 \section accredit1-1 基本功能 功能描述 - 实现对设备的授权管理 \section accredit1-2 设计 - 读取设备授权码,对设备授权进行授权 \section accredit1-3 流程 (1) 读取设备授权信息 (2) 是否授权,否跳到(3),是跳到(5) (3) 试用期, 到期?是退出,否跳到(4) (4) 初始化执行程序,采集数据 (5) 授权已过期?是退出,否跳到(4) \section accredit1-4 注意 注意事项: - 及时判断设备授权是否过期 \section accredit1-5 示例 示例参考 \page post OneNeT检查注册模块 \section accredit1-1 基本功能 功能描述 - 实现对设备注册检查是否注册判断 \section accredit1-2 设计 - 请求核对设备注册情况 - 对设备进行标记 \section accredit1-3 流程 (1) 加载设备 (2) 遍历设备对列 (3) 判断设备是否注册,否跳到(6),是跳到(4) (4) 判断设备信息是否更新,是跳到(5),否转(2) (5) OneNet设备发出http请求,跳到(7) (6) 向OneNet注册设备 (7) 判断遍历设备是否完成,是退出,否跳到(2) \section accredit1-4 注意 注意事项: - 对设备注册进行唯一性核查 \section accredit1-5 示例
int COneNetPost::OneNet_CheckDeviceRegist(void) { std::map\page postReg OneNET注册模块 \section reg1-1 基本功能 功能描述 - 使用POST方法向OneNet平台注册设备。 - 设备注册成功后自动向数据中插入注册的设备信息,以便在下次启动时更好地检查设备注册情况。 \section reg1-2 设计 - 检查配置的传感器是否已向OneNet平台注册,若没有注册则向平台注册设备 - 已经注册向OneNet平台更新设备信息 - 没有注册,向OneNet平台注册注册设备 - 参考 OneNET devices \section reg1-3 流程 (1) 加载设备 (2) 遍历注册设备对列 (3) 向平台发出删除设备 (4) 删除本地设备注册信息 (5) 设备遍历完成?,否转到(2),是转到(6) (6) 检查设备注册状态 (7) 退出 \section reg1-4 注意 注意事项: - 注册前先检查设备是否已经注册 - 设备有更新要及时更新数据库 \section reg1-5 示例 示例参考 //向平台注册注册设备::iterator itPostItem = m_PostItem.begin(); std::map ::iterator it; for (; itPostItem != m_PostItem.end(); itPostItem++) { it = m_PostDevice.find(iSid); if (it == m_PostDevice.end())//设备未注册 { OneNet_RegistDevice(itPostItem->second); } } return m_PostDevice.size(); }
int COneNetPost::OneNet_RegistDevice(TPostMsgItem& item) { char postdata[_BUF1K]; //Post数据输入缓冲区,用于向平台发送Post数据 char outdata[_BUF2K]; //Post数据输出缓冲区,用于存储平台返回的数据 long outlen = 0; //Post返回数据长度,用于记录平台返回的数据大小 int iSid = item.Sid; int iKind = item.Kind; int iDevId = 0; std::string sDevApiKey; std::string sUrl; std::string sUrlHeader; cJSON *nd = NULL; cJSON *json = NULL; cJSON *child = NULL; //注册设备 sUrl = Format("http://%s:%d/register_de?register_code=%s", m_sPostHost.c_str(), m_iPostPort, m_PostRegCode[item.SubSys].c_str());//URL sUrlHeader=Format("");//Http头 if (iSid > 0) sprintf(postdata, "{\"sn\": \"%s-%d\"}", m_sMacID.c_str(), iSid); else sprintf(postdata, "{\"sn\": \"%s\"}", m_sMacID.c_str()); if (DoHttpRequest(sUrl.c_str(), sUrlHeader.c_str(), postdata, outdata, &outlen) <= 0) { return 0; } //处理返回数据 json = cJSON_Parse((const char*)outdata); nd = cJSON_GetObjectItem(json, "error"); int res = 0; if (strcmp(nd->valuestring, "succ") != 0) { cJSON_Delete(json); return 0; } child = cJSON_GetObjectItem(json, "data"); nd = cJSON_GetObjectItem(child, "device_id");//取得设备ID iDevId = atol(nd->valuestring); nd = cJSON_GetObjectItem(child, "key");//取得设备ApiKey sDevApiKey = nd->valuestring; strcpy(item.ApiKey, nd->valuestring); item.DevID = iDevId; m_PostDevice[iSid] = item; sprintf(postdata, "insert into tbRegDevDef(DevID, SID, Kind, Type, SubSys, Name, Note, ApiKey, Mask, Ext0, Ext1) \ values(%d, %d, %d, %d, %d, '%s', '%s', '%s', 0, 0, 0)", item.DevID, item.Sid, item.Kind, item.Type, item.SubSys, item.Name, item.ANote, item.ApiKey); m_dbCfg->execDML(postdata); cJSON_Delete(json); //更新设备信息 OneNet_UpdateDeviceInfo(item); return 1; }\page postOneNet OneNeT上传模块 \section post1-1 基本功能 功能描述 - 传感器数据上传 - 报警数据上传 \section post1-2 设计 - 遍历查表 - 查询数据 - 上传数据 - 参考 OneNeT datapoints \section post1-3 流程 (1) 获取设备列表 (2) 遍历设备数据记录 (3) 检查数据是否更新?,否转(2),是转(4) (4) 有数据更新http请求数据上传 (5) 判断是否遍历完成?,是转到(6),否转(2) (6) 结束 \section post1-4 注意 注意事项 - 检查表格是否存在 - 检查数据是否更新 - 数据上传是否成功 \section post1-5 示例 示例参考 //上传传感器数据
std::map::iterator itPostItem = m_PostItem.begin(); std::map ::iterator itDateUpd; for (; itPostItem != m_PostItem.end(); itPostItem++)//遍历 { itDateUpd = m_PostDateUpd.find(itPostItem->second.Sid); //数据更新时间 if (itDateUpd == m_PostDateUpd.end())//没有相关更新记录 continue; sTable = m_PostDbTabName[iType]; if (m_dbDat->tableExists(sTable.c_str()))//数据表存在 { ssql = Format(_T("select * from %s where SID=%d"),sTable.c_str(),iSid); iqry = m_dbDat->qryExec(ssql.data()); if (!m_dbDat->qryEof(iqry)) { sDateUpd = m_dbDat->qryFieldStr(iqry, _T("DateUpd"));//数据更新时间 if (sDateUpd != itDateUpd->second)//数据有更新 { itDateUpd->second = sDateUpd; //TODO: 检查数据库是否存在并取出想应的数据,然后打包成Post数据帧 iFieldCount = m_dbDat->qryFieldCount(iqry); sprintf(postdata,"{"); for(int k=1; k qryFieldName(iqry,k), m_dbDat->qryFieldInt(iqry, _T(m_dbDat->qryFieldName(iqry, k)))); strcat(postdata, abuf); } strcat(postdata,"}"); sUrl = Format("http://%s:%d/devices/%ld/%s", m_sPostHost.c_str(), m_iPostPort, m_PostDevice[iSid].DevID, m_sPostPath.c_str()); sUrlHeader=Format("api-key:%s", m_PostApiKey[itPostItem->second.SubSys].c_str()); if (DoHttpRequest(sUrl.c_str(), sUrlHeader.c_str(), postdata, outdata, &outlen) <= 0) { ; } } } m_dbDat->qryFinalize(iqry); } _sleep(1); }