#include "stdafx.h" #include "LNHandle.h" #include #include "AppService.h" #include "Device.h" #include #include "MonitorObject.h" #include "MGWSServer.h" #include "ResistAlarm.h" #include <315ClientManager.h> using namespace rapidjson; CLNHandle::CLNHandle() { m_bWork = true; m_pThread = new std::thread(ThreadForHandle, (DWORD_PTR)this); } CLNHandle::~CLNHandle() { } BOOL CLNHandle::HandlePack(LPBYTE pPack, int nPackLen, SOCKADDR* psa, void* pClientContext /*= NULL*/) { CLNContext* pContext = (CLNContext*)pClientContext; if (pPack == nullptr || nPackLen == 0) { if (pContext) { pContext->SetIPAdress(); CString strLog; strLog.Format(_T("CZHGSHandle 有新的链接:%s"), pContext->GetIPAdressNew()); TRACE("%s\r\n", CStringA(strLog)); SPDLOG_INFO(strLog); } return TRUE; } CString strIp; if (psa) { SOCKADDR_IN* addr = (SOCKADDR_IN*)psa; strIp.Format("%s:%d", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port)); } else if (pContext) { strIp = pContext->GetIPAdressNew(); } uint8_t ch_head = (uint8_t)pPack[0]; uint8_t ch_tail = (uint8_t)pPack[nPackLen - 1]; if (ch_head != '{' || ch_tail != '}') { CString strLog; strLog.Format("[%s][%s]数据格式非JSON,丢弃!长度(%d): ", (LPCSTR)strIp, psa ? "UDP" : "TCP", nPackLen); CSimpleLog::Error(strLog + CSimpleLog::GetHexStringWithNoSpace(pPack, nPackLen)); return FALSE; } if (g_bLog) CSimpleLog::Info("收到(" + strIp + ")(" + to_string(nPackLen).c_str() + "):" + CString((char*)pPack, nPackLen)); lock_guard lock(m_mtx); m_lst.emplace_back(new tagHandlePack(pPack, nPackLen, psa, pContext)); return TRUE; } BOOL CLNHandle::ProcessPack(LPBYTE pPack, int nPackLen, SOCKADDR* psa, CLNContext* pClientContext) { CLNContext *pContext = (CLNContext*)pClientContext; Document doc; if (doc.Parse((char*)pPack, nPackLen).HasParseError() || doc.HasMember("cmd") == false || doc["cmd"].IsString() == false) { CString strLog; strLog.Format("[设备]数据JSON格式解析错误!丢弃.长度(%d):", nPackLen); CSimpleLog::Error(strLog + CSimpleLog::GetHexString(pPack, nPackLen)); return FALSE; } //KEY区分大小写 if (doc.HasMember("IMEI") == false || doc["IMEI"].IsString() == false) { CSimpleLog::Error("[设备]IMEI解析出错!"); return FALSE; } auto cmd = doc["cmd"].GetString(); auto imei = doc["IMEI"].GetString(); if (strcmp("push_msg", cmd) == 0) return HandlePushMsg(doc, imei, psa, pContext, pPack, nPackLen); else if (strcmp("ping", cmd) == 0) return HandlePingPack(doc, imei, psa, pContext); else if (strcmp("push_info", cmd) == 0) return HandlePushInfo(doc, imei, psa, pContext); else if (strcmp("info_ack", cmd) == 0) return HandleInfoAck(doc, imei, psa, pContext); else if (strcmp("time", cmd) == 0) return HanldeTime(doc, imei, psa, pContext); else if (strcmp("update", cmd) == 0) //client return HandleUpdate(doc, imei, psa, pContext); else if (strcmp("update_ack", cmd) == 0) return HandleUpdateAck(doc, pPack, nPackLen, imei, psa, pContext); else if (strcmp("updateinit", cmd) == 0) return HandleUpdateInit(doc, imei, psa, pContext); else if (strcmp("updateseq", cmd) == 0) return HandleUpdateSeq(doc, imei, psa, pContext); else if (strcmp("updateok", cmd) == 0) return HandleUpdateOk(doc, imei, psa, pContext); else if (strcmp("get_online_new", cmd) == 0) return HandleOnlineDeviceNew(psa, pContext); else if (strcmp("get_online", cmd) == 0) return HandleOnlineDevice(doc, imei, psa, pContext); else if (strcmp("query_msg_ack", cmd) == 0) return HandleQueryMsgAck(doc, imei, psa, pContext); else if (strcmp("push_online", cmd) == 0) return HandlePushOnline(doc, imei, psa, pContext, pPack, nPackLen); else CSimpleLog::Error(CString("[设备]命令未解析:") + cmd); return TRUE; //throw std::logic_error("The method or operation is not implemented."); } BOOL CLNHandle::HandlePingPack(const rapidjson::Document& doc, const char* imei, const SOCKADDR* psa, CLNContext* pContext /*= NULL*/) { if (pContext) pContext->m_mapImei[imei]++; CTime ctNow = CTime::GetCurrentTime(); { //更新当前设备的心跳时间 auto pDevice = CDeviceMng::Instance()->Insert(imei); assert(pDevice); if (pDevice) { if (pDevice->m_ctUpdateTime < ctNow) pDevice->m_ctUpdateTime = ctNow; } } //string mo, mp; //SYSTEMTIME stNow; //ctNow.GetAsSystemTime(stNow); //if (CMonitorObjectMng::Instance()->IMEI2MOMP(imei, 0, mo, mp)) // CResistAlarmMng::Instance()->RecoverAlarm(mo, mp, -1, eZL_ALARMTYPE::EQUIP_OFFLINE, 1, stNow); //if (CMonitorObjectMng::Instance()->IMEI2MOMP(imei, 1, mo, mp)) // CResistAlarmMng::Instance()->RecoverAlarm(mo, mp, -1, eZL_ALARMTYPE::EQUIP_OFFLINE, 1, stNow); //if (CMonitorObjectMng::Instance()->IMEI2MOMP(imei, 2, mo, mp)) // CResistAlarmMng::Instance()->RecoverAlarm(mo, mp, -1, eZL_ALARMTYPE::EQUIP_OFFLINE, 1, stNow); //update CString strSql; //strSql.Format("UPDATE rm_deviceinfo SET updatetime='%s' WHERE IMEI = '%s' ", (LPCSTR)ctNow.Format("%Y-%m-%d %H:%M:%S"), imei); strSql.Format("IF EXISTS (SELECT TOP 1 * FROM rm_deviceinfo WHERE IMEI = '%s') "\ " BEGIN "\ " UPDATE rm_deviceinfo SET updatetime = '%s' WHERE IMEI = '%s' "\ " END "\ " ELSE "\ " BEGIN"\ " INSERT INTO[dbo].[rm_deviceinfo]([IMEI], [CCID]) VALUES('%s', '') "\ " END", imei, (LPCSTR)ctNow.Format("%Y-%m-%d %H:%M:%S"), imei, imei); if (!CDBConnectPool::Instance()->DBExecuteSQL(strSql)) { CSimpleLog::Error(strSql + "执行失败"); } //response StringBuffer strBuf; Writer writer(strBuf); writer.StartObject(); writer.Key("cmd"); writer.String("pong"); writer.Key("IMEI"); writer.String(imei); writer.EndObject(); string data = strBuf.GetString(); if (pContext) return pContext->Send(data.c_str(), data.length()) != SOCKET_ERROR; else if (psa) return CAppService::Instance()->GetUdpSocket()->SendTo((void*)data.c_str(), data.length(), psa, sizeof(SOCKADDR)); return FALSE; } BOOL CLNHandle::HandlePushMsg(const rapidjson::Document& doc, const char* imei, const SOCKADDR* psa, CLNContext* pContext, LPBYTE pPack, int nPackLen) { auto start_time = chrono::steady_clock::now(); int code = 200; string packnum = "0"; if (pContext) pContext->m_mapImei[imei]++; if (doc.HasMember("packnum") && doc["packnum"].IsString()) packnum = doc["packnum"].GetString(); //response { StringBuffer strBuf; Writer writer(strBuf); writer.StartObject(); writer.Key("cmd"); writer.String("push_msg_ack"); writer.Key("code"); writer.Int(code); writer.Key("IMEI"); writer.String(imei); writer.Key("packnum"); writer.String(packnum.c_str()); writer.EndObject(); string data = strBuf.GetString(); if (pContext) pContext->Send(data.c_str(), data.length()) != SOCKET_ERROR; else if (psa) CAppService::Instance()->GetUdpSocket()->SendTo((void*)data.c_str(), data.length(), psa, sizeof(SOCKADDR)); } do { //analyze string szTime; if (doc.HasMember("time") && doc["time"].IsString()) szTime = doc["time"].GetString(); else { code = 401; break; } COleDateTime odt; try { odt.ParseDateTime(szTime.c_str()); } catch (COleException*) { ASSERT(0); CSimpleLog::Error(("[设备]时间格式错误:" + szTime).c_str()); code = 401; break; } COleDateTime odtNow = COleDateTime::GetCurrentTime(); #ifndef DEBUG_202 if (strcmp(imei, "1234567890") != 0) //测试设备 { COleDateTimeSpan t(0, 0, 2, 0); COleDateTimeSpan t2(3, 0, 0, 0); time_t tmNow; time(&tmNow); if ((odtNow - odt > t2 || odtNow - odt > t || odt - odtNow > t) && tmNow - g_stStart > 20) //刚启动不下发同步, 设备有缓存 { auto doc = yyjson_mut_doc_new(nullptr); auto root = yyjson_mut_obj(doc); yyjson_mut_doc_set_root(doc, root); yyjson_mut_obj_add_str(doc, root, "cmd", "time_ack"); yyjson_mut_obj_add_int(doc, root, "timestamp", tmNow); yyjson_mut_obj_add_strcpy(doc, root, "IMEI", imei); size_t len = 0; auto json = yyjson_mut_write(doc, 0, &len); if (json) { if (pContext) pContext->Send(json, len) != SOCKET_ERROR; else if (psa) CAppService::Instance()->GetUdpSocket()->SendTo(json, len, psa, sizeof(SOCKADDR)); } yyjson_mut_doc_free(doc); doc = nullptr; CString strLog; strLog.Format("超过服务器的时间六小时:IMEI(%s) 上传时间(%s) 服务器时间(%s) 下发一条time_ack:%s", imei, (LPCSTR)odt.Format("%Y-%m-%d %H:%M:%S"), (LPCSTR)odtNow.Format("%Y-%m-%d %H:%M:%S"), json); CSimpleLog::Error(strLog); if (json) { free(json); json = nullptr; } code = 401; break; } } #endif // if (odt.m_status != COleDateTime::DateTimeStatus::valid) { ASSERT(0); CSimpleLog::Error(("[设备]收到时间无效:" + szTime).c_str()); code = 401; break; } SYSTEMTIME st; odt.GetAsSystemTime(st); CTime ctNow(st); TIMESTAMP_STRUCT ts; ts.year = st.wYear; ts.month = st.wMonth; ts.day = st.wDay; ts.hour = st.wHour; ts.minute = st.wMinute; ts.second = st.wSecond; ts.fraction = 0; string data0, data1, data2, data3, data4, data5, data6, data7, data8; if (doc.HasMember("data0") && doc["data0"].IsString()) data0 = doc["data0"].GetString(); if (doc.HasMember("data1") && doc["data1"].IsString()) data1 = doc["data1"].GetString(); if (doc.HasMember("data2") && doc["data2"].IsString()) data2 = doc["data2"].GetString(); if (doc.HasMember("data3") && doc["data3"].IsString()) data3 = doc["data3"].GetString(); if (doc.HasMember("data4") && doc["data4"].IsString()) data4 = doc["data4"].GetString(); if (doc.HasMember("data5") && doc["data5"].IsString()) data5 = doc["data5"].GetString(); if (doc.HasMember("data6") && doc["data6"].IsString()) data6 = doc["data6"].GetString(); if (doc.HasMember("data7") && doc["data7"].IsString()) data7 = doc["data7"].GetString(); if (doc.HasMember("data8") && doc["data8"].IsString()) data8 = doc["data8"].GetString(); int temperature = INT_MIN, humidity = INT_MIN; int bMakeup = 0; if (doc.HasMember("temperature") && doc["temperature"].IsString()) temperature = atof(doc["temperature"].GetString()) * 100; if (doc.HasMember("humidity") && doc["humidity"].IsString()) humidity = atof(doc["humidity"].GetString()) * 100; if (doc.HasMember("make_up") && doc["make_up"].IsInt()) bMakeup = doc["make_up"].GetInt(); //vector vctData0(ROW_ARRAY_SIZE), vctData1(ROW_ARRAY_SIZE), vctData2(ROW_ARRAY_SIZE), vctData3(ROW_ARRAY_SIZE), // vctData4(ROW_ARRAY_SIZE), vctData5(ROW_ARRAY_SIZE), vctData6(ROW_ARRAY_SIZE), vctData7(ROW_ARRAY_SIZE), vctData8(ROW_ARRAY_SIZE); vector vctData0(ROW_ARRAY_SIZE, 0), vctData1(ROW_ARRAY_SIZE, 0), vctData2(ROW_ARRAY_SIZE, 0), vctData3(ROW_ARRAY_SIZE, 0), vctData4(ROW_ARRAY_SIZE, 0), vctData5(ROW_ARRAY_SIZE, 0), vctData6(ROW_ARRAY_SIZE, 0), vctData7(ROW_ARRAY_SIZE, 0), vctData8(ROW_ARRAY_SIZE, 0); auto len0 = convertStrToArray(data0, vctData0); auto len1 = convertStrToArray(data1, vctData1); auto len2 = convertStrToArray(data2, vctData2); auto len3 = convertStrToArray(data3, vctData3); auto len4 = convertStrToArray(data4, vctData4); auto len5 = convertStrToArray(data5, vctData5); auto len6 = convertStrToArray(data6, vctData6); auto len7 = convertStrToArray(data7, vctData7); auto len8 = convertStrToArray(data8, vctData8); //转换 string mo_mp; string imei_idx = imei; int idx = 0; if (len3) idx = 1; else if (len6) idx = 2; imei_idx += "." + to_string(idx); auto bMoMp = CMonitorObjectMng::Instance()->IMEI2MOMP(imei_idx, mo_mp); if (g_strMoMp.compare(mo_mp) == 0) CSimpleLog::Info(fmt::format("{} recv data:{}", mo_mp, CString((char*)pPack, nPackLen)).c_str()); //实时温湿度分送到客户端 //auto lws_server = CAppService::Instance()->GetLwsServer(); auto mg_server = CAppService::Instance()->GetMgServer(); auto mg_315_server= g_p315ClientManager->GetTcpClient(); if (temperature != INT_MIN && humidity != INT_MIN && humidity > 0 && odt > m_mapIMEI_temp[imei]) { m_mapIMEI_temp[imei] = odt; CString strSql; strSql.Format("INSERT INTO rm_temphumidity_%04d%02d ([IMEI],[acquisitiontime],[temperature],[humidity]) "\ "VALUES('%s' , '%s' , %d , %d); ", st.wYear, st.wMonth, imei, (LPCSTR)odt.Format("%Y-%m-%d %H:%M:%S"), temperature, humidity); if (!CDBConnectPool::Instance()->DBExecuteSQL(strSql)) { CSimpleLog::Error("sql 执行失败:" + strSql); } if (mg_server) mg_server->SendHumiTemp(mo_mp, odt, humidity, temperature); uint8_t* pack = nullptr; int len = 0; if (CSuperManager::Instance()->GetSuperNum() && bMoMp) { auto no = GeneralTempPack(mo_mp, temperature, humidity, ctNow.GetTime(), &pack, &len); if (no) CSuperManager::Instance()->SendPack(pack, len, no, E_ZL_PROTOCAL::ZL_TEMP_HUMI, false); delete[] pack; pack = nullptr; } // } //#ifdef DEBUG_202 // //针对21号J1-2200以下打0.85折 // if (strcmp(imei, "860588048955283") == 0) // { // if (len2 > 0) // { // for (int i = 0; i < len2; i++) // { // if (vctData2[i] != SHORT_MIN && vctData2[i] < -2200) // { // vctData2[i] = vctData2[i] * 0.85; // } // } // } // } // //#endif // DEBUG_202 //三个为一组 if ((len0 != len1 && (len2 != len1)) || (len3 != len4 && (len4 != len5)) || (len6 != len7 && (len8 != len7)) || (len0 == 0 && len3 == 0 && len6 == 0)) { CSimpleLog::Error("解析Data len 出错"); code = 401; break; } auto pDevice = CDeviceMng::Instance()->Insert(imei); assert(pDevice != nullptr); if (pDevice == nullptr) { CSimpleLog::Fatal("insert imei fail."); code = 500; break; } BOOL bIntervalMinute = FALSE; if (pDevice->m_ctUpdateTime < ctNow) { if (ctNow - pDevice->m_ctUpdateTime >= 59) bIntervalMinute = TRUE; //距离上个数据间隔一分钟. pDevice->m_ctUpdateTime = ctNow; } else if (pDevice->m_ctUpdateTime > ctNow) pDevice->m_ctUpdateTime = ctNow - CTimeSpan(0, 0, 0, 1); int nData[3] = { INT_MIN, INT_MIN, INT_MIN }; pDevice->m_nTemperature = temperature; pDevice->m_nHumidity = humidity; //时间判断 if (len0) { #ifndef DEBUG_202 if (pDevice->m_odt_data0 >= odt) { CString strLog; strLog.Format("[设备]时间错误:上送时间:%s 设备0通道时间:%s", imei, (LPCSTR)odt.Format("%Y-%m-%d %H:%M:%S"), (LPCSTR)pDevice->m_odt_data0.Format("%Y-%m-%d %H:%M:%S")); CSimpleLog::Error(strLog); code = 401; break; } #endif // !DEBUG_202 pDevice->m_odt_data0 = odt; nData[0] = *vctData0.rbegin(); nData[1] = *vctData1.rbegin(); nData[2] = *vctData2.rbegin(); } else if (len3) { #ifndef DEBUG_202 if (pDevice->m_odt_data1 >= odt) { CString strLog; strLog.Format("[设备]时间错误:上送时间:%s 设备1通道时间:%s", imei, (LPCSTR)odt.Format("%Y-%m-%d %H:%M:%S"), (LPCSTR)pDevice->m_odt_data1.Format("%Y-%m-%d %H:%M:%S")); CSimpleLog::Error(strLog); code = 401; break; } #endif // !DEBUG_202 pDevice->m_odt_data1 = odt; nData[0] = *vctData3.rbegin(); nData[1] = *vctData4.rbegin(); nData[2] = *vctData5.rbegin(); } else if (len6) { #ifndef DEBUG_202 if (pDevice->m_odt_data2 >= odt) { CString strLog; strLog.Format("[设备]时间错误:上送时间:%s 设备2通道时间:%s", imei, (LPCSTR)odt.Format("%Y-%m-%d %H:%M:%S"), (LPCSTR)pDevice->m_odt_data2.Format("%Y-%m-%d %H:%M:%S")); CSimpleLog::Error(strLog); code = 401; break; } #endif // !DEBUG_202 pDevice->m_odt_data2 = odt; nData[0] = *vctData6.rbegin(); nData[1] = *vctData7.rbegin(); nData[2] = *vctData8.rbegin(); } else { CString str; str.Format("len error. %s:%d", __FILE__, __LINE__); CSimpleLog::Error(str); code = 401; break; } //insert auto nNum = max(max(len0, len3), len6); if (nNum == 0 || nNum > ROW_ARRAY_SIZE) { CSimpleLog::Error("Max size zero."); code = 401; break; } vector vctResult0(ROW_ARRAY_SIZE, true), vctResult3(ROW_ARRAY_SIZE, true), vctResult6(ROW_ARRAY_SIZE, true); uint32_t newlen0 = 0, newlen3 = 0, newlen6 = 0; __time64_t tmNowStart = ctNow.GetTime() * 1000; SECOND_STAT_INFO tSS1, tSS2, tSS3; if (len0) newlen0 = compressArrayNew(vctData0, vctData1, vctData2, len0, vctResult0, tmNowStart, tSS1, tSS2, tSS3); if (len3) newlen3 = compressArrayNew(vctData3, vctData4, vctData5, len3, vctResult3, tmNowStart, tSS1, tSS2, tSS3); if (len6) newlen6 = compressArrayNew(vctData6, vctData7, vctData8, len6, vctResult6, tmNowStart, tSS1, tSS2, tSS3); if (bIntervalMinute && (tSS1.dif_val >= 100 || tSS2.dif_val >= 100 || tSS3.dif_val >= 100)) SPDLOG_INFO("波动: ss1:{} ss2:{} ss3:{} {}", tSS1.dif_val, tSS2.dif_val, tSS3.dif_val, CString((char*)pPack, nPackLen)); uint32_t nNewNum = max(max(newlen0, newlen3), newlen6); //发送315前需要获取转辙机定反位 if (bMoMp && mg_315_server) { auto zzjno = CMonitorObjectMng::Instance()->GetZZJNO(mo_mp); //auto pZZJ = CMonitorObjectMng::Instance()->GetTreeByID(mo_mp); //if (pZZJ) if (zzjno > 0) { //string direct1, direct2; //CMonitorObjectMng::Instance()->GetDirectByMoMp(mo_mp, direct1, direct2); //判断0通道是定位还是反位是通过GetNameByMoMp中的name1,和 name2 string name1, name2, name3; CMonitorObjectMng::Instance()->GetNameByMoMp(mo_mp, name1, name2, name3); if (name1 == "反位") { swap(nData[0], nData[1]); } mg_315_server->SendRealDataValue(zzjno, CMonitorObjectMng::Instance()->GetZZJEPOS(mo_mp), true, nData[0], nData[1], nData[2], temperature, humidity, ctNow); } } //实时分送到客户端 if (mg_server) { uint8_t* pack = nullptr; int len = 0; if (len0) { //mo_mp 108.J1 mg_server->SendRealResistData(mo_mp, nNum, vctData0, vctData1, vctData2, vctResult0, ctNow); if (CSuperManager::Instance()->GetSuperNum() && bMoMp) { auto no = GeneralResistPack(mo_mp, nNum, vctData0, vctData1, vctData2, vctResult0, ctNow, &pack, &len); if (no) CSuperManager::Instance()->SendPack(pack, len, no, E_ZL_PROTOCAL::ZL_RESIST_DATA, false); delete[] pack; pack = nullptr; } } else if (len3) { //mo_mp 108.J2 mg_server->SendRealResistData(mo_mp, nNum, vctData3, vctData4, vctData5, vctResult3, ctNow); if (CSuperManager::Instance()->GetSuperNum() && bMoMp) { auto no = GeneralResistPack(mo_mp, nNum, vctData3, vctData4, vctData5, vctResult3, ctNow, &pack, &len); if (no) CSuperManager::Instance()->SendPack(pack, len, no, E_ZL_PROTOCAL::ZL_RESIST_DATA, false); delete[] pack; pack = nullptr; } /// } else if (len6) { //mo_mp 108.J3 mg_server->SendRealResistData(mo_mp, nNum, vctData6, vctData7, vctData8, vctResult6, ctNow); if (CSuperManager::Instance()->GetSuperNum() && bMoMp) { auto no = GeneralResistPack(mo_mp, nNum, vctData6, vctData7, vctData8, vctResult6, ctNow, &pack, &len); if (no) CSuperManager::Instance()->SendPack(pack, len, no, E_ZL_PROTOCAL::ZL_RESIST_DATA, false); delete[] pack; pack = nullptr; } } } //放在缓存当中 bool bSave = true; { if (len0) bSave = pDevice->Insert(idx, tmNowStart, 1000 / nNum, vctData0, vctData1, vctData2, vctResult0, nNum, tSS1, tSS2, tSS3, nNewNum, bMakeup); if (len3) bSave = pDevice->Insert(idx, tmNowStart, 1000 / nNum, vctData3, vctData4, vctData5, vctResult3, nNum, tSS1, tSS2, tSS3, nNewNum, bMakeup); if (len6) bSave =pDevice->Insert(idx, tmNowStart, 1000 / nNum, vctData6, vctData7, vctData8, vctResult6, nNum, tSS1, tSS2, tSS3, nNewNum, bMakeup); } if (bSave) { //申请内存 LPRESISTANCE p = new RESISTANCE[nNewNum]; if (p == nullptr) { CSimpleLog::Fatal("内存分配失败"); code = 401; break; } memset(p, 0, sizeof(RESISTANCE) * nNewNum); auto db = CDBConnectPool::Instance()->GetConnection(); COdbcStatement stmt(db); stmt.Create(); stmt.SetAttribute(SQL_ATTR_ROW_BIND_TYPE, (SQLPOINTER)sizeof(RESISTANCE), 0); stmt.SetAttribute(SQL_ATTR_PARAM_BIND_TYPE, (SQLPOINTER)sizeof(RESISTANCE), SQL_IS_INTEGER); stmt.SetAttribute(SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER)(DWORD_PTR)nNewNum, SQL_IS_INTEGER); SQLUSMALLINT ParamStatusArray[ROW_ARRAY_SIZE] = { 0 }; //设定状态数组 stmt.SetAttribute(SQL_ATTR_ROW_STATUS_PTR, ParamStatusArray, 0); SQLINTEGER nBindOffset = 0; stmt.SetAttribute(SQL_ATTR_ROW_BIND_OFFSET_PTR, (SQLPOINTER)&nBindOffset, 0); CString strSql; strSql.Format("INSERT INTO rm_resistance_%04d%02d%02d ([IMEI],[acquisitiontime],[idx],[data0],[data1],[data2]) "\ "VALUES(? , ? , ? , ? , ? , ? ); ", st.wYear, st.wMonth, st.wDay); char* sql = (char*)(LPCSTR)strSql; int nCol = 1; stmt.SQLBindCharParam(nCol++, p[0].imei, sizeof(p[0].imei)); stmt.SQLBindCharParam(nCol++, p[0].time, sizeof(p[0].time)); stmt.SQLBindTinyIntParam(nCol++, &p[0].index); //stmt.SQLBindTimeStampParam(nCol++, &p[0].time); stmt.SQLBindIntParam(nCol++, &p[0].data0); stmt.SQLBindIntParam(nCol++, &p[0].data1); stmt.SQLBindIntParam(nCol++, &p[0].data2); //prepare int step = 1000 / nNum; int j = 0; { for (auto i = 0; i < nNum; i++) { if (len0) { if (vctResult0[i] == false) continue; p[j].index = 0; //if (!vctData0[i].IsEmpty()) p[j].data0 = strtol(vctData0[i], NULL, 16) - 0x8000; //if (!vctData1[i].IsEmpty()) p[j].data1 = strtol(vctData1[i], NULL, 16) - 0x8000; //if (!vctData2[i].IsEmpty()) p[j].data2 = strtol(vctData2[i], NULL, 16) - 0x8000; p[j].data0 = vctData0[i]; p[j].data1 = vctData1[i]; p[j].data2 = vctData2[i]; //ASSERT(p[j].data2); //pDevice->Insert(0, tmNowStart + step * i, vctData0[i], vctData1[i], vctData2[i]); } else if (len3) { if (vctResult3[i] == false) continue; p[j].index = 1; //if (!vctData3[i].IsEmpty()) p[j].data0 = strtol(vctData3[i], NULL, 16) - 0x8000; //if (!vctData4[i].IsEmpty()) p[j].data1 = strtol(vctData4[i], NULL, 16) - 0x8000; //if (!vctData5[i].IsEmpty()) p[j].data2 = strtol(vctData5[i], NULL, 16) - 0x8000; p[j].data0 = vctData3[i]; p[j].data1 = vctData4[i]; p[j].data2 = vctData5[i]; //pDevice->Insert(1, tmNowStart + step * i, vctData3[i], vctData4[i], vctData5[i]); } else if (len6) { if (vctResult6[i] == false) continue; p[j].index = 2; //if (!vctData6[i].IsEmpty()) p[j].data0 = strtol(vctData6[i], NULL, 16) - 0x8000; //if (!vctData7[i].IsEmpty()) p[j].data1 = strtol(vctData7[i], NULL, 16) - 0x8000; //if (!vctData8[i].IsEmpty()) p[j].data2 = strtol(vctData8[i], NULL, 16) - 0x8000; p[j].data0 = vctData6[i]; p[j].data1 = vctData7[i]; p[j].data2 = vctData8[i]; //pDevice->Insert(2, tmNowStart + step * i, vctData6[i], vctData7[i], vctData8[i]); } memcpy_s(p[j].imei, sizeof(p[j].imei), imei, strlen(imei)); sprintf_s(p[j].time, sizeof(p[j].time), "%04d-%02d-%02d %02d:%02d:%02d.%03d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, step * i); j++; //memcpy(&p[j].time, &ts, sizeof(ts)); //ts.fraction = step * i; } assert(j == nNewNum); } //exec //#ifndef _DEBUG auto iret = db->SetAutoCommit(false); iret = stmt.Prepare(sql); if (ISODBCSUCCESS(stmt.Execute())) { } else { vector vct; GetOdbcError((SQLSMALLINT)SQL_HANDLE_STMT, stmt.GetHandle(), vct); CString strError; if (vct.size() > 0) { COdbcError error = vct.front(); strError.Format("%s %s %d %s %d %s", __FILE__, __FUNCTION__, __LINE__, error.strSQLState, error.nNativeError, error.strMessage); TRACE("%s\r\n", strError); } CSimpleLog::Error(strError); strError.Format("IMEI:%s time:%s num:%d newnum:%d j:%d", imei, odt.Format("%Y-%m-%d %H:%M:%S"), nNum, nNewNum, j); CSimpleLog::Error(strError); code = 500; } iret = db->Commit(); db->SetAutoCommit(true); //#endif // !_DEBUG CDBConnectPool::Instance()->FreeConnection(db); if (p) { delete[] p; p = nullptr; } } //补偿点 { string insert_sql; string str_time; time_t tTime; int data0, data1, data2; uint8_t* pack = nullptr; int len = 0; if (len0) { if (pDevice->CalcBInsertData(0, &tTime, &data0, &data1, &data2)) { str_time = (LPCSTR)CTime(tTime / 1000).Format("%Y-%m-%d %H:%M:%S.") + to_string(tTime % 1000); insert_sql = fmt::format("INSERT INTO rm_resistance_{}{:0>2}{:0>2} (IMEI,acquisitiontime,idx,data0,data1,data2)VALUES('{}', '{}', {}, {}, {}, {});", st.wYear, st.wMonth, st.wDay, imei, str_time, 0, data0, data1, data2); pDevice->Insert(0, tTime, data0, data1, data2); //mg_315_server->SendRealDataValue(mo_mp, true, data0, data1, data2, ctNow); } } else if (len3) { if (pDevice->CalcBInsertData(1, &tTime, &data0, &data1, &data2)) { str_time = (LPCSTR)CTime(tTime / 1000).Format("%Y-%m-%d %H:%M:%S.") + to_string(tTime % 1000); insert_sql = fmt::format("INSERT INTO rm_resistance_{}{:0>2}{:0>2} (IMEI,acquisitiontime,idx,data0,data1,data2)VALUES('{}', '{}', {}, {}, {}, {});", st.wYear, st.wMonth, st.wDay, imei, str_time, 1, data0, data1, data2); pDevice->Insert(1, tTime, data0, data1, data2); //mg_315_server->SendRealDataValue(mo_mp, true, data0, data1, data2, ctNow); } } else if (len6) { if (pDevice->CalcBInsertData(2, &tTime, &data0, &data1, &data2)) { str_time = (LPCSTR)CTime(tTime / 1000).Format("%Y-%m-%d %H:%M:%S.") + to_string(tTime % 1000); insert_sql = fmt::format("INSERT INTO rm_resistance_{}{:0>2}{:0>2} (IMEI,acquisitiontime,idx,data0,data1,data2)VALUES('{}', '{}', {}, {}, {}, {});", st.wYear, st.wMonth, st.wDay, imei, str_time, 2, data0, data1, data2); pDevice->Insert(2, tTime, data0, data1, data2); //mg_315_server->SendRealDataValue(mo_mp, true, data0, data1, data2, ctNow); } } if (insert_sql.length()) { if (CSuperManager::Instance()->GetSuperNum() && bMoMp) { auto no = GeneralResistPack(mo_mp, data0, data1, data2, str_time, &pack, &len); if (no) CSuperManager::Instance()->SendPack(pack, len, no, E_ZL_PROTOCAL::ZL_RESIST_DATA, false); delete[] pack; pack = nullptr; } CString sql(insert_sql.c_str()); CSimpleLog::Info("数据补偿:" + sql); CDBConnectPool::Instance()->DBExecuteSQL(sql); } } }while (false); auto dif = chrono::duration_cast(chrono::steady_clock::now() - start_time).count(); if (dif > 500) CSimpleLog::Info(fmt::format("push msg 处理耗时: {} ms.", dif).c_str()); return TRUE; } //实时 uint32_t CLNHandle::GeneralResistPack(const string& momp, const int num, const std::vector& vctData0, const std::vector& vctData1, const std::vector& vctData2, const std::vector& vctResult, const CTime& atime, uint8_t** pack, int* len) { auto doc = yyjson_mut_doc_new(nullptr); auto root = yyjson_mut_obj(doc); yyjson_mut_doc_set_root(doc, root); int step = 1000 / num; //uint64_t utime_t = atime.GetTime() * 1000; string up, momp_name; CMonitorObjectMng::Instance()->GetStationNameByMomP(momp, up, momp_name); string name1, name2, name3; CMonitorObjectMng::Instance()->GetNameByMoMp(momp, name1, name2, name3); string mo, mp; CMonitorObjectMng::spiltByPoint(momp, mo, mp); yyjson_mut_obj_add_strcpy(doc, root, "station", up.c_str()); yyjson_mut_obj_add_strcpy(doc, root, "mo", mo.c_str()); yyjson_mut_obj_add_strcpy(doc, root, "mp", mp.c_str()); auto time = yyjson_mut_arr(doc); yyjson_mut_obj_add_val(doc, root, "time", time); auto fix_data = yyjson_mut_arr(doc); yyjson_mut_obj_add_val(doc, root, "fix_data", fix_data); auto invert_data = yyjson_mut_arr(doc); yyjson_mut_obj_add_val(doc, root, "invert_data", invert_data); auto convert_data = yyjson_mut_arr(doc); yyjson_mut_obj_add_val(doc, root, "convert_data", convert_data); if (name1.find("定位") != -1) { for (int i = 0; i < num; i++) { if (vctResult[i] == false) continue; yyjson_mut_arr_add_strcpy(doc, time, fmt::format("{}.{:0>3}", atime.Format("%Y-%m-%d %H:%M:%S"), step*i).c_str()); yyjson_mut_arr_add_int(doc, fix_data, vctData0[i]); yyjson_mut_arr_add_int(doc, invert_data, vctData1[i]); yyjson_mut_arr_add_int(doc, convert_data, vctData2[i]); } } else { for (int i = 0; i < num; i++) { if (vctResult[i] == false) continue; yyjson_mut_arr_add_strcpy(doc, time, fmt::format("{}.{:0>3}", atime.Format("%Y-%m-%d %H:%M:%S"), step * i).c_str()); yyjson_mut_arr_add_int(doc, invert_data, vctData0[i]); yyjson_mut_arr_add_int(doc, fix_data, vctData1[i]); yyjson_mut_arr_add_int(doc, convert_data, vctData2[i]); } } size_t json_len; auto json = yyjson_mut_write(doc, 0, &json_len); yyjson_mut_doc_free(doc); *len = json_len + sizeof(HJDATAHEAD2) + 2; *pack = new uint8_t[*len]; auto no = CAppService::Instance()->GetPackNo(); CHjDataConver::conver_sendpack(*pack, (LPBYTE)json, json_len, 0, no, E_ZL_PROTOCAL::ZL_RESIST_DATA, OR_DATA_INFO(0, 0, 1, 2, OPT_TYPE::OPT_ADD)); free(json); return no; } //补传一个点 uint32_t CLNHandle::GeneralResistPack(const string& momp, int data0, int data1, int data2, string str_time, uint8_t** pack, int* len) { auto doc = yyjson_mut_doc_new(nullptr); auto root = yyjson_mut_obj(doc); yyjson_mut_doc_set_root(doc, root); string up, momp_name; CMonitorObjectMng::Instance()->GetStationNameByMomP(momp, up, momp_name); string name1, name2, name3; CMonitorObjectMng::Instance()->GetNameByMoMp(momp, name1, name2, name3); string mo, mp; CMonitorObjectMng::spiltByPoint(momp, mo, mp); yyjson_mut_obj_add_strcpy(doc, root, "station", up.c_str()); yyjson_mut_obj_add_strcpy(doc, root, "mo", mo.c_str()); yyjson_mut_obj_add_strcpy(doc, root, "mp", mp.c_str()); auto time = yyjson_mut_arr(doc); yyjson_mut_obj_add_val(doc, root, "time", time); auto fix_data = yyjson_mut_arr(doc); yyjson_mut_obj_add_val(doc, root, "fix_data", fix_data); auto invert_data = yyjson_mut_arr(doc); yyjson_mut_obj_add_val(doc, root, "invert_data", invert_data); auto convert_data = yyjson_mut_arr(doc); yyjson_mut_obj_add_val(doc, root, "convert_data", convert_data); yyjson_mut_arr_add_strcpy(doc, time, str_time.c_str()); if (name1.find("定位") != -1) { yyjson_mut_arr_add_int(doc, fix_data, data0); yyjson_mut_arr_add_int(doc, invert_data, data1); } else { yyjson_mut_arr_add_int(doc, invert_data, data0); yyjson_mut_arr_add_int(doc, fix_data, data1); } yyjson_mut_arr_add_int(doc, convert_data, data2); size_t json_len; auto json = yyjson_mut_write(doc, 0, &json_len); yyjson_mut_doc_free(doc); *len = json_len + sizeof(HJDATAHEAD2) + 2; *pack = new uint8_t[*len]; auto no = CAppService::Instance()->GetPackNo(); CHjDataConver::conver_sendpack(*pack, (LPBYTE)json, json_len, 0, no, E_ZL_PROTOCAL::ZL_RESIST_DATA, OR_DATA_INFO(0, 0, 1, 2, OPT_TYPE::OPT_ADD)); free(json); return no; } uint32_t CLNHandle::GeneralTempPack(const string& momp, int temp, int humi, time_t utime_t, uint8_t** pack, int* len) { if (momp.length() <= 3) return 0; if (utime_t - m_mapTempHumi[momp] < 60) return 0;//温湿度1分钟上送一次 m_mapTempHumi[momp] = utime_t; string mo, mp; CMonitorObjectMng::spiltByPoint(momp, mo, mp); auto doc = yyjson_mut_doc_new(nullptr); auto root = yyjson_mut_obj(doc); yyjson_mut_doc_set_root(doc, root); string up, momp_name; CMonitorObjectMng::Instance()->GetStationNameByMomP(momp, up, momp_name); //string name1, name2, name3; //CMonitorObjectMng::Instance()->GetNameByMoMp(momp, name1, name2, name3); yyjson_mut_obj_add_strcpy(doc, root, "station", up.c_str()); yyjson_mut_obj_add_strcpy(doc, root, "mo", mo.c_str()); yyjson_mut_obj_add_strcpy(doc, root, "mp", mp.c_str()); yyjson_mut_obj_add_strcpy(doc, root, "time", CTime(utime_t).Format("%Y-%m-%d %H:%M:%S")); yyjson_mut_obj_add_int(doc, root, "temp", temp); yyjson_mut_obj_add_int(doc, root, "humi", humi); size_t json_len; auto json = yyjson_mut_write(doc, 0, &json_len); yyjson_mut_doc_free(doc); *len = json_len + sizeof(HJDATAHEAD2) + 2; *pack = new uint8_t[*len]; auto no = CAppService::Instance()->GetPackNo(); CHjDataConver::conver_sendpack(*pack, (LPBYTE)json, json_len, 0, no, E_ZL_PROTOCAL::ZL_TEMP_HUMI, OR_DATA_INFO(0, 0, 1, 2, OPT_TYPE::OPT_ADD)); free(json); return no; } BOOL CLNHandle::HandlePushInfo(const rapidjson::Document& doc, const char* imei, const SOCKADDR* psa, CLNContext* pContext /*= NULL*/) { if (pContext) pContext->m_mapImei[imei]++; string CCID; if (doc.HasMember("CCID") && doc["CCID"].IsString()) CCID = doc["CCID"].GetString(); string location; if (doc.HasMember("location") && doc["location"].IsString()) location = doc["location"].GetString(); string type; if (doc.HasMember("type") && doc["type"].IsString()) type = doc["type"].GetString(); string version; if (doc.HasMember("version") && doc["version"].IsString()) version = doc["version"].GetString(); vector vct(2); auto vctLen = convertStrToArray(location, vct); //model = 0 代表数据模式 1 代表升级模式 //update CString strSql; strSql.Format(" IF EXISTS (SELECT TOP 1 * FROM rm_deviceinfo WHERE IMEI = '%s') " \ " BEGIN " " UPDATE rm_deviceinfo set CCID = '%s', longitude = %f, latitude = %f, type='%s', version='%s', updatetime = GETDATE(), model = 0 WHERE IMEI = '%s' " \ " END " \ " ELSE " \ " BEGIN " \ " INSERT INTO [dbo].[rm_deviceinfo] ([IMEI],[CCID],[longitude],[latitude],[type],[version],[model]) VALUES ('%s', '%s', %f, %f, '%s', '%s', 0)" \ " END", imei, CCID.c_str(), atof(vct[0]), atof(vct[1]), type.c_str(), version.c_str(), imei, imei, CCID.c_str(), atof(vct[0]), atof(vct[1]), type.c_str(), version.c_str() ); if (!CDBConnectPool::Instance()->DBExecuteSQL(strSql)) CSimpleLog::Error(strSql + "执行失败"); //response StringBuffer strBuf; Writer writer(strBuf); writer.StartObject(); writer.Key("cmd"); writer.String("push_info_ack"); writer.Key("IMEI"); writer.String(imei); writer.EndObject(); string data = strBuf.GetString(); if (pContext) return pContext->Send(data.c_str(), data.length()) != SOCKET_ERROR; else if (psa) return CAppService::Instance()->GetUdpSocket()->SendTo((void*)data.c_str(), data.length(), psa, sizeof(SOCKADDR)); else return FALSE; } BOOL CLNHandle::HandleInfoAck(const rapidjson::Document& doc, const char* imei, const SOCKADDR* psa, CLNContext* pContext /*= NULL*/) { return FALSE; } BOOL CLNHandle::HanldeTime(const rapidjson::Document& doc, const char* imei, const SOCKADDR* psa, CLNContext* pContext /*= NULL*/) { if (pContext == FALSE) return FALSE; time_t tmNow; time(&tmNow); //response StringBuffer strBuf; Writer writer(strBuf); writer.StartObject(); writer.Key("cmd"); writer.String("time_ack"); writer.Key("timestamp"); writer.Uint64(tmNow); writer.Key("IMEI"); writer.String(imei); writer.EndObject(); string data = strBuf.GetString(); return pContext->Send(data.c_str(), data.length()) != SOCKET_ERROR; } BOOL CLNHandle::SendTimeAckToAllDevice() { auto doc = yyjson_mut_doc_new(nullptr); auto root = yyjson_mut_obj(doc); yyjson_mut_doc_set_root(doc, root); yyjson_mut_obj_add_str(doc, root, "cmd", "time_ack"); auto pAcceptor = CAppService::Instance()->GetAcceptor(); pAcceptor->Lock(); for (auto& it : pAcceptor->m_lstClientContext) { auto pContext = (CLNContext*)it; for (auto& ik : pContext->m_mapImei) { yyjson_mut_obj_remove_str(root, "IMEI"); yyjson_mut_obj_remove_str(root, "timestamp"); yyjson_mut_obj_add_strcpy(doc, root, "IMEI", ik.first); auto tt = CTime::GetCurrentTime().GetTime(); yyjson_mut_obj_add_int(doc, root, "timestamp", tt); size_t l; auto json = yyjson_mut_write(doc, 0, &l); if (json) { pContext->Send(json, l); free(json); } } } pAcceptor->Unlock(); yyjson_mut_doc_free(doc); return TRUE; } //{"cmd":"push_online","IMEI":"002E00404B305009","st0":[0,0],"st1":[0,0],"st2":[1,0],"st3":[0,0],"st4":[0,0],"st5":[1,0],"st6":[0,0],"st7":[0,0],"st8":[1,0]} //{"cmd":"push_online","IMEI":"1234567890","packnum":"2","st0":[1],"st1":[0],"st2":[0],"st3":[0],"st4":[0],"st5":[0],"st6":[0],"st7":[0],"st8":[0],"dt0":[1],"dt1":[0],"dt2":[0],"dt3":[0],"dt4":[0],"dt5":[0],"dt6":[0],"dt7":[0],"dt8":[0]} BOOL CLNHandle::HandlePushOnline(const rapidjson::Document& doc, const char* imei, const SOCKADDR* psa, CLNContext* pClientContext, LPBYTE pPack, int nPackLen) { CSimpleLog::Info(CString((char*)pPack, nPackLen)); if (doc.HasMember("packnum") == FALSE || doc["packnum"].IsString() == FALSE) return FALSE; auto packnum = doc["packnum"].GetString(); CString strData; strData.Format(R"({"cmd":"push_online_ack","IMEI":"%s","packnum":"%s"})", imei, packnum ? packnum : ""); if (pClientContext) pClientContext->Send(strData, strData.GetLength()) != SOCKET_ERROR; else if (psa) CAppService::Instance()->GetUdpSocket()->SendTo((void*)(LPCSTR)strData, strData.GetLength(), psa, sizeof(SOCKADDR)); auto pDevice = CDeviceMng::Instance()->Find(imei); if (pDevice == nullptr) return FALSE; SENSOR_STATUS sensor_status[9][2]; memset(&sensor_status, (int)SENSOR_STATUS::UNKONW, sizeof(sensor_status)); char key[10]; for (int i = 0; i < 9; i++) { sprintf_s(key, 10, "st%d", i); if (doc.HasMember(key) == false || doc[key].IsArray() == false) continue; auto st = doc[key].GetArray(); for (int j = 0; j < st.Size() && j < 2; j++) { if (st[j].IsInt() == false) continue; if (st[j].GetInt() == 0) sensor_status[i][j] = SENSOR_STATUS::ABNORMAL; else sensor_status[i][j] = SENSOR_STATUS::NORMAL; } } for (int i = 0; i < 9; i++) { for (int j = 0; j < 2; j++) { const auto& tt = sensor_status[i][j]; auto& src_tt = pDevice->m_sensor_status[i][j]; bool bNew = false, bConver = false; if (src_tt != SENSOR_STATUS::UNKONW && tt == src_tt) continue; if (tt == SENSOR_STATUS::NORMAL && src_tt == SENSOR_STATUS::ABNORMAL) //恢复 bConver = true; else if (tt == SENSOR_STATUS::ABNORMAL && src_tt == SENSOR_STATUS::NORMAL) //产生 bNew = true; else if (src_tt == SENSOR_STATUS::UNKONW && tt == SENSOR_STATUS::ABNORMAL) bNew = true; else if (src_tt == SENSOR_STATUS::UNKONW) src_tt = tt; else if (tt == SENSOR_STATUS::UNKONW) //丢失 bNew = true; else ASSERT(FALSE); src_tt = tt; //赋值 if (bConver == false && bNew == false) continue; string mo, mp; uint8_t idx = i % 3; if (false == CMonitorObjectMng::Instance()->IMEI2MOMP(imei, idx, mo, mp)) continue; auto pInfo = CMonitorObjectMng::Instance()->GetMoMpInfo(mo + '.' + mp); if (pInfo == nullptr) { ASSERT(FALSE); continue; } //判断是否安装 switch (idx) { case 0: if (pInfo->binstall_1 == false) continue; break; case 1: if (pInfo->binstall_2 == false) continue; break; case 2: if (pInfo->binstall_3 == false) continue; break; default: ASSERT(FALSE); break; } SYSTEMTIME stNow; GetLocalTime(&stNow); //报警发送 if (bNew) { //存入数据库 CResistAlarmMng::Instance()->GeneralAlarm(mo, mp, idx, eZL_ALARMTYPE::SENSOR_ABNORMAL, 1, stNow); //上送报警 传感器异常暂时屏蔽 等待放开 //g_p315ClientManager->GetTcpClient()->SendAlarmData(CMonitorObjectMng::Instance()->GetZZJNO(mo + '.' + mp), 1, CTime(stNow).GetTime(), 0xFFFFFFFF, // eZL_ALARMTYPE::SENSOR_ABNORMAL, eDaoChaPosi::DCP_UNKNOWN, 0, 0, TIEDA_ACQ_VALUE(INT_MIN), TIEDA_ACQ_VALUE(INT_MIN), 0); } else if (bConver) { CResistAlarmMng::Instance()->RecoverAlarm(mo, mp, idx, eZL_ALARMTYPE::SENSOR_ABNORMAL, 1, stNow); //g_p315ClientManager->GetTcpClient()->SendAlarmData(CMonitorObjectMng::Instance()->GetZZJNO(mo + '.' + mp), 2, CTime(stNow).GetTime(), CTime(stNow).GetTime(), // eZL_ALARMTYPE::SENSOR_ABNORMAL, eDaoChaPosi::DCP_UNKNOWN, 0, 0, TIEDA_ACQ_VALUE(INT_MIN), TIEDA_ACQ_VALUE(INT_MIN), 0); } } } return TRUE; } //client BOOL CLNHandle::HandleUpdate(const rapidjson::Document& doc, const char* imei, const SOCKADDR* psa, CLNContext* pClientContext /*= NULL*/) { if (pClientContext == FALSE) return FALSE; auto pContext = (CLNContext*)pClientContext; pContext->ivuname = imei; BOOL bDataRight = TRUE; //接收文件数据 string data; if (doc.HasMember("data") && doc["data"].IsString()) data = doc["data"].GetString(); else bDataRight = FALSE; string type; if (doc.HasMember("type") && doc["type"].IsString()) type = doc["type"].GetString(); else bDataRight = FALSE; uint32_t filecrc; if (doc.HasMember("filecrc") && doc["filecrc"].IsUint()) filecrc = doc["filecrc"].GetUint(); else bDataRight = FALSE; uint32_t filesize; if (doc.HasMember("filesize") && doc["filesize"].IsUint()) filesize = doc["filesize"].GetUint(); else bDataRight = FALSE; if (bDataRight) { auto& mapTypeData = CAppService::Instance()->m_mapTypeData; auto it = mapTypeData.find(type.c_str()); int datalen = data.length(); if (it != mapTypeData.end()) { it->second->Join(); it->second = nullptr; } char* pData = new char[datalen + 2]; auto pInfo = new UPGRADE_FILE_DATA; mapTypeData[type.c_str()] = pInfo; pInfo->data = pData; pInfo->len = filesize * 2; pInfo->crc = filecrc; memcpy_s(pData, datalen + 2, data.c_str(), datalen); pData[datalen] = 0x00; pData[datalen + 1] = 0x00; } else { CSimpleLog::Error("HandleUpdate 数据解析错误!"); } //校验文件数据OK //response StringBuffer strBuf; Writer writer(strBuf); writer.StartObject(); BOOL bUpdateToDevice = FALSE; char ip[30]; uint16_t port = 0; pContext->GetIPAdressNew(ip, 30, port); if (bDataRight && SendUpdateToDevice(imei, ip, type)) { //writer.Key("cmd"); //writer.String("update_ack"); //writer.Key("result"); //writer.String("true"); bUpdateToDevice = TRUE; } else { writer.Key("cmd"); writer.String("update_ack"); writer.Key("IMEI"); writer.String(imei); writer.Key("result"); writer.String("false"); writer.EndObject(); string senddata = strBuf.GetString(); #ifdef SEND_LOG CSimpleLog::Info(senddata.c_str()); #endif // SEND_LOG bUpdateToDevice &= pContext->Send(senddata.c_str(), senddata.length()) != SOCKET_ERROR; } return bUpdateToDevice; } //device BOOL CLNHandle::HandleUpdateAck(const rapidjson::Document& doc, LPBYTE pPack, int nPackLen, const char* imei, const SOCKADDR* psa, CLNContext* pClientContext /*= NULL*/) { CString strLog; string result; if (doc.HasMember("result") && doc["result"].IsString()) result = doc["result"].GetString(); strLog.Format("收到设备升级数据ok包:" + CString(imei) + "result:" + result.c_str()); TRACE("%s\r\n", strLog); CSimpleLog::Info(strLog); //根据imei查找TCP链路 auto pAcceptor = CAppService::Instance()->GetAcceptor(); auto pContext = pAcceptor->FindContextByIVU(imei); if (pContext == nullptr) return FALSE; auto ret = pContext->Send(pPack, nPackLen) != SOCKET_ERROR; pContext->ReleaseSharedPointer(); return ret; } //client BOOL CLNHandle::HandleOnlineDevice(const rapidjson::Document& doc, const char* imei, const SOCKADDR* psa, CLNContext* pClientContext /*= NULL*/) { if (pClientContext == FALSE) return FALSE; auto pContext = (CLNContext*)pClientContext; auto pAcceptor = CAppService::Instance()->GetAcceptor(); if (pAcceptor == nullptr) return FALSE; std::list lst; pAcceptor->GetAllContextImei(lst); //response StringBuffer strBuf; Writer writer(strBuf); writer.StartObject(); writer.Key("cmd"); writer.String("get_online_ack"); writer.Key("list"); writer.StartArray(); for (const auto& it : lst) writer.String(it); writer.EndArray(); writer.EndObject(); string data = strBuf.GetString(); return pContext->Send(data.c_str(), data.length()) != SOCKET_ERROR; } BOOL CLNHandle::HandleOnlineDeviceNew(const SOCKADDR* psa, CLNContext* pContext /*= NULL*/) { auto pAcceptor = CAppService::Instance()->GetAcceptor(); if (pAcceptor == nullptr) return FALSE; std::list lst; pAcceptor->GetAllContextImei(lst); auto doc = yyjson_mut_doc_new(nullptr); auto root = yyjson_mut_obj(doc); yyjson_mut_doc_set_root(doc, root); yyjson_mut_obj_add_str(doc, root, "cmd", "get_online_ack"); auto list = yyjson_mut_arr(doc); yyjson_mut_obj_add_val(doc, root, "list", list); auto desc_arr = yyjson_mut_arr(doc); yyjson_mut_obj_add_val(doc, root, "desc", desc_arr); for (auto& it : lst) { yyjson_mut_arr_add_str(doc, list, it); string imei_idx = it + ".0"; string mo_mp; string desc = " "; if (CMonitorObjectMng::Instance()->IMEI2MOMP(imei_idx, mo_mp)) desc += "[" + mo_mp + "]"; imei_idx = it + ".1"; if (CMonitorObjectMng::Instance()->IMEI2MOMP(imei_idx, mo_mp)) desc += "[" + mo_mp + "]"; imei_idx = it + ".2"; if (CMonitorObjectMng::Instance()->IMEI2MOMP(imei_idx, mo_mp)) desc += "[" + mo_mp + "]"; yyjson_mut_arr_add_strcpy(doc, desc_arr, desc.c_str()); } size_t len; auto json = yyjson_mut_write(doc, 0, &len); BOOL bRet = FALSE; if (pContext) bRet = pContext->Send(json, len) != SOCKET_ERROR; else if (psa) bRet = CAppService::Instance()->GetUdpSocket()->SendTo(json, len, psa, sizeof(SOCKADDR)); return bRet; } BOOL CLNHandle::HandleQueryMsgAck(const rapidjson::Document& doc, const char* imei, const SOCKADDR* psa, CLNContext* pClientContext /*= NULL*/) { if (doc.HasMember("result") == FALSE || doc["result"].IsString() == FALSE) return FALSE; string result = doc["result"].GetString(); CString strLog; if (result.compare("true") == 0) strLog.Format("设备[%s]响应实时数据成功.",imei); else if (result.compare("false") == 0) strLog.Format("设备[%s]响应实时数据失败.", imei); else strLog.Format("设备[%s]响应实时数据%s.", result.c_str()); CSimpleLog::Info(strLog); return TRUE; } BOOL CLNHandle::HandleUpdateInit(const rapidjson::Document& doc, const char* imei, const SOCKADDR* psa, CLNContext* pClientContext) { CAppService::Instance()->m_bHaveDeviceUpgrade = TRUE; time(&CAppService::Instance()->m_tDeviceUpgrade); //根据type 来发送 filelen 和 filecrc updateinit_ack if (psa == nullptr && pClientContext == nullptr) return FALSE; CString sql; sql.Format("UPDATE rm_deviceinfo SET model = 1 WHERE IMEI = '%s';", imei); if (CDBConnectPool::Instance()->DBExecuteSQL(sql) == FALSE) CSimpleLog::Error(sql); uint32_t filesize = 0; uint32_t filecrc = 0; do { string type; if (doc.HasMember("type") && doc["type"].IsString()) type = doc["type"].GetString(); else break; auto& mapTypeData = CAppService::Instance()->m_mapTypeData; const auto it = mapTypeData.find(type.c_str()); if (it == mapTypeData.end()) { CString strLog; strLog.Format("%s %d 未找到文件 IMEI:%s type:%s ", __FUNCTION__, __LINE__, imei, type.c_str()); CSimpleLog::Error(strLog); break; } if (it->second == nullptr) break; auto pInfo = it->second; filesize = it->second->len / 2; filecrc = it->second->crc; } while (false); //response StringBuffer strBuf; Writer writer(strBuf); writer.StartObject(); writer.Key("cmd"); writer.String("updateinit_ack"); writer.Key("IMEI"); writer.String(imei); writer.Key("filesize"); writer.Uint(filesize); writer.Key("filecrc"); writer.Uint(filecrc); writer.EndObject(); string data = strBuf.GetString(); #ifdef SEND_LOG CSimpleLog::Info(data.c_str()); #endif // SEND_LOG if (psa) { return CAppService::Instance()->GetUdpSocket()->SendTo(data.c_str(), data.length(), psa, sizeof(SOCKADDR)) != SOCKET_ERROR; } else if (pClientContext) { const auto pContext = (CLNContext*)pClientContext; return pContext->Send(data.c_str(), data.length()) > 0; } return false; } BOOL CLNHandle::HandleUpdateSeq(const rapidjson::Document& doc, const char* imei, const SOCKADDR* psa, CLNContext* pClientContext) { CAppService::Instance()->m_bHaveDeviceUpgrade = TRUE; time(&CAppService::Instance()->m_tDeviceUpgrade); //根据type 和 seq 来发送 seq datalen data updateseq_ack if (psa == nullptr && pClientContext == nullptr) return FALSE; int datalen = 0; char szData[1025] = { 0 }; int seq = -1; do { string type; if (doc.HasMember("type") && doc["type"].IsString()) type = doc["type"].GetString(); else break; if (doc.HasMember("seq") && doc["seq"].IsInt()) seq = doc["seq"].GetInt(); else break; auto& mapTypeData = CAppService::Instance()->m_mapTypeData; const auto it = mapTypeData.find(type.c_str()); if (it == mapTypeData.end()) { CString strLog; strLog.Format("%s %d 未找到文件 %s ", __FUNCTION__, __LINE__, imei); CSimpleLog::Error(strLog); break; } if (it->second == nullptr) break; auto pInfo = it->second; int start = seq * 512 * 2; int end = start + 512; if (start > pInfo->len) datalen = 0; else if (end > pInfo->len) datalen = (pInfo->len - start) / 2; else datalen = 512; memcpy_s(szData, 1024, pInfo->data + start, datalen * 2); } while (false); //response StringBuffer strBuf; Writer writer(strBuf); writer.StartObject(); writer.Key("cmd"); writer.String("updateseq_ack"); writer.Key("IMEI"); writer.String(imei); writer.Key("seq"); writer.Int(seq); writer.Key("datalen"); writer.Int(datalen); writer.Key("data"); writer.String(szData); writer.EndObject(); string data = strBuf.GetString(); #ifdef SEND_LOG CSimpleLog::Info(data.c_str()); #endif // _DEBUG if (psa) { return CAppService::Instance()->GetUdpSocket()->SendTo(data.c_str(), data.length(), psa, sizeof(SOCKADDR)) != SOCKET_ERROR; } else if (pClientContext) { const auto pContext = (CLNContext*)pClientContext; return pContext->Send(data.c_str(), data.length()) > 0; } return false; } BOOL CLNHandle::HandleUpdateOk(const rapidjson::Document& doc, const char* imei, const SOCKADDR* psa, CLNContext* pClientContext) { CAppService::Instance()->m_bHaveDeviceUpgrade = FALSE; time(&CAppService::Instance()->m_tDeviceUpgrade); //返回升级成功命令, 删除升级临时数据 type updateok_ack string type; if (doc.HasMember("type") && doc["type"].IsString()) type = doc["type"].GetString(); else return FALSE; CString strLog; strLog.Format("%s %s 升级完成", imei, type.c_str()); CSimpleLog::Info(strLog); if (psa == nullptr && pClientContext == nullptr) return FALSE; //response StringBuffer strBuf; Writer writer(strBuf); writer.StartObject(); writer.Key("cmd"); writer.String("updateok_ack"); writer.Key("IMEI"); writer.String(imei); writer.EndObject(); string data = strBuf.GetString(); #ifdef SEND_LOG CSimpleLog::Info(data.c_str()); #endif // _DEBUG BOOL ret = FALSE; if (psa) { ret = CAppService::Instance()->GetUdpSocket()->SendTo(data.c_str(), data.length(), psa, sizeof(SOCKADDR)) != SOCKET_ERROR; } else if (pClientContext) { const auto pContext = (CLNContext*)pClientContext; ret = pContext->Send(data.c_str(), data.length()) > 0; } //通知websocket //auto lwsService = CAppService::Instance()->GetLwsServer(); //std::map m_mapLwsSession; //{ // uint8_t s_data[200]; // memcpy_s(s_data + LWS_PRE, 200 - LWS_PRE, data.c_str(), data.length()); // std::lock_guard lcok(lwsService->m_mtxSession); // for (auto& it : lwsService->m_mapLwsSession) // { // if (m_strUpgradeRemoteAddr.compare(it.second.ip) == 0) // { // lws_write(it.first, s_data + LWS_PRE, data.length(), lws_write_protocol::LWS_WRITE_TEXT); // } // } //} auto mgService = CAppService::Instance()->GetMgServer(); if (mgService) mgService->SendToClient(data.c_str(), data.length(), m_strUpgradeRemoteAddr.c_str()); return ret; } //device int CLNHandle::SendUpdateToDevice(const char* imei, string remote_addr, string type) { m_strUpgradeRemoteAddr = remote_addr; CAppService::Instance()->m_bHaveDeviceUpgrade = TRUE; time(&CAppService::Instance()->m_tDeviceUpgrade); CAppService::Instance()->m_tDeviceUpgrade -= 55; //根据imei查找TCP链路 auto pAcceptor = CAppService::Instance()->GetAcceptor(); auto pContext = pAcceptor->FindContextByIMEI(imei); if (pContext == nullptr) { CString strLog; strLog.Format("%s %d 未找到设备 %s ", __FUNCTION__, __LINE__, imei); CSimpleLog::Error(strLog); return 1; } //下发升级指令 //response StringBuffer strBuf; Writer writer(strBuf); writer.StartObject(); writer.Key("cmd"); writer.String("update"); writer.Key("IMEI"); writer.String(imei); writer.Key("type"); writer.String(type.c_str()); writer.EndObject(); string data = strBuf.GetString(); CSimpleLog::Info(data.c_str()); auto ret = pContext->Send(data.c_str(), data.length()) != SOCKET_ERROR; pContext->ReleaseSharedPointer(); if (ret) return 0; else return 2; } int CLNHandle::SendMsgToDevice(const char* imei) { //根据imei查找TCP链路 auto pAcceptor = CAppService::Instance()->GetAcceptor(); auto pContext = pAcceptor->FindContextByIMEI(imei); if (pContext == nullptr) { CString strLog; strLog.Format("%s %d 未找到设备 %s ", __FUNCTION__, __LINE__, imei); CSimpleLog::Error(strLog); return 1; } char json[100]; int len = sprintf_s(json, 100, R"({"cmd":"query_msg","IMEI":"%s"})", imei); auto ret = pContext->Send(json, len) != SOCKET_ERROR; pContext->ReleaseSharedPointer(); CSimpleLog::Info(json); if (ret) return 0; else return 2; } std::string CLNHandle::m_strUpgradeRemoteAddr; uint32_t CLNHandle::convertStrToArray(const string& str, std::vector& lst) { // string->char * char *s_input = (char *)str.c_str(); const char * split = ","; // 以逗号为分隔符拆分字符串 char *p = strtok(s_input, split); int i = 0; while (p != NULL) { if (i < lst.capacity()) lst[i++] = p; p = strtok(NULL, split); } return i; } uint32_t CLNHandle::convertStrToArraytest(const string& str, std::vector& lst) { // string->char * char* s_input = (char*)str.c_str(); const char* split = ","; // 以逗号为分隔符拆分字符串 char* p = strtok(s_input, split); int i = 0; while (p != NULL) { if (i < lst.capacity()) { int l = strlen(p); if (l > 4) { TRACE("%s,\r\n", p); lst[i++] = strtol(p, NULL, 16) - 0x800000; } else if (l == 4) { ASSERT(strtol(p, NULL, 16) - 0x8000); lst[i++] = strtol(p, NULL, 16) - 0x8000; } } p = strtok(NULL, split); } return i; } std::map CLNHandle::m_mapIMEI_time0; std::map CLNHandle::m_mapIMEI_time3; std::map CLNHandle::m_mapIMEI_time6; std::map CLNHandle::m_mapIMEI_temp; void CLNHandle::ThreadForHandle(DWORD_PTR pThis) { Sleep(1000); SPDLOG_INFO(" 51609 handle thread start"); auto pHanlde = (CLNHandle*)pThis; while (pHanlde->m_bWork) { Sleep(1); if (pHanlde->m_lst.size() == 0) { Sleep(10); continue; } tagHandlePack* pack = nullptr; { lock_guard lock(pHanlde->m_mtx); pack = pHanlde->m_lst.front(); pHanlde->m_lst.pop_front(); } pHanlde->ProcessPack(pack->pPack, pack->nPackLen, pack->psa.sa_family == 0x00 ? nullptr : &pack->psa, pack->pClientContext); pack->join();//释放 } SPDLOG_INFO(" 51609 handle thread exit"); }