#include "stdafx.h" #include "LWSServer.h" #include "AppService.h" #include #include #include "JDSPBuffer.h" #include #include "MonitorObject.h" #include "Device.h" #include "ResistAlarm.h" #include #ifdef _DEBUG #pragma comment(lib, "hjwebsockets40d.lib") #else #pragma comment(lib, "hjwebsockets40.lib") #endif // _DEBUG #define MAX_SEND_LENGHT (5242880 + LWS_PRE) time_t g_stStart; //程序启动的时间 static int ws_protocol_callback(struct lws* wsi, enum lws_callback_reasons reason, void* user, void* in, size_t len) { switch (reason) { case LWS_CALLBACK_ESTABLISHED: // 当服务器和客户端完成握手后 { TRACE("Client connect!\n"); auto pService = CAppService::Instance()->GetLwsServer(); if (pService) pService->Establishe(wsi); } break; case LWS_CALLBACK_CLOSED: TRACE("LWS closed!\n"); { auto pService = CAppService::Instance()->GetLwsServer(); if (pService) pService->Close(wsi); } break; case LWS_CALLBACK_WSI_DESTROY: /* 含义:正在销毁ws连接对象 备注:表示libwebsockets框架即将销毁wsi对象。此时如果用户自定义对象中存在动态分配的空间,则需要在此时进行释放。 回调函数的参数含义: context: 全局上下文 wsi: ws连接对象 user: 用户自定义数据   in: 空指针   len: 0 */ TRACE("LWS DESTROY!\n"); { auto pService = CAppService::Instance()->GetLwsServer(); if (pService) pService->Destroy(wsi); } break; case LWS_CALLBACK_RECEIVE: // 当接收到客户端发来的帧以后 { auto pService = CAppService::Instance()->GetLwsServer(); ASSERT(pService); if (pService) { auto pBuffer = pService->GetBuffer(); ASSERT(pBuffer); auto fin = lws_is_final_fragment(wsi); if (fin && pBuffer->IsEmpty()) { pService->Recv(wsi, in, len); } else if (fin) { pBuffer->AddData((LPBYTE)in, len); auto packlen = pBuffer->HasPack(); assert(packlen); if (packlen) { pService->Recv(wsi, pBuffer->GetBuffer(), packlen); pBuffer->Remove(packlen); } } else { pBuffer->AddData((LPBYTE)in, len); } } } /* // 判断是否最后一帧 data->fin = lws_is_final_fragment(wsi); // 判断是否二进制消息 data->bin = lws_frame_is_binary(wsi); // 对服务器的接收端进行流量控制,如果来不及处理,可以控制之 // 下面的调用禁止在此连接上接收数据 lws_rx_flow_control(wsi, 0); // 业务处理部分,为了实现Echo服务器,把客户端数据保存起来 memcpy(&data->buf[LWS_PRE], in, len); data->len = len; memset(g_buf, 0, MAX_PAYLOAD_SIZE); //printf("recvied message:%s\n", (char*)data->buf + LWS_PRE); { //test printf //auto ret = utf82gbk(g_buf, MAX_PAYLOAD_SIZE, (char*)data->buf + LWS_PRE); //if (ret >= 0) TRACE("recv message(gbk):%s\n", g_buf); } // 需要给客户端应答时,触发一次写回调 lws_callback_on_writable(wsi); */ break; case LWS_CALLBACK_SERVER_WRITEABLE: // 当此连接可写时 // //lws_write(wsi, &data->buf[LWS_PRE], data->len, LWS_WRITE_TEXT); ////test //{ // sprintf_s(g_buf, MAX_PAYLOAD_SIZE, "%s", // "{\"cmd\":\"new_data_notify\",\"tag\":\"addr\",\"1122011356\":\"G3.K1322+270_古钱岭至狮岭互通门架.plate_detect\",\"data_fmt\":\"plate_info\",\"data\":[{\"time\":\"2020-03-24 17:27:22.362\",\"url\":\"24172722362-粤AVD463-蓝_plate.jpg\",\"license\":\"粤AVD463\",\"lane\":0,\"color\":\"蓝\",\"width\":\"195px\",\"confidence\":\"89%\"},{\"time\":\"2020-03-24 17:27:51.646\",\"url\":\"24172751646-粤LK828Y-蓝_plate.jpg\",\"license\":\"粤LK828Y\",\"lane\":1,\"color\":\"蓝\",\"width\":\"194px\",\"confidence\":\"85%\"}]}"); // TRACE("send message(gbk):%s\n", g_buf); // //auto ret = gbk2utf8(g_buf, MAX_PAYLOAD_SIZE, // // "{\"cmd\":\"new_data_notify\",\"tag\":\"addr\",\"1122011356\":\"G3.K1322+270_古钱岭至狮岭互通门架.plate_detect\",\"data_fmt\":\"plate_info\",\"data\":[{\"time\":\"2020-03-24 17:27:22.362\",\"url\":\"24172722362-粤AVD463-蓝_plate.jpg\",\"license\":\"粤AVD463\",\"lane\":0,\"color\":\"蓝\",\"width\":\"195px\",\"confidence\":\"89%\"},{\"time\":\"2020-03-24 17:27:51.646\",\"url\":\"24172751646-粤LK828Y-蓝_plate.jpg\",\"license\":\"粤LK828Y\",\"lane\":1,\"color\":\"蓝\",\"width\":\"194px\",\"confidence\":\"85%\"}]}" // // ); // //lws_write(wsi, (uint8_t*)g_buf, ret - 1, LWS_WRITE_TEXT); //} // 下面的调用允许在此连接上接收数据 lws_rx_flow_control(wsi, 1); break; } // 回调函数最终要返回0,否则无法创建服务器 return 0; } /** * 支持的WebSocket子协议数组 * 子协议即JavaScript客户端WebSocket(url, protocols)第2参数数组的元素 * 你需要为每种协议提供回调函数 */ struct lws_protocols ws_protocols[] = { { //协议名称,协议回调,接收缓冲区大小 "ws", ws_protocol_callback, 0, MAX_PAYLOAD_SIZE, }, { NULL, NULL, 0 // 最后一个元素固定为此格式 } }; //struct lws_protocols { /*协议名称*/ //const char* name; /*服务回调,协议事件处理*/ //lws_callback_function* callback; /*服务建立和断开时申请内存大小,也是callback中user的内存*/ //size_t per_session_data_size; /*接收缓存区大小*/ //size_t rx_buffer_size; /*协议id,可以用来区分协议*/ //unsigned int id; /*自定义数据*/ //void* user; /*发送缓存大小,为0则与rx_buffer_size相同*/ //size_t tx_packet_size; int per_session_data::SendHistResist(lws* wsi, string mo_mp, time_t start, time_t end, std::map& data0, std::map& data1, std::map& data2) { char sz_utf_first[100]; char sz_utf_second[100]; char sz_utf_three[100]; string name1, name2, name3; CMonitorObjectMng::Instance()->GetNameByMoMp(mo_mp, name1, name2, name3); if (name1[0x00] == 0x00) gbk2utf8(sz_utf_first, 100, "1号测力曲线"); else gbk2utf8(sz_utf_first, 100, name1.c_str()); if (name2[0x00] == 0x00) gbk2utf8(sz_utf_second, 100, "2号测力曲线"); else gbk2utf8(sz_utf_second, 100, name2.c_str()); if (name3[0x00] == 0x00) gbk2utf8(sz_utf_three, 100, "转换阻力曲线"); else gbk2utf8(sz_utf_three, 100, name3.c_str()); int offset = 0; int limit = 10000; auto it_data0 = data0.begin(); auto it_data1 = data1.begin(); auto it_data2 = data2.begin(); uint8_t *pSend = new uint8_t[MAX_SEND_LENGHT]; bBlock = false; do { static int n = 600; for (int i = 0; i < n; i++) { if (bWork == false) break; if (bBlock) this_thread::sleep_for(chrono::milliseconds(100)); else break; } #ifndef _DEBUG if (bBlock) ////5秒未返回确认包,结束 break;; #endif // _DEBUG //10000 一次 using namespace rapidjson; rapidjson::StringBuffer strBuf; Writer writer(strBuf); writer.StartObject(); writer.Key("cmd"); writer.String("query_hist"); writer.Key("tag"); writer.String((mo_mp + ".resist").c_str()); writer.Key("time"); writer.String(""); writer.Key("data_fmt"); writer.String("curve"); writer.Key("unit"); writer.String("N"); writer.Key("data"); writer.StartArray(); //1号测力点 writer.StartObject(); writer.Key("name"); writer.String(sz_utf_first); writer.Key("points"); writer.StartArray(); for (int i = 0; i < limit && it_data0 != data0.end(); ++it_data0) { if (it_data0->first < start) continue; if (it_data0->first >= end) break; writer.StartObject(); writer.Key("x"); writer.Uint64(it_data0->first); writer.Key("y"); writer.Int(it_data0->second); writer.EndObject(); ++i; } writer.EndArray(); writer.EndObject(); //2号测力点 writer.StartObject(); writer.Key("name"); writer.String(sz_utf_second); writer.Key("points"); writer.StartArray(); for (int i = 0; i < limit && it_data1 != data1.end(); ++it_data1) { if (it_data1->first < start) continue; if (it_data1->first >= end) break; writer.StartObject(); writer.Key("x"); writer.Uint64(it_data1->first); writer.Key("y"); writer.Int(it_data1->second); writer.EndObject(); ++i; } writer.EndArray(); writer.EndObject(); //3号测力点 writer.StartObject(); writer.Key("name"); writer.String(sz_utf_three); writer.Key("points"); writer.StartArray(); for (int i = 0; i < limit && it_data2 != data2.end(); ++it_data2) { if (it_data2->first < start) continue; if (it_data2->first >= end) break; writer.StartObject(); writer.Key("x"); writer.Uint64(it_data2->first); writer.Key("y"); writer.Int(it_data2->second); writer.EndObject(); ++i; } writer.EndArray(); writer.EndObject(); writer.EndArray(); writer.EndObject(); auto pData = strBuf.GetString(); int len = strBuf.GetLength(); if (bWork == false) break; memcpy_s(pSend + LWS_PRE, MAX_SEND_LENGHT, (uint8_t*)pData, len); auto ret = lws_write(wsi, pSend + LWS_PRE, len, lws_write_protocol::LWS_WRITE_TEXT); bBlock = true; if (ret < 0) break; if (bWork == false) break; } while (!((it_data0 == data0.end() || it_data0->first >= end) && (it_data1 == data1.end() || it_data1->first >= end) && (it_data2 == data2.end() || it_data2->first >= end))); delete[] pSend; pSend = nullptr; return 0; } int per_session_data::SendHistResistForEcharts(lws* wsi, string mo_mp, time_t start, time_t end, std::map& data0, std::map& data1, std::map& data2) { char sz_utf_first[100]; char sz_utf_second[100]; char sz_utf_three[100]; string name1, name2, name3; CMonitorObjectMng::Instance()->GetNameByMoMp(mo_mp, name1, name2, name3); if (name1[0x00] == 0x00) gbk2utf8(sz_utf_first, 100, "1号测力曲线"); else gbk2utf8(sz_utf_first, 100, name1.c_str()); if (name2[0x00] == 0x00) gbk2utf8(sz_utf_second, 100, "2号测力曲线"); else gbk2utf8(sz_utf_second, 100, name2.c_str()); if (name3[0x00] == 0x00) gbk2utf8(sz_utf_three, 100, "转换阻力曲线"); else gbk2utf8(sz_utf_three, 100, name3.c_str()); int offset = 0; int limit = 5000; auto it_data0 = data0.begin(); auto it_data1 = data1.begin(); auto it_data2 = data2.begin(); uint8_t *pSend = new uint8_t[MAX_SEND_LENGHT]; bBlock = false; do { static int n = 600; for (int i = 0; i < n; i++) { if (bWork == false) break; if (bBlock) this_thread::sleep_for(chrono::milliseconds(100)); else break; } #ifndef _DEBUG if (bBlock) ////5秒未返回确认包,结束 break;; #endif // _DEBUG //10000 一次 using namespace rapidjson; rapidjson::StringBuffer strBuf; Writer writer(strBuf); writer.StartObject(); writer.Key("cmd"); writer.String("query_hist"); writer.Key("tag"); writer.String((mo_mp + ".resist").c_str()); writer.Key("time"); writer.String(""); writer.Key("data_fmt"); writer.String("curve"); writer.Key("unit"); writer.String("N"); writer.Key("data"); writer.StartArray(); //1号测力点 writer.StartObject(); writer.Key("name"); writer.String(sz_utf_first); writer.Key("points"); writer.StartArray(); for (int i = 0; i < limit && it_data0 != data0.end(); ++it_data0) { if (it_data0->first < start) continue; if (it_data0->first >= end) break; if (it_data0->second == INVALID_RESIST) continue; writer.StartArray(); writer.Uint64(it_data0->first); writer.Int(it_data0->second); writer.EndArray(); ++i; } writer.EndArray(); writer.EndObject(); //2号测力点 writer.StartObject(); writer.Key("name"); writer.String(sz_utf_second); writer.Key("points"); writer.StartArray(); for (int i = 0; i < limit && it_data1 != data1.end(); ++it_data1) { if (it_data1->first < start) continue; if (it_data1->first >= end) break; if (it_data1->second == INVALID_RESIST) continue; writer.StartArray(); writer.Uint64(it_data1->first); writer.Int(it_data1->second); writer.EndArray(); ++i; } writer.EndArray(); writer.EndObject(); //3号测力点 writer.StartObject(); writer.Key("name"); writer.String(sz_utf_three); writer.Key("points"); writer.StartArray(); for (int i = 0; i < limit && it_data2 != data2.end(); ++it_data2) { if (it_data2->first < start) continue; if (it_data2->first >= end) break; if (it_data2->second == INVALID_RESIST) continue; writer.StartArray(); writer.Uint64(it_data2->first); writer.Int(it_data2->second); writer.EndArray(); ++i; } writer.EndArray(); writer.EndObject(); writer.EndArray(); writer.EndObject(); auto pData = strBuf.GetString(); int len = strBuf.GetLength(); if (bWork == false) break; memcpy_s(pSend + LWS_PRE, MAX_SEND_LENGHT, (uint8_t*)pData, len); auto ret = lws_write(wsi, pSend + LWS_PRE, len, lws_write_protocol::LWS_WRITE_TEXT); bBlock = true; if (ret < 0) break; if (bWork == false) break; } while (!((it_data0 == data0.end() || it_data0->first >= end) && (it_data1 == data1.end() || it_data1->first >= end) && (it_data2 == data2.end() || it_data2->first >= end))); delete[] pSend; pSend = nullptr; return 0; } //暂时不调用 int per_session_data::SendHistResistDB(LPHISTORY_QUERY history_query) { char sz_utf_first[100]; char sz_utf_second[100]; char sz_utf_three[100]; string name1, name2, name3; CMonitorObjectMng::Instance()->GetNameByMoMp(history_query->mo_mp, name1, name2, name3); if (name1[0x00] == 0x00) gbk2utf8(sz_utf_first, 100, "1号测力曲线"); else gbk2utf8(sz_utf_first, 100, name1.c_str()); if (name2[0x00] == 0x00) gbk2utf8(sz_utf_second, 100, "2号测力曲线"); else gbk2utf8(sz_utf_second, 100, name2.c_str()); if (name3[0x00] == 0x00) gbk2utf8(sz_utf_three, 100, "转换阻力曲线"); else gbk2utf8(sz_utf_three, 100, name3.c_str()); int offset = 0; int limit = 5000; //每次取出20000 CTime ctStart(history_query->tmStart / 1000); CTime ctEnd(history_query->tmEnd / 1000); char tablename[50]; SYSTEMTIME st; ctStart.GetAsSystemTime(st); sprintf_s(tablename, 50, "rm_resistance_%04d%02d%02d", st.wYear, st.wMonth, st.wDay); string strStartTime = ctStart.Format("%Y-%m-%d %H:%M:%S"); string strEndTime = ctEnd.Format("%Y-%m-%d %H:%M:%S"); uint8_t *pSend = new uint8_t[MAX_SEND_LENGHT]; bBlock = false; CString sql; do { static int n = 600; for (int i = 0; i < n; i++) { if (bWork == false) break; if (bBlock) this_thread::sleep_for(chrono::milliseconds(100)); else break; } #ifndef _DEBUG if (bBlock) ////5秒未返回确认包,结束 break;; #endif // _DEBUG auto cost_start = chrono::steady_clock::now(); sql.Format("SELECT [acquisitiontime],[data0],[data1],[data2] "\ "FROM %s WHERE IMEI = '%s' AND acquisitiontime >= '%s' and acquisitiontime < '%s' AND idx = %d "\ "ORDER BY acquisitiontime ASC OFFSET %d ROWS FETCH NEXT %d ROWS ONLY", tablename, history_query->imei.c_str(), strStartTime.c_str(), strEndTime.c_str(), history_query->idx, offset, limit); TRACE("%s\r\n", sql); int no = 0; TIMESTAMP_STRUCT ts; int sdata0, sdata1, sdata2; COdbcStatement stmt; if (CDBConnectPool::Instance()->DBQuery(stmt, sql) == FALSE) { CSimpleLog::Error("查询语句出错:" + sql); break; } int nCol = 1; stmt.BindTimeStampCol(nCol++, &ts); stmt.BindIntCol(nCol++, &sdata0); stmt.BindIntCol(nCol++, &sdata1); stmt.BindIntCol(nCol++, &sdata2); std::map data0, data1, data2; do { if (stmt.FetchNext() != 0) break; no++; CTime ctTime; try { ctTime = CTime(ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second); } catch (...) { continue; } time_t tm = ctTime.GetTime() * 1000 + ts.fraction / 1000000; data0[tm] = sdata0; data1[tm] = sdata1; data2[tm] = sdata2; } while (true); //10000 一次 using namespace rapidjson; rapidjson::StringBuffer strBuf; Writer writer(strBuf); writer.StartObject(); writer.Key("cmd"); writer.String("query_hist"); writer.Key("tag"); writer.String((history_query->mo_mp + ".resist").c_str()); writer.Key("time"); writer.String(""); writer.Key("data_fmt"); writer.String("curve"); writer.Key("unit"); writer.String("N"); writer.Key("data"); writer.StartArray(); //1号测力点 writer.StartObject(); writer.Key("name"); writer.String(sz_utf_first); writer.Key("points"); writer.StartArray(); for (const auto& it : data0) { writer.StartObject(); writer.Key("x"); writer.Uint64(it.first); writer.Key("y"); writer.Int(it.second); writer.EndObject(); } writer.EndArray(); writer.EndObject(); //2号测力点 writer.StartObject(); writer.Key("name"); writer.String(sz_utf_second); writer.Key("points"); writer.StartArray(); for (const auto& it : data1) { writer.StartObject(); writer.Key("x"); writer.Uint64(it.first); writer.Key("y"); writer.Int(it.second); writer.EndObject(); } writer.EndArray(); writer.EndObject(); //3号测力点 writer.StartObject(); writer.Key("name"); writer.String(sz_utf_three); writer.Key("points"); writer.StartArray(); for (const auto& it : data2) { writer.StartObject(); writer.Key("x"); writer.Uint64(it.first); writer.Key("y"); writer.Int(it.second); writer.EndObject(); } writer.EndArray(); writer.EndObject(); writer.EndArray(); auto cost_end = chrono::steady_clock::now(); auto cost_dif = chrono::duration_cast(cost_end - cost_start).count(); writer.Key("cost"); writer.String((to_string(cost_dif) + "ms").c_str()); writer.EndObject(); auto pData = strBuf.GetString(); int len = strBuf.GetLength(); if (bWork == false) break; memcpy_s(pSend + LWS_PRE, MAX_SEND_LENGHT, (uint8_t*)pData, len); auto ret = lws_write(wsi, pSend + LWS_PRE, len, lws_write_protocol::LWS_WRITE_TEXT); auto cost_send_dif = chrono::duration_cast(chrono::steady_clock::now() - cost_end).count(); CSimpleLog::Info(("send " + history_query->mo_mp + ".resist hist data. read cost " + to_string(cost_dif) + "ms. send cost " + to_string(cost_send_dif) + "ms. send len :" + to_string(len)).c_str()); //len 455214 bBlock = true; if (ret < 0) break; if (bWork == false) break; offset += no; if (no != limit) { break; } } while (true); delete[] pSend; pSend = nullptr; return 0; } int per_session_data::SendHistResistDBForEcharts(LPHISTORY_QUERY history_query) { char sz_utf_first[100]; char sz_utf_second[100]; char sz_utf_three[100]; string name1, name2, name3; CMonitorObjectMng::Instance()->GetNameByMoMp(history_query->mo_mp, name1, name2, name3); if (name1[0x00] == 0x00) gbk2utf8(sz_utf_first, 100, "1号测力曲线"); else gbk2utf8(sz_utf_first, 100, name1.c_str()); if (name2[0x00] == 0x00) gbk2utf8(sz_utf_second, 100, "2号测力曲线"); else gbk2utf8(sz_utf_second, 100, name2.c_str()); if (name3[0x00] == 0x00) gbk2utf8(sz_utf_three, 100, "转换阻力曲线"); else gbk2utf8(sz_utf_three, 100, name3.c_str()); int offset = 0; int limit = 5000; //每次取出10000 CTime ctStart(history_query->tmStart / 1000); CTime ctEnd(history_query->tmEnd / 1000); char tablename[50]; char tablenameTom[50]; SYSTEMTIME stStart; ctStart.GetAsSystemTime(stStart); sprintf_s(tablename, 50, "rm_resistance_%04d%02d%02d", stStart.wYear, stStart.wMonth, stStart.wDay); SYSTEMTIME stEnd; ctEnd.GetAsSystemTime(stEnd); sprintf_s(tablenameTom, 50, "rm_resistance_%04d%02d%02d", stEnd.wYear, stEnd.wMonth, stEnd.wDay); string strStartTime = ctStart.Format("%Y-%m-%d %H:%M:%S"); string strEndTime = ctEnd.Format("%Y-%m-%d %H:%M:%S"); uint8_t *pSend = new uint8_t[MAX_SEND_LENGHT]; bBlock = false; CString sql; do { static int n = 600; for (int i = 0; i < n; i++) { if (bWork == false) break; if (bBlock) this_thread::sleep_for(chrono::milliseconds(100)); else break; } #ifndef _DEBUG if (bBlock) ////5秒未返回确认包,结束 break;; #endif // _DEBUG auto cost_start = chrono::steady_clock::now(); if (stStart.wDay == stEnd.wDay) { sql.Format("SELECT [acquisitiontime],[data0],[data1],[data2] "\ "FROM %s WHERE IMEI = '%s' AND acquisitiontime >= '%s' and acquisitiontime < '%s' AND idx = %d "\ "ORDER BY acquisitiontime ASC OFFSET %d ROWS FETCH NEXT %d ROWS ONLY", tablename, history_query->imei.c_str(), strStartTime.c_str(), strEndTime.c_str(), history_query->idx, offset, limit); } else { sql.Format("SELECT [acquisitiontime],[data0],[data1],[data2] "\ "FROM %s WHERE IMEI = '%s' AND acquisitiontime >= '%s' and acquisitiontime < '%s' AND idx = %d "\ "UNION ALL "\ "SELECT [acquisitiontime],[data0],[data1],[data2] "\ "FROM %s WHERE IMEI = '%s' AND acquisitiontime >= '%s' and acquisitiontime < '%s' AND idx = %d "\ "ORDER BY acquisitiontime ASC OFFSET %d ROWS FETCH NEXT %d ROWS ONLY", tablename, history_query->imei.c_str(), strStartTime.c_str(), strEndTime.c_str(), history_query->idx, tablenameTom, history_query->imei.c_str(), strStartTime.c_str(), strEndTime.c_str(), history_query->idx, offset, limit); } TRACE("%s\r\n", sql); int no = 0; TIMESTAMP_STRUCT ts; int sdata0, sdata1, sdata2; COdbcStatement stmt; if (CDBConnectPool::Instance()->DBQuery(stmt, sql) == FALSE) { CSimpleLog::Error("查询语句出错:" + sql); break; } int nCol = 1; stmt.BindTimeStampCol(nCol++, &ts); stmt.BindIntCol(nCol++, &sdata0); stmt.BindIntCol(nCol++, &sdata1); stmt.BindIntCol(nCol++, &sdata2); std::map data0, data1, data2; do { if (stmt.FetchNext() != 0) break; no++; CTime ctTime; try { ctTime = CTime(ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.second); } catch (...) { continue; } time_t tm = ctTime.GetTime() * 1000 + ts.fraction / 1000000; data0[tm] = sdata0; data1[tm] = sdata1; data2[tm] = sdata2; } while (true); //10000 一次 using namespace rapidjson; rapidjson::StringBuffer strBuf; Writer writer(strBuf); writer.StartObject(); writer.Key("cmd"); writer.String("query_hist"); writer.Key("tag"); writer.String((history_query->mo_mp + ".resist").c_str()); writer.Key("time"); writer.String(""); writer.Key("data_fmt"); writer.String("curve"); writer.Key("unit"); writer.String("N"); writer.Key("data"); writer.StartArray(); //1号测力点 writer.StartObject(); writer.Key("name"); writer.String(sz_utf_first); writer.Key("points"); writer.StartArray(); for (const auto& it : data0) { if (INVALID_RESIST == it.second) continue; writer.StartArray(); writer.Uint64(it.first); writer.Int(it.second); writer.EndArray(); } writer.EndArray(); writer.EndObject(); //2号测力点 writer.StartObject(); writer.Key("name"); writer.String(sz_utf_second); writer.Key("points"); writer.StartArray(); for (const auto& it : data1) { if (INVALID_RESIST == it.second) continue; writer.StartArray(); writer.Uint64(it.first); writer.Int(it.second); writer.EndArray(); } writer.EndArray(); writer.EndObject(); //3号测力点 writer.StartObject(); writer.Key("name"); writer.String(sz_utf_three); writer.Key("points"); writer.StartArray(); for (const auto& it : data2) { if (INVALID_RESIST == it.second) continue; writer.StartArray(); writer.Uint64(it.first); writer.Int(it.second); writer.EndArray(); } writer.EndArray(); writer.EndObject(); writer.EndArray(); auto cost_end = chrono::steady_clock::now(); auto cost_dif = chrono::duration_cast(cost_end - cost_start).count(); writer.Key("cost"); writer.String((to_string(cost_dif) + "ms").c_str()); writer.EndObject(); auto pData = strBuf.GetString(); int len = strBuf.GetLength(); if (bWork == false) break; memcpy_s(pSend + LWS_PRE, MAX_SEND_LENGHT, (uint8_t*)pData, len); auto ret = lws_write(wsi, pSend + LWS_PRE, len, lws_write_protocol::LWS_WRITE_TEXT); auto cost_send_dif = chrono::duration_cast(chrono::steady_clock::now() - cost_end).count(); CSimpleLog::Info(("send " + history_query->mo_mp + ".resist hist data. read cost " + to_string(cost_dif) + "ms. send cost " + to_string(cost_send_dif) + "ms. send num :" + to_string(data0.size())).c_str()); //len 335214 bBlock = true; if (ret < 0) break; if (bWork == false) break; offset += no; if (no != limit) { break; } } while (true); delete[] pSend; pSend = nullptr; return 0; } //实时 void CLWSServer::ThreadProcForQueryHist(LPHISTORY_QUERY history_query) { auto pDevice = CDeviceMng::Instance()->Find(history_query->imei); if (pDevice == nullptr) return; assert(pDevice); auto pService = CAppService::Instance()->GetLwsServer(); if (pService == nullptr) return; //lock_guard lock(pService->m_mtxSession); auto it = pService->m_mapLwsSession.find(history_query->wsi); if (it == pService->m_mapLwsSession.end()) return; if (history_query->idx == 0) it->second.SendHistResistForEcharts(history_query->wsi, history_query->mo_mp, history_query->tmStart, history_query->tmEnd, pDevice->map_resist_idx00, pDevice->map_resist_idx01, pDevice->map_resist_idx02); else if (history_query->idx == 1) it->second.SendHistResistForEcharts(history_query->wsi, history_query->mo_mp, history_query->tmStart, history_query->tmEnd, pDevice->map_resist_idx10, pDevice->map_resist_idx11, pDevice->map_resist_idx12); else if (history_query->idx == 2) it->second.SendHistResistForEcharts(history_query->wsi, history_query->mo_mp, history_query->tmStart, history_query->tmEnd, pDevice->map_resist_idx20, pDevice->map_resist_idx21, pDevice->map_resist_idx22); delete history_query; history_query = nullptr; } //历史 void CLWSServer::ThreadProcForQueryHistDB(LPHISTORY_QUERY history_query) { auto pService = CAppService::Instance()->GetLwsServer(); if (pService == nullptr) return; auto it = pService->m_mapLwsSession.find(history_query->wsi); if (it == pService->m_mapLwsSession.end()) return; it->second.SendHistResistDBForEcharts(history_query); delete history_query; history_query = nullptr; } void CLWSServer::ThreadProc(DWORD_PTR wparam, uint16_t port) { CLWSServer* pThis = (CLWSServer*)wparam; if (!pThis->m_work) return; ws_protocols[0].user = pThis; struct lws_context_creation_info ctx_info = { 0 }; ctx_info.port = port; ctx_info.iface = NULL; // 在所有网络接口上监听 ctx_info.protocols = ws_protocols; ctx_info.gid = -1; ctx_info.uid = -1; ctx_info.options = LWS_SERVER_OPTION_VALIDATE_UTF8; //SSL CA证书 //ctx_info.ssl_ca_filepath = "../ca/ca-cert.pem"; //ctx_info.ssl_cert_filepath = "./server-cert.pem"; //ctx_info.ssl_private_key_filepath = "./server-key.pem"; //ctx_info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; //ctx_info.options |= LWS_SERVER_OPTION_REQUIRE_VALID_OPENSSL_CLIENT_CERT; struct lws_context* context = lws_create_context(&ctx_info); while (pThis->m_work) { lws_service(context, 100); this_thread::sleep_for(chrono::milliseconds(0)); } lws_context_destroy(context); } CLWSServer::CLWSServer() { } CLWSServer::~CLWSServer() { } BOOL CLWSServer::Start(uint16_t port) { Stop(); m_work = true; pBuffer = new CJDSPBuffer(10 * 1024 * 1024); if (pBuffer == nullptr) return false; m_pThread = new std::thread(ThreadProc, (DWORD_PTR)this, port); if (m_pThread == nullptr) return FALSE; return TRUE; } void CLWSServer::Stop() { m_work = false; if (m_pThread) { m_pThread->join(); delete m_pThread; m_pThread = nullptr; } if (pBuffer) { delete (CJDSPBuffer*)pBuffer; pBuffer = nullptr; } } uint8_t g_send_buf[LWS_PRE + MAX_PAYLOAD_SIZE]; uint8_t g_recv_buf[LWS_PRE + MAX_PAYLOAD_SIZE]; BOOL CLWSServer::SendPackToALLClient(const uint8_t* data, int len, LWS_SEND_PACK_TYPE type /*= LWS_SEND_PACK_TYPE::LSPT_UNKOWN*/, lws_write_protocol protocol) { if (m_mapLwsSession.size() == 0) return TRUE; //filter { TRACE("send message:%s\n", (char*)data); CSimpleLog::Info((char*)data); lock_guard lock(m_mtxSend); auto pSend = g_send_buf + LWS_PRE; uint8_t* pNew = nullptr; if (protocol == lws_write_protocol::LWS_WRITE_BINARY) { if (len > MAX_PAYLOAD_SIZE) { pNew = new uint8_t[len + LWS_PRE]; pSend = pNew + LWS_PRE; } memcpy(pSend, data, len); lock_guard lock(m_mtxSession); for (auto& it : m_mapLwsSession) { //订阅 //if (type == LWS_SEND_PACK_TYPE::LSPT_PLATE_DETECT && it.second.bSubPlateDetect == FALSE) continue; //else if (type == LWS_SEND_PACK_TYPE::LSPT_ALARM_EVENT && it.second.bSubAlarmEvent == FALSE) continue; //else if (type == LWS_SEND_PACK_TYPE::LSPT_TRAFFIC_FLOW && it.second.bSubTrafficFlow == FALSE) continue; //if (type == LWS_SEND_PACK_TYPE::LSPT_BOLT_DETECT && it.second.bSubBoltDetect == FALSE) continue; if (it.second.refer > 0) { int ret = lws_write(it.first, pSend, len - (int)1, protocol); if (ret <= 0) { it.second.send_fail_count++; } else { it.second.send_size += ret; it.second.send_count++; } } } } else if (protocol == lws_write_protocol::LWS_WRITE_TEXT) { assert(len * 2 < MAX_PAYLOAD_SIZE); if (len * 2 > MAX_PAYLOAD_SIZE) { pNew = new uint8_t[len * 2 + LWS_PRE]; pSend = pNew + LWS_PRE; } int new_len = gbk2utf8((char*)pSend, len * 2, (const char*)data); lock_guard lock(m_mtxSession); for (auto& it : m_mapLwsSession) { //订阅 //if (type == LWS_SEND_PACK_TYPE::LSPT_PLATE_DETECT && it.second.bSubPlateDetect == FALSE) continue; //else if (type == LWS_SEND_PACK_TYPE::LSPT_ALARM_EVENT && it.second.bSubAlarmEvent == FALSE) continue; //else if (type == LWS_SEND_PACK_TYPE::LSPT_TRAFFIC_FLOW && it.second.bSubTrafficFlow == FALSE) continue; //if (type == LWS_SEND_PACK_TYPE::LSPT_BOLT_DETECT && it.second.bSubBoltDetect == FALSE) continue; if (it.second.refer > 0) { int ret = lws_write(it.first, pSend, new_len - (int)1, protocol); if (ret <= 0) { it.second.send_fail_count++; } else { it.second.send_size += ret; it.second.send_count++; } } } } else { assert(0); } if (pNew) { delete[] pNew; pNew = nullptr; } } return FALSE; } BOOL CLWSServer::SendPackToALLClient_with_noEncode(const uint8_t* data, int len, LWS_SEND_PACK_TYPE type /*= LWS_SEND_PACK_TYPE::LSPT_UNKOWN*/, lws_write_protocol protocol /*= lws_write_protocol::LWS_WRITE_TEXT*/) { if (m_mapLwsSession.size() == 0) return TRUE; //filter { TRACE("send message:%s\n", (char*)data); CSimpleLog::Info((char*)data); lock_guard lock(m_mtxSend); auto pSend = g_send_buf + LWS_PRE; uint8_t* pNew = nullptr; if (protocol == lws_write_protocol::LWS_WRITE_BINARY) { if (len > MAX_PAYLOAD_SIZE) { pNew = new uint8_t[len + LWS_PRE]; pSend = pNew + LWS_PRE; } memcpy(pSend, data, len); lock_guard lock(m_mtxSession); for (auto& it : m_mapLwsSession) { //订阅 //if (type == LWS_SEND_PACK_TYPE::LSPT_PLATE_DETECT && it.second.bSubPlateDetect == FALSE) continue; //else if (type == LWS_SEND_PACK_TYPE::LSPT_ALARM_EVENT && it.second.bSubAlarmEvent == FALSE) continue; //else if (type == LWS_SEND_PACK_TYPE::LSPT_TRAFFIC_FLOW && it.second.bSubTrafficFlow == FALSE) continue; //if (type == LWS_SEND_PACK_TYPE::LSPT_BOLT_DETECT && it.second.bSubBoltDetect == FALSE) continue; if (it.second.refer > 0) { int ret = lws_write(it.first, pSend, len - (int)1, protocol); if (ret <= 0) { it.second.send_fail_count++; } else { it.second.send_size += ret; it.second.send_count++; } } } } else if (protocol == lws_write_protocol::LWS_WRITE_TEXT) { assert(len <= MAX_PAYLOAD_SIZE); if (len >= MAX_PAYLOAD_SIZE) { pNew = new uint8_t[len + LWS_PRE]; pSend = pNew + LWS_PRE; } memcpy(pSend, data, len); lock_guard lock(m_mtxSession); for (auto& it : m_mapLwsSession) { //订阅 //if (type == LWS_SEND_PACK_TYPE::LSPT_PLATE_DETECT && it.second.bSubPlateDetect == FALSE) continue; //else if (type == LWS_SEND_PACK_TYPE::LSPT_ALARM_EVENT && it.second.bSubAlarmEvent == FALSE) continue; //else if (type == LWS_SEND_PACK_TYPE::LSPT_TRAFFIC_FLOW && it.second.bSubTrafficFlow == FALSE) continue; //if (type == LWS_SEND_PACK_TYPE::LSPT_BOLT_DETECT && it.second.bSubBoltDetect == FALSE) continue; if (it.second.refer > 0) { int ret = lws_write(it.first, pSend, len, protocol); if (ret <= 0) { it.second.send_fail_count++; } else { it.second.send_size += ret; it.second.send_count++; } } } } else { assert(0); } if (pNew) { delete[] pNew; pNew = nullptr; } } return FALSE; } int CLWSServer::GetLwsSessionNum() { return m_mapLwsSession.size(); } void CLWSServer::Establishe(lws* wsi) { char ip[32]; lws_get_peer_simple(wsi, ip, 32); char log[100]; sprintf_s(log, 100, "[前端]有新链接:%s", ip); CSimpleLog::Info(log); lock_guard lock(m_mtxSession); per_session_data& session_data = m_mapLwsSession[wsi]; session_data.refer++; time(&session_data.tmConnect); session_data.wsi = wsi; session_data.context = lws_get_context(wsi); memcpy(session_data.ip, ip, 32); } void CLWSServer::Close(lws* wsi) { m_mapLwsSession[wsi].refer--; } void CLWSServer::Destroy(lws* wsi) { char log[100] = { 0 }; { lock_guard lock(m_mtxSession); auto it = m_mapLwsSession.find(wsi); if (it != m_mapLwsSession.end()) { sprintf_s(log, 100, "[前端]链接断开:%s", it->second.ip); m_mapLwsSession.erase(it); } } if (log[0] != 0x00) CSimpleLog::Info(log); } #include void CLWSServer::Recv(lws* wsi, void* in, size_t len) { // 判断是否二进制消息 char ip[32]; lws_get_peer_simple(wsi, ip, 32); TRACE("%s\r\n", ip); int bin = lws_frame_is_binary(wsi); if (bin) { CSimpleLog::Info("[前端]收到二进制数据"); return; } if (len < 5) return; if (((char*)in)[0x00] != '{') return; using namespace rapidjson; Document doc; { lock_guard lock(m_mtxRecv); int newjsonlen = utf82gbk((char*)g_recv_buf + LWS_PRE, MAX_PAYLOAD_SIZE, (char*)in, len) - 1; TRACE("recv message : %s\n", (char*)g_recv_buf + LWS_PRE); CSimpleLog::Info("recv:\r\n" + CString(g_recv_buf + LWS_PRE)); if (doc.Parse((char*)g_recv_buf + LWS_PRE, newjsonlen).HasParseError() || doc.HasMember("cmd") == false || doc["cmd"].IsString() == false) { //string result = "{ \"cmd\":\"error\",\"code\":400,\"msg\":\"400 JSON parse error.\"}"; //lock_guard lock(m_mtxSend); //memcpy(g_send_buf + LWS_PRE, result.c_str(), result.length() + 1); //lws_write(wsi, g_send_buf + LWS_PRE, result.length(), LWS_WRITE_TEXT); //CSimpleLog::Error("[前端]数据解析出错:" + CString((char*)g_recv_buf + LWS_PRE, newjsonlen) + "."); return; } } auto pTemp = new uint8_t[500]; //准备回包的数据 auto pData = pTemp + LWS_PRE; auto cmd = doc["cmd"].GetString(); if (strcmp("heartbeat.ping", cmd) == 0) { SYSTEMTIME tm; GetLocalTime(&tm); sprintf_s((char*)pData, 200, "{\"cmd\":\"heartbeat.pong\",\"time\":\"%04d-%02d-%02d %02d:%02d:%02d.%03d\"}", tm.wYear, tm.wMonth, tm.wDay, tm.wHour, tm.wMinute, tm.wSecond, tm.wMilliseconds); lws_write(wsi, pData, strlen((char*)pData), LWS_WRITE_TEXT); } else if (strcmp("sub_notify", cmd) == 0) { string imei_idx; auto code = HandleSubNotify(wsi, doc, imei_idx); doc.AddMember("code", code, doc.GetAllocator()); StringBuffer buffer; Writer writer(buffer); doc.Accept(writer); const char* output = buffer.GetString(); int len = buffer.GetLength(); memcpy(pData, output, len); lws_write(wsi, pData, len, LWS_WRITE_TEXT); } else if (strcmp("unsub_notify", cmd) == 0) { auto code = HanldeUnsubNotify(wsi, doc); doc.AddMember("code", code, doc.GetAllocator()); StringBuffer buffer; Writer writer(buffer); doc.Accept(writer); const char* output = buffer.GetString(); int len = buffer.GetLength(); memcpy(pData, output, len); lws_write(wsi, pData, len, LWS_WRITE_TEXT); } else if (strcmp("login", cmd) == 0) { auto code = HandleLogin(wsi, doc); doc.AddMember("code", code, doc.GetAllocator()); StringBuffer buffer; Writer writer(buffer); doc.Accept(writer); const char* output = buffer.GetString(); int len = buffer.GetLength(); memcpy(pData, output, len); lws_write(wsi, pData, len, LWS_WRITE_TEXT); //主动发送未处理报警 if (code == 200) SendUnAckAlarm(wsi); } else if (strcmp("query_alm_unack", cmd) == 0) { auto code = SendUnAckAlarm(wsi); if (code != 200) { doc.AddMember("code", code, doc.GetAllocator()); StringBuffer buffer; Writer writer(buffer); doc.Accept(writer); const char* output = buffer.GetString(); int len = buffer.GetLength(); memcpy(pData, output, len); lws_write(wsi, pData, len, LWS_WRITE_TEXT); } } else if (strcmp("query_hist", cmd) == 0) { //历史数据 auto code = HandleQueryHist(wsi, doc); doc.AddMember("code", code, doc.GetAllocator()); StringBuffer buffer; Writer writer(buffer); doc.Accept(writer); const char* output = buffer.GetString(); int len = buffer.GetLength(); memcpy(pData, output, len); lws_write(wsi, pData, len, LWS_WRITE_TEXT); } else if (strcmp("query_hist_confirm", cmd) == 0) { auto code = HandleQueryHistConfirm(wsi, doc); //string result = "{\"cmd\":\"query_hist_confirm\",\"code\":" + to_string(code) + ",\"msg\":\"\"}"; //memcpy(g_send_buf + LWS_PRE, result.c_str(), result.length() + 1); //lws_write(wsi, g_send_buf + LWS_PRE, result.length(), LWS_WRITE_TEXT); } else if (strcmp("conf_read", cmd) == 0)//配置读取 { auto code = HandleConfRead(wsi, doc); if (code != 200) { string result = "{\"cmd\":\"conf_read\",\"code\":" + to_string(code) + ",\"msg\":\"\"}"; memcpy(pData, result.c_str(), result.length() + 1); lws_write(wsi, pData, result.length(), LWS_WRITE_TEXT); } } else if (strcmp("conf_write", cmd) == 0) { auto code = HandleConfWrite(wsi, doc); rapidjson::Document::AllocatorType &allocator = doc.GetAllocator(); //获取分配器 if (doc.HasMember("conf")) doc.RemoveMember("conf"); doc.AddMember("code", code, allocator); StringBuffer buffer; Writer writer(buffer); doc.Accept(writer); memcpy(pData, buffer.GetString(), buffer.GetLength()); lws_write(wsi, pData, buffer.GetLength(), LWS_WRITE_TEXT); } else if (strcmp("alm_ack", cmd) == 0) {//报警受理 string ack_time, ack_name; auto code = HandleAlarmAck(wsi, doc, ack_time, ack_name); rapidjson::Document::AllocatorType& allocator = doc.GetAllocator(); //获取分配器 if (code == 200 && ack_time.length()) { { Value str_value(kStringType); str_value.SetString(ack_time.c_str(), ack_time.length()); doc.AddMember("ack_time", str_value, allocator); } { Value str_value(kStringType); char utf[50] = { 0 }; int len = gbk2utf8(utf, 50, ack_name.c_str()) - 1; str_value.SetString(utf, len); doc.AddMember("ack_name", str_value, allocator); } } doc.AddMember("code", code, allocator); StringBuffer buffer; Writer writer(buffer); doc.Accept(writer); if (code == 200) { SendPackToALLClient_with_noEncode((uint8_t*)buffer.GetString(), buffer.GetLength()); } else { memcpy(pData, buffer.GetString(), buffer.GetLength()); lws_write(wsi, pData, buffer.GetLength(), LWS_WRITE_TEXT); } } else if (strcmp("alm_handle", cmd) == 0) { //报警受理 string handle_time, hanlde_info, handle_name; auto code = HandleAlarmHandle(wsi, doc, handle_time, handle_name, hanlde_info); rapidjson::Document::AllocatorType& allocator = doc.GetAllocator(); //获取分配器 doc.RemoveMember("hanlde_info"); if (code == 200 && handle_time.length()) { { Value str_value(kStringType); str_value.SetString(handle_time.c_str(), handle_time.length()); doc.AddMember("handle_time", str_value, allocator); } { Value str_value(kStringType); char utf[50] = { 0 }; int len = gbk2utf8(utf, 50, handle_name.c_str()) - 1; str_value.SetString(utf, len); doc.AddMember("handle_name", str_value, allocator); } { Value str_value(kStringType); char utf[250] = { 0 }; int len = gbk2utf8(utf, 250, hanlde_info.c_str()) - 1; str_value.SetString(utf, len); doc.AddMember("hanlde_info", str_value, allocator); } } doc.AddMember("code", code, allocator); StringBuffer buffer; Writer writer(buffer); doc.Accept(writer); if (code == 200) { SendPackToALLClient_with_noEncode((uint8_t*)buffer.GetString(), buffer.GetLength()); } else { memcpy(pData, buffer.GetString(), buffer.GetLength()); lws_write(wsi, pData, buffer.GetLength(), LWS_WRITE_TEXT); } } else if (strcmp("sync", cmd) == 0) { int code = 200; rapidjson::Document::AllocatorType& allocator = doc.GetAllocator(); //获取分配器 { lock_guard lock(m_mtxSession); per_session_data& session_data = m_mapLwsSession[wsi]; if (strstr(session_data.token, "AAAAAAAA") == nullptr) { code = 403; doc.AddMember("code", code, allocator); doc.AddMember("msg", "Forbidden ! Without Permission !", allocator); } } //同步数据库数据 if (code == 200) { auto ret = CMonitorObjectMng::Instance()->LoadMonitorTree(); ret &= CMonitorObjectMng::Instance()->LoadHistoryData(); if (ret) { doc.AddMember("code", 200, allocator); } else { doc.AddMember("code", 500, allocator); } } StringBuffer buffer; Writer writer(buffer); doc.Accept(writer); memcpy(pData, buffer.GetString(), buffer.GetLength()); lws_write(wsi, pData, buffer.GetLength(), LWS_WRITE_TEXT); } else if (strcmp("new_data", cmd) == 0) { } else { string result = "{ \"cmd\":\"unkonw_cmd\",\"msg\":\"403 not realizes .\"}"; memcpy(pData, result.c_str(), result.length() + 1); lws_write(wsi, pData, result.length(), LWS_WRITE_TEXT); CSimpleLog::Error(CString("[前端]数据解析未实现:")); } delete[] pTemp; } void CLWSServer::GetSessionDesc(std::map& session_desc) { //for (auto& it : m_mapLwsSession) //{ // session_desc[(DWORD_PTR)it.first].Format("%s[上线时间:%s]%s[已发送:%.3f MB]", it.second.ip, // COleDateTime(it.second.tmConnect).Format("%Y-%m-%d %H:%M:%S"), // (it.second.bSubBoltDetect & it.second.bSubRailGapDetect) ? // "[已订阅所有]" :( // (!it.second.bSubBoltDetect & !it.second.bSubRailGapDetect) ? // "[未订阅]" : // (it.second.bSubBoltDetect ? CString("[已订阅报警事件]") : CString("")) + // (it.second.bSubRailGapDetect ? CString("[已订阅车牌检测]") : CString("")) // ), it.second.send_size / 1024.0 / 1024.0); //} } uint32_t CLWSServer::FindJsonPack(const char* CH, uint32_t len) { if (len <= 1 || CH[0] != '{') return 0; uint32_t packlen = 0; int first = 0, end = 0; for (size_t i = 0; i < len; i++) { if (CH[i] == '{') { ++first; } else if (CH[i] == '}') { ++end; if (first == end) { packlen = i + 1; break; } } } return packlen; } int CLWSServer::HandleLogin(lws* wsi, rapidjson::Document& doc) { if (doc.HasMember("token") && doc["token"].IsString()) { string token = doc["token"].GetString(); if (token.compare("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA") == 0) { lock_guard lock(m_mtxSession); auto it = m_mapLwsSession.find(wsi); if (it == m_mapLwsSession.end()) return 500; strncpy_s(it->second.token, 37, token.c_str(), token.length()); strncpy_s(it->second.username, sizeof(it->second.username), "系统管理员", strlen("系统管理员")); strncpy_s(it->second.node, sizeof(it->second.node), "100000", strlen("100000")); it->second.isLogin = true; return 200; } CString sql; sql.Format("SELECT username,node FROM rm_user WHERE token = '%s';", token.c_str()); COdbcStatement stmt; if (FALSE == CDBConnectPool::Instance()->DBQuery(stmt, sql)) { CSimpleLog::Error("[前端]查询语句出错:" + sql); return 404; } char username[50]; char node[50]; int nCol = 1; stmt.BindCharCol(nCol++, username, sizeof(username)); stmt.BindCharCol(nCol++, node, sizeof(node)); if (stmt.FetchNext() != 0) return 401; lock_guard lock(m_mtxSession); auto it = m_mapLwsSession.find(wsi); if (it == m_mapLwsSession.end()) return 500; strncpy_s(it->second.token, 37, token.c_str(), token.length()); strncpy_s(it->second.username, sizeof(it->second.username), username, strlen(username)); strncpy_s(it->second.node, sizeof(it->second.node), node, strlen(node)); it->second.isLogin = true; return 200; } else { return 400; } } int CLWSServer::HandleSubNotify(lws* wsi, rapidjson::Document& doc, std::string& imei_idx) { if (doc.HasMember("tag") && doc["tag"].IsString()) { string tag = doc["tag"].GetString(); int npos = tag.rfind('.'); string momp = tag.substr(0, npos); string type = tag.substr(npos + 1); if (type.compare("resist") == 0) { lock_guard lock(m_mtxSession); auto it = m_mapLwsSession.find(wsi); if (it == m_mapLwsSession.end()) return 500; //if (it->second.isLogin == FALSE) return 401; if (!CMonitorObjectMng::Instance()->MOMP2IMEI(momp, imei_idx)) return 404; it->second.m_lstSubReal.push_back(imei_idx); return 200; } return 400; } else { return 400; } } int CLWSServer::HanldeUnsubNotify(lws* wsi, rapidjson::Document& doc) { if (doc.HasMember("tag") && doc["tag"].IsString()) { string tag = doc["tag"].GetString(); int npos = tag.rfind('.'); string momp = tag.substr(0, npos); string type = tag.substr(npos + 1); if (type.compare("resist") == 0) { lock_guard lock(m_mtxSession); auto it = m_mapLwsSession.find(wsi); if (it == m_mapLwsSession.end()) return 500; string imei_idx; if (!CMonitorObjectMng::Instance()->MOMP2IMEI(momp, imei_idx)) return 404; for (auto i = it->second.m_lstSubReal.begin(); i != it->second.m_lstSubReal.end();) { if ((*i).compare(imei_idx) == 0) { i = it->second.m_lstSubReal.erase(i); continue; } i++; } return 200; } return 500; } else { return 400; } } int CLWSServer::HandleQueryHist(lws* wsi, rapidjson::Document& doc) { if (doc.HasMember("tag") && doc["tag"].IsString()) { string tag = doc["tag"].GetString(); int npos = tag.rfind('.'); string mo_mp = tag.substr(0, npos); string type = tag.substr(npos + 1); if (mo_mp.compare("undefined") == 0) { CSimpleLog::Error("[前端]收到未定义的请求"); return 401; } if (type.compare("resist") == 0) //阻力数据 { CTime ctStart, ctEnd; if (doc.HasMember("time") && doc["time"].IsString()) { string query_time = doc["time"].GetString(); int pos = query_time.find('~'); if (pos == -1) return 400; string start = query_time.substr(0, pos); string end = query_time.substr(pos + 1); try { int year, month, day, hour, minute, second; sscanf_s(start.c_str(), "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second); ctStart = CTime(year, month, day, hour, minute, second); sscanf_s(end.c_str(), "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second); ctEnd = CTime(year, month, day, hour, minute, second); } catch (CException* ) { return 400; } } else { return 400; } string imei_idx; if (!CMonitorObjectMng::Instance()->MOMP2IMEI(mo_mp, imei_idx)) return 404; string imei, idx; if (!CMonitorObjectMng::Instance()->spiltByPoint(imei_idx, imei, idx)) return 400; int index = atoi(idx.c_str()); auto pDevice = CDeviceMng::Instance()->Find(imei); if (pDevice == nullptr) return 404; lock_guard lock(m_mtxSession); auto it = m_mapLwsSession.find(wsi); if (it == m_mapLwsSession.end()) return 500; //if (it->second.isLogin == FALSE) return 401; it->second.bWork = false; if (it->second.thread_hist) { it->second.thread_hist->join(); delete it->second.thread_hist; it->second.thread_hist = nullptr; } LPHISTORY_QUERY query_hist = new HISTORY_QUERY; query_hist->idx = index; query_hist->imei = imei; query_hist->mo_mp = mo_mp; time_t tmStart = ctStart.GetTime(); query_hist->tmStart = tmStart * 1000; query_hist->tmEnd = ctEnd.GetTime() * 1000; query_hist->type = "resist"; query_hist->wsi = wsi; it->second.bWork = true; time_t tmNow; time(&tmNow); if (tmStart < g_stStart - 7200 || tmNow - tmStart > MAX_SAVE_TIME / 1000) { //超过当天,赋值当天 临时 //auto end = CTime(ctStart.GetYear(), ctStart.GetMonth(), ctStart.GetDay(), 23, 59, 59); //改为限定24小时 auto end = ctStart + CTimeSpan(1, 0, 0, 0); if (ctEnd > end) query_hist->tmEnd = end.GetTime() * 1000; it->second.thread_hist = new thread(CLWSServer::ThreadProcForQueryHistDB, query_hist); } else { //实时也改为限定24小时 auto end = ctStart + CTimeSpan(1, 0, 0, 0); if (ctEnd > end) query_hist->tmEnd = end.GetTime() * 1000; it->second.thread_hist = new thread(CLWSServer::ThreadProcForQueryHist, query_hist); } return 200; } return 400; } else { return 400; } } int CLWSServer::HandleQueryHistConfirm(lws* wsi, rapidjson::Document& doc) { if (doc.HasMember("tag") && doc["tag"].IsString()) { string tag = doc["tag"].GetString(); int npos = tag.rfind('.'); string momp = tag.substr(0, npos); string type = tag.substr(npos + 1); if (type.compare("resist") == 0) { lock_guard lock(m_mtxSession); auto it = m_mapLwsSession.find(wsi); if (it == m_mapLwsSession.end()) return 500; it->second.bBlock = false; //string imei_idx; //if (!CMonitorObjectMng::Instance()->MOMP2IMEI(momp, imei_idx)) return 404; //for (auto i = it->second.m_lstSubReal.begin(); i != it->second.m_lstSubReal.end();) //{ // if ((*i).compare(imei_idx) == 0) // { // i = it->second.m_lstSubReal.erase(i); // continue; // } // i++; //} return 200; } return 500; } else { return 400; } } int CLWSServer::HandleConfRead(lws* wsi, rapidjson::Document& doc) { //读取类型 if (doc.HasMember("type") == false || doc["type"].IsString() == false) return 400; if (doc.HasMember("tag") == false || doc["tag"].IsString() == false) return 400; string type = doc["type"].GetString(); string tag = doc["tag"].GetString(); using namespace rapidjson; rapidjson::Document::AllocatorType &allocator = doc.GetAllocator(); //获取分配器 if (type.compare("monitor.alarm.max_over_limit") == 0) //最大值超限 { int nPos = tag.find('.'); if (nPos != -1) { auto mo = tag.substr(0, nPos); int nPos2 = tag.find('.', nPos + 1); if (nPos2 != -1) { auto mp = tag.substr(nPos + 1, nPos2 - nPos - 1); int nPos3 = tag.find('.', nPos2 + 1); if (nPos3 != -1) { auto no = tag.substr(nPos2 + 1, nPos3 - nPos2 - 1); if (mo.length() > 0 && mp.length() > 0 && no.length() > 0) { int nNo = atoi(no.c_str()) - 1; auto pBase = CResistAlarmMng::Instance()->Find(mo, mp, nNo, eZL_ALARMTYPE::MAX_OVER_LIMIT); if (pBase) { string name1, name2, name3; CMonitorObjectMng::Instance()->GetNameByMoMp(mo + "." + mp, name1, name2, name3); assert(pBase->type == eZL_ALARMTYPE::MAX_OVER_LIMIT); auto pInfo = (MAX_OVER_LIMIT_INFO*)pBase; Value confArray(kArrayType); Value confName(kObjectType); confName.AddMember("name", "enable", allocator); string enable = pInfo->enable ? "true" : "false"; Value str_value(kStringType); str_value.SetString(enable.c_str(), enable.length()); confName.AddMember("val", str_value, allocator); confArray.PushBack(confName, allocator); string alarm, warn, f_alarm, f_warn; Value label_name, label_name2; if (pInfo->alarm_high_limit != SHORT_MAX) { Value confAlarmHigh(kObjectType); if (nNo == 2) confAlarmHigh.AddMember("name", "d_alarm_high_limit", allocator); else { confAlarmHigh.AddMember("name", "lock_alarm_high_limit", allocator); if (nNo == 0) { label_name.SetString(name1.c_str(), name1.size()); confAlarmHigh.AddMember("label", label_name, allocator); } else if (nNo == 1) { label_name.SetString(name2.c_str(), name2.size()); confAlarmHigh.AddMember("label", label_name, allocator); } } alarm = to_string(pInfo->alarm_high_limit); Value alarm_value; alarm_value.SetString(alarm.c_str(), alarm.size()); confAlarmHigh.AddMember("val", alarm_value, allocator); confArray.PushBack(confAlarmHigh, allocator); } if (pInfo->warn_high_limit != SHORT_MAX) { Value confWarnHigh(kObjectType); if (nNo == 2) confWarnHigh.AddMember("name", "d_warn_high_limit", allocator); else { confWarnHigh.AddMember("name", "lock_warn_high_limit", allocator); if (nNo == 0) { label_name2.SetString(name1.c_str(), name1.size()); confWarnHigh.AddMember("label", label_name2, allocator); } else if (nNo == 1) { label_name2.SetString(name2.c_str(), name2.size()); confWarnHigh.AddMember("label", label_name2, allocator); } } warn = to_string(pInfo->warn_high_limit); str_value.SetString(warn.c_str(), warn.length()); confWarnHigh.AddMember("val", str_value, allocator); confArray.PushBack(confWarnHigh, allocator); } if (pInfo->f_alarm_high_limit != SHORT_MAX) { Value f_confAlarmHigh(kObjectType); if (nNo == 2)f_confAlarmHigh.AddMember("name", "f_alarm_high_limit", allocator); else f_confAlarmHigh.AddMember("name", "keep_alarm_high_limit", allocator); f_alarm = to_string(pInfo->f_alarm_high_limit); str_value.SetString(f_alarm.c_str(), f_alarm.length()); f_confAlarmHigh.AddMember("val", str_value, allocator); confArray.PushBack(f_confAlarmHigh, allocator); } if (pInfo->f_warn_high_limit != SHORT_MAX) { Value f_confWarnHigh(kObjectType); if (nNo == 2) f_confWarnHigh.AddMember("name", "f_warn_high_limit", allocator); else f_confWarnHigh.AddMember("name", "keep_warn_high_limit", allocator); f_warn = to_string(pInfo->f_warn_high_limit); str_value.SetString(f_warn.c_str(), f_warn.length()); f_confWarnHigh.AddMember("val", str_value, allocator); confArray.PushBack(f_confWarnHigh, allocator); } doc.AddMember("conf", confArray, allocator); //生成字符串 StringBuffer buffer; rapidjson::Writer writer(buffer); doc.Accept(writer); string str/* = ANSItoUTF8(buffer.GetString())*/; //int len = str.GetLength(); //auto pData = buffer.GetString(); uint8_t* pSend = new uint8_t[LWS_PRE + str.length()]; memcpy(pSend + LWS_PRE, str.c_str(), str.length()); lws_write(wsi, pSend + LWS_PRE, str.length(), LWS_WRITE_TEXT); delete[] pSend; pSend = nullptr; } else { Value confArray(kArrayType); doc.AddMember("conf", confArray, allocator); //生成字符串 StringBuffer buffer; rapidjson::Writer writer(buffer); doc.Accept(writer); int len = buffer.GetLength(); uint8_t* pSend = new uint8_t[LWS_PRE + len]; memcpy(pSend + LWS_PRE, buffer.GetString(), len); lws_write(wsi, pSend + LWS_PRE, len, LWS_WRITE_TEXT); delete[] pSend; pSend = nullptr; } return 200; } } } } return 400; } else if (type.compare("monitor.resist.rename") == 0) //设置曲线别名 { string name1, name2, name3; CMonitorObjectMng::Instance()->GetNameByMoMp(tag, name1, name2, name3); Value conf(kArrayType); Value value(kStringType); char utf[200]; if (name1.length()) { int str_len = gbk2utf8(utf, 200, name1.c_str()); value.SetString(utf, str_len - 1, allocator); } else { int str_len = gbk2utf8(utf, 200,"1号测力曲线"); value.SetString(utf, str_len - 1, allocator); } conf.PushBack(value, allocator); if (name2.length()) { int str_len = gbk2utf8(utf, 200, name2.c_str()); value.SetString(utf, str_len - 1, allocator); } else { int str_len = gbk2utf8(utf, 200, "2号测力曲线"); value.SetString(utf, str_len - 1, allocator); } conf.PushBack(value, allocator); if (name3.length()) { int str_len = gbk2utf8(utf, 200, name3.c_str()); value.SetString(utf, str_len - 1, allocator); } else { int str_len = gbk2utf8(utf, 200, "转换阻力曲线"); value.SetString(utf, str_len - 1, allocator); } conf.PushBack(value, allocator); doc.AddMember("conf", conf, allocator); //生成字符串 StringBuffer buffer; rapidjson::Writer writer(buffer); doc.Accept(writer); int len = buffer.GetLength(); uint8_t* pSend = new uint8_t[LWS_PRE + len]; memcpy(pSend + LWS_PRE, buffer.GetString(), len); lws_write(wsi, pSend + LWS_PRE, len, LWS_WRITE_TEXT); delete[] pSend; pSend = nullptr; return 200; } else if (type.compare("monitor.switch_direct.rename") == 0) { string direct1, direct2; CMonitorObjectMng::Instance()->GetDirectByMoMp(tag, direct1, direct2); Value conf(kArrayType); Value value(kStringType); char utf[200]; int str_len = gbk2utf8(utf, 200, direct1.c_str()); value.SetString(utf, str_len - 1, allocator); conf.PushBack(value, allocator); str_len = gbk2utf8(utf, 200, direct2.c_str()); value.SetString(utf, str_len - 1, allocator); conf.PushBack(value, allocator); doc.AddMember("conf", conf, allocator); //生成字符串 StringBuffer buffer; rapidjson::Writer writer(buffer); doc.Accept(writer); int len = buffer.GetLength(); uint8_t* pSend = new uint8_t[LWS_PRE + len]; memcpy(pSend + LWS_PRE, buffer.GetString(), len); lws_write(wsi, pSend + LWS_PRE, len, LWS_WRITE_TEXT); delete[] pSend; pSend = nullptr; return 200; } else if (type.compare("monitor.alarm.friction_over_limit") == 0){ int nPos = tag.find('.'); if (nPos != -1) { auto mo = tag.substr(0, nPos); int nPos2 = tag.find('.', nPos + 1); if (nPos2 != -1) { auto mp = tag.substr(nPos + 1, nPos2 - nPos - 1); int nPos3 = tag.find('.', nPos2 + 1); if (nPos3 != -1) { auto no = tag.substr(nPos2 + 1, nPos3 - nPos2 - 1); if (mo.length() > 0 && mp.length() > 0 && no.length() > 0) { int nNo = atoi(no.c_str()) - 1; if (nNo != 2) return 400; auto pBase = CResistAlarmMng::Instance()->Find(mo, mp, nNo, eZL_ALARMTYPE::FRICTION_OVER_LIMIT); if (pBase) { assert(pBase->type == eZL_ALARMTYPE::FRICTION_OVER_LIMIT); auto pInfo = (FRICTION_OVER_LIMIT_INFO*)pBase; //换成 yyjson auto res_doc = yyjson_mut_doc_new(nullptr); auto res_obj = yyjson_mut_obj(res_doc); yyjson_mut_doc_set_root(res_doc, res_obj); yyjson_mut_obj_add_str(res_doc, res_obj, "cmd", "conf_read"); yyjson_mut_obj_add_str(res_doc, res_obj, "type", type.c_str()); yyjson_mut_obj_add_str(res_doc, res_obj, "tag", tag.c_str()); //conf auto res_arr = yyjson_mut_arr(res_doc); yyjson_mut_obj_add_val(res_doc, res_obj, "conf", res_arr); { auto obj = yyjson_mut_obj(res_doc); yyjson_mut_obj_add_str(res_doc, obj, "name", "enable"); yyjson_mut_obj_add_str(res_doc, obj, "val", pInfo->enable ? "true" : "false"); yyjson_mut_arr_add_val(res_arr, obj); } { auto obj = yyjson_mut_obj(res_doc); yyjson_mut_obj_add_str(res_doc, obj, "name", "up_alarm_low_limit"); yyjson_mut_obj_add_strcpy(res_doc, obj, "val", to_string(pInfo->up_alarm_low_limit).c_str()); yyjson_mut_arr_add_val(res_arr, obj); } { auto obj = yyjson_mut_obj(res_doc); yyjson_mut_obj_add_str(res_doc, obj, "name", "up_warn_low_limit"); yyjson_mut_obj_add_strcpy(res_doc, obj, "val", to_string(pInfo->up_warn_low_limit).c_str()); yyjson_mut_arr_add_val(res_arr, obj); } { auto obj = yyjson_mut_obj(res_doc); yyjson_mut_obj_add_str(res_doc, obj, "name", "dw_alarm_high_limit"); yyjson_mut_obj_add_strcpy(res_doc, obj, "val", to_string(pInfo->dw_alarm_high_limit).c_str()); yyjson_mut_arr_add_val(res_arr, obj); } { auto obj = yyjson_mut_obj(res_doc); yyjson_mut_obj_add_str(res_doc, obj, "name", "dw_warn_high_limit"); yyjson_mut_obj_add_strcpy(res_doc, obj, "val", to_string(pInfo->dw_warn_high_limit).c_str()); yyjson_mut_arr_add_val(res_arr, obj); } size_t len = 0; auto res_json = yyjson_mut_write(res_doc, YYJSON_WRITE_NOFLAG, &len); ASSERT(res_json); uint8_t* pSend = new uint8_t[LWS_PRE + len]; memcpy(pSend + LWS_PRE, res_json, len); lws_write(wsi, pSend + LWS_PRE, len, LWS_WRITE_TEXT); delete[] pSend; pSend = nullptr; free((void*)res_json); yyjson_mut_doc_free(res_doc); } else { Value confArray(kArrayType); doc.AddMember("conf", confArray, allocator); //生成字符串 StringBuffer buffer; rapidjson::Writer writer(buffer); doc.Accept(writer); int len = buffer.GetLength(); uint8_t* pSend = new uint8_t[LWS_PRE + len]; memcpy(pSend + LWS_PRE, buffer.GetString(), len); lws_write(wsi, pSend + LWS_PRE, len, LWS_WRITE_TEXT); delete[] pSend; pSend = nullptr; } return 200; } } } } return 400; } else { return 500; } } int CLWSServer::HandleConfWrite(lws* wsi, rapidjson::Document& jsondoc) { //读取类型 if (jsondoc.HasMember("type") == false || jsondoc["type"].IsString() == false) return 400; if (jsondoc.HasMember("tag") == false || jsondoc["tag"].IsString() == false) return 400; if (jsondoc.HasMember("conf") == false || jsondoc["conf"].IsArray() == false) return 400; string type = jsondoc["type"].GetString(); string tag = jsondoc["tag"].GetString(); auto conf = jsondoc["conf"].GetArray(); using namespace rapidjson; rapidjson::Document::AllocatorType &allocator = jsondoc.GetAllocator(); //获取分配器 if (type.compare("monitor.alarm.max_over_limit") == 0) { int nPos = tag.find('.'); if (nPos != -1) { auto mo = tag.substr(0, nPos); int nPos2 = tag.find('.', nPos + 1); if (nPos2 != -1) { auto mp = tag.substr(nPos + 1, nPos2 - nPos - 1); int nPos3 = tag.find('.', nPos2 + 1); if (nPos3 != -1) { auto no = tag.substr(nPos2 + 1, nPos3 - nPos2 - 1); if (mo.length() > 0 && mp.length() > 0 && no.length() > 0) { int nNo = atoi(no.c_str()) - 1; bool enable = false; short alarm = MAXSHORT, warn = MAXSHORT, f_alarm = MAXSHORT, f_warn = MAXSHORT; for (SizeType i = 0; i < conf.Size(); i++) { if (conf[i].HasMember("name") && conf[i]["name"].IsString() && conf[i].HasMember("val") && conf[i]["val"].IsString()) { string name = conf[i]["name"].GetString(); string val = conf[i]["val"].GetString(); if (name.compare("enable") == 0) { if (val.compare("false") == 0) { enable = false; } else { enable = true; } } else if (name.compare("lock_alarm_high_limit") == 0) { alarm = atoi(val.c_str()); } else if (name.compare("lock_warn_high_limit") == 0) { warn = atoi(val.c_str()); } else if (name.compare("d_alarm_high_limit") == 0) { alarm = atoi(val.c_str()); } else if (name.compare("d_warn_high_limit") == 0) { warn = atoi(val.c_str()); } else if (name.compare("keep_alarm_high_limit") == 0) { f_alarm = atoi(val.c_str()); } else if (name.compare("keep_warn_high_limit") == 0) { f_warn = atoi(val.c_str()); } else if (name.compare("f_alarm_high_limit") == 0) { f_alarm = atoi(val.c_str()); } else if (name.compare("f_warn_high_limit") == 0) { f_warn = atoi(val.c_str()); } } } auto pBase = CResistAlarmMng::Instance()->Find(mo, mp, nNo, eZL_ALARMTYPE::MAX_OVER_LIMIT); auto pInfo = (MAX_OVER_LIMIT_INFO*)pBase; if (pBase == nullptr) pInfo = new MAX_OVER_LIMIT_INFO; pInfo->enable = enable; pInfo->no = nNo; pInfo->type = eZL_ALARMTYPE::MAX_OVER_LIMIT; pInfo->alarm_high_limit = alarm; pInfo->warn_high_limit = warn; pInfo->f_alarm_high_limit = f_alarm; pInfo->f_warn_high_limit = f_warn; //生成字符串 Document doc; doc.SetArray(); for (SizeType i = 0; i < conf.Size(); i++) doc.PushBack(conf[i], allocator); StringBuffer buffer; rapidjson::Writer writer(buffer); doc.Accept(writer); if (pBase == nullptr) { auto ret = CResistAlarmMng::Instance()->Insert(mo, mp, nNo, (int)eZL_ALARMTYPE::MAX_OVER_LIMIT, pInfo); assert(ret); if (ret == false) { delete pInfo; return 500; } //add CString sql; sql.Format("INSERT INTO [rm_alarm_set]([mo],[mp],[no],[type],[conf],[time]) VALUES ('%s','%s',%d,%d,'%s','%I64u')", mo.c_str(), mp.c_str(), nNo, eZL_ALARMTYPE::MAX_OVER_LIMIT, buffer.GetString(), 0); if (CDBConnectPool::Instance()->DBExecuteSQL(sql) == FALSE) { assert(0); CSimpleLog::Error("语句执行失败" + sql); return 500; } } else { //update CString sql; sql.Format("update rm_alarm_set SET conf = '%s' WHERE mo = '%s' and mp = '%s' and no = %d and type = %d", buffer.GetString(), mo.c_str(), mp.c_str(), nNo, eZL_ALARMTYPE::MAX_OVER_LIMIT); if (CDBConnectPool::Instance()->DBExecuteSQL(sql) == FALSE) { assert(0); CSimpleLog::Error("语句执行失败" + sql); return 500; } } return 200; } } } } return 400; } else if (type.compare("monitor.resist.rename") == 0) { if (conf.Size() != 3) return 400; int nPos = tag.find('.'); if (nPos != -1) { auto mo = tag.substr(0, nPos); auto mp = tag.substr(nPos + 1, tag.length() - nPos - 1); string name1, name2, name3; //update name1 = conf[0].GetString(); name2 = conf[1].GetString(); name3 = conf[2].GetString(); CMonitorObjectMng::Instance()->SetNameByMoMp(tag, name1, name2, name3); //save CString sql; sql.Format("update rm_map set name1='%s',name2='%s',name3='%s' where mo = '%s' and mp = '%s';", name1.c_str(), name2.c_str(), name3.c_str(), mo.c_str(), mp.c_str()); auto ret = CDBConnectPool::Instance()->DBExecuteSQL(sql); if (false == ret) { CSimpleLog::Error("语句执行错误." + sql); return 500; } return 200; } return 400; } else if (type.compare("monitor.switch_direct.rename") == 0) { if (conf.Size() != 2) return 400; int nPos = tag.find('.'); if (nPos != -1) { auto mo = tag.substr(0, nPos); auto mp = tag.substr(nPos + 1, tag.length() - nPos - 1); string direct1, direct2; //update direct1 = conf[0].GetString(); direct2 = conf[1].GetString(); CMonitorObjectMng::Instance()->SetDirectByMoMp(tag, direct1, direct2); //save CString sql; sql.Format("update rm_map set direct1='%s',direct2='%s' where mo = '%s' and mp = '%s';", direct1.c_str(), direct2.c_str(), mo.c_str(), mp.c_str()); auto ret = CDBConnectPool::Instance()->DBExecuteSQL(sql); if (false == ret) { CSimpleLog::Error("语句执行错误." + sql); return 500; } return 200; } return 400; } else if (type.compare("monitor.alarm.friction_over_limit") == 0) { auto eType = eZL_ALARMTYPE::FRICTION_OVER_LIMIT; int nPos = tag.find('.'); if (nPos != -1) { auto mo = tag.substr(0, nPos); int nPos2 = tag.find('.', nPos + 1); if (nPos2 != -1) { auto mp = tag.substr(nPos + 1, nPos2 - nPos - 1); int nPos3 = tag.find('.', nPos2 + 1); if (nPos3 != -1) { auto no = tag.substr(nPos2 + 1, nPos3 - nPos2 - 1); if (mo.length() > 0 && mp.length() > 0 && no.length() > 0) { int nNo = atoi(no.c_str()) - 1; if (nNo != 2) return 400; bool enable = false; int up_alarm_low_limit = INT_MAX; int up_warn_low_limit = INT_MAX; int dw_alarm_high_limit = INT_MIN; int dw_warn_high_limit = INT_MIN; for (SizeType i = 0; i < conf.Size(); i++) { if (conf[i].HasMember("name") && conf[i]["name"].IsString() && conf[i].HasMember("val") && conf[i]["val"].IsString()) { string name = conf[i]["name"].GetString(); string val = conf[i]["val"].GetString(); if (name.compare("enable") == 0) { if (val.compare("false") == 0) { enable = false; } else { enable = true; } } else if (name.compare("up_alarm_low_limit") == 0) { up_alarm_low_limit = atoi(val.c_str()); } else if (name.compare("up_warn_low_limit") == 0) { up_warn_low_limit = atoi(val.c_str()); } else if (name.compare("dw_alarm_high_limit") == 0) { dw_alarm_high_limit = atoi(val.c_str()); } else if (name.compare("dw_warn_high_limit") == 0) { dw_warn_high_limit = atoi(val.c_str()); } } } auto pBase = CResistAlarmMng::Instance()->Find(mo, mp, nNo, eType); auto pInfo = (FRICTION_OVER_LIMIT_INFO*)pBase; if (pBase == nullptr) pInfo = new FRICTION_OVER_LIMIT_INFO; pInfo->enable = enable; pInfo->no = nNo; pInfo->type = eType; pInfo->up_alarm_low_limit = up_alarm_low_limit; pInfo->up_warn_low_limit = up_warn_low_limit; pInfo->dw_alarm_high_limit = dw_alarm_high_limit; pInfo->dw_warn_high_limit = dw_warn_high_limit; //生成字符串 Document doc; doc.SetArray(); for (SizeType i = 0; i < conf.Size(); i++) doc.PushBack(conf[i], allocator); StringBuffer buffer; rapidjson::Writer writer(buffer); doc.Accept(writer); if (pBase == nullptr) { auto ret = CResistAlarmMng::Instance()->Insert(mo, mp, nNo, (int)eType, pInfo); assert(ret); if (ret == false) { delete pInfo; return 500; } //add CString sql; sql.Format("INSERT INTO [rm_alarm_set]([mo],[mp],[no],[type],[conf],[time]) VALUES ('%s','%s',%d,%d,'%s','%I64u')", mo.c_str(), mp.c_str(), nNo, eType, buffer.GetString(), 0); if (CDBConnectPool::Instance()->DBExecuteSQL(sql) == FALSE) { ASSERT(0); CSimpleLog::Error("语句执行失败" + sql); return 500; } } else { //update CString sql; sql.Format("update rm_alarm_set SET conf = '%s' WHERE mo = '%s' and mp = '%s' and no = %d and type = %d", buffer.GetString(), mo.c_str(), mp.c_str(), nNo, eType); if (CDBConnectPool::Instance()->DBExecuteSQL(sql) == FALSE) { ASSERT(0); CSimpleLog::Error("语句执行失败" + sql); return 500; } } return 200; } } } } return 400; } return 500; } int CLWSServer::HandleAlarmAck(lws* wsi, rapidjson::Document& jsondoc, std::string& ack_time, std::string& handle_name) { if (jsondoc.HasMember("alarm_id") == false || jsondoc["alarm_id"].IsNumber() == false) return 400; { lock_guard lock(m_mtxSession); auto it = m_mapLwsSession.find(wsi); if (it != m_mapLwsSession.end()) { handle_name = it->second.username; } } SYSTEMTIME stOccr_time; int alarm_id = jsondoc["alarm_id"].GetInt(); { CTime ctNow = CTime::GetCurrentTime(); //删除内存数据 bool ret = CResistAlarmMng::Instance()->AckAlarm(alarm_id, handle_name, ctNow); //更新数据库 { ack_time = ctNow.Format("%Y-%m-%d %H:%M:%S"); CString sql; sql.Format("UPDATE [rm_alarm] SET ack_result = 1, ack_name='%s', ack_time='%s' WHERE ID = %d;", handle_name.c_str(), ack_time.c_str(), alarm_id); ret |= CDBConnectPool::Instance()->DBExecuteSQL(sql); } if (ret) return 200; return 400; } return 500; } int CLWSServer::HandleAlarmHandle(lws* wsi, rapidjson::Document& jsondoc, std::string& ack_time, std::string& handle_name, std::string& hanlde_info) { //读取类型 //if (jsondoc.HasMember("type") == false || jsondoc["type"].IsString() == false) // return 400; //if (jsondoc.HasMember("tag") == false || jsondoc["tag"].IsString() == false) // return 400; if (jsondoc.HasMember("alarm_id") == false || jsondoc["alarm_id"].IsNumber() == false) return 400; SYSTEMTIME stOccr_time; //string type = jsondoc["type"].GetString(); //string tag = jsondoc["tag"].GetString(); int alarm_id = jsondoc["alarm_id"].GetInt(); if (jsondoc.HasMember("hanlde_info") && jsondoc["hanlde_info"].IsString()) hanlde_info = UTF8toANSI(jsondoc["hanlde_info"].GetString()); { lock_guard lock(m_mtxSession); auto it = m_mapLwsSession.find(wsi); if (it != m_mapLwsSession.end()) { handle_name = it->second.username; } } //if (type.compare("monitor.alarm.max_over_limit") == 0) { CTime ctNow = CTime::GetCurrentTime(); //删除内存数据 bool ret = CResistAlarmMng::Instance()->HandleAlarm(alarm_id); //更新数据库 { ack_time = ctNow.Format("%Y-%m-%d %H:%M:%S"); CString sql; sql.Format("UPDATE [rm_alarm] SET handle_result = 1, handle_name='%s', handle_time='%s', handle_info='%s' WHERE ID = %d;", handle_name.c_str(), ack_time.c_str(), hanlde_info.c_str(), alarm_id); ret |= CDBConnectPool::Instance()->DBExecuteSQL(sql); } if (ret) return 200; return 400; } return 500; } void CLWSServer::SendRealResistData(const string& imei_idx, const int num, const vector& vctData0, const vector& vctData1, const vector& vctData2, const vector& vctResult, const CTime& atime) { if (m_mapLwsSession.size() == 0) return; bool bSub = false; { lock_guard lock(m_mtxSession); for (const auto& it :m_mapLwsSession) { if (strstr(it.second.token, "BBBBBBBB")) { bSub = true; break; } //if (it.second.isLogin == false) continue; for (const auto& ik : it.second.m_lstSubReal) { if (ik.compare(imei_idx) == 0) { bSub = true; break; } } if (bSub) break; } } //所有客户端都未订阅 if (!bSub) return; string mo_mp; auto ret = CMonitorObjectMng::Instance()->IMEI2MOMP(imei_idx, mo_mp); assert(ret); if (false == ret) { CString strLog; strLog.Format("imei(%s) 转换成 mo, mp 失败.请检测是否绑定.%s:%d", imei_idx.c_str(), __FUNCTION__, __LINE__); CSimpleLog::Error(strLog); } rapidjson::StringBuffer strBuf; GeneralResistData(mo_mp, num, 0, vctData0, vctData1, vctData2, vctResult, atime, strBuf); string strSend = strBuf.GetString(); lock_guard lock(m_mtxSend); memcpy_s(g_send_buf + LWS_PRE, MAX_PAYLOAD_SIZE, strSend.c_str(), strSend.length()); lock_guard lock2(m_mtxSession); for (const auto& it : m_mapLwsSession) { bSub = false; //if (it.second.isLogin == false) continue; if (strstr(it.second.token, "BBBBBBBB")) { bSub = true; } else { for (const auto& ik : it.second.m_lstSubReal) { if (ik.compare(imei_idx) == 0) { bSub = true; break; } } } if (bSub) { lws_write(it.first, g_send_buf + LWS_PRE, strSend.length(), LWS_WRITE_TEXT); } } } void CLWSServer::SendHumiTemp(const char* imei, const COleDateTime& dt, int humi, int temp) { if (m_mapLwsSession.size() == 0) return; bool bSub = false; { lock_guard lock(m_mtxSession); for (const auto& it : m_mapLwsSession) { if (strstr(it.second.token, "BBBBBBBB")) { bSub = true; break; } if (bSub) break; } } //所有客户端都未订阅 if (!bSub) return; 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", "new_data_notify"); yyjson_mut_obj_add_strcpy(doc, root, "time", dt.Format("%Y-%m-%d %H:%M:%S")); yyjson_mut_obj_add_int(doc, root, "humi", humi / 100); yyjson_mut_obj_add_int(doc, root, "temp", temp); string imei_idx = string(imei) + ".0"; string mo_mp; if (CMonitorObjectMng::Instance()->IMEI2MOMP(imei_idx, mo_mp)) { yyjson_mut_obj_add_strcpy(doc, root, "tag", (mo_mp + ".humi_temp").c_str()); size_t len; auto json = yyjson_mut_write(doc, 0, &len); if (json) { auto pTemp = new uint8_t[300]; auto pData = pTemp + LWS_PRE; { lock_guard lock(m_mtxSession); memcpy_s(pData, MAX_PAYLOAD_SIZE, json, len); for (const auto& it : m_mapLwsSession) { if (strstr(it.second.token, "BBBBBBBB")) { lws_write(it.first, pData, len, LWS_WRITE_TEXT); } } } delete[] pTemp; free((void*)json); } } imei_idx = string(imei) + ".1"; if (CMonitorObjectMng::Instance()->IMEI2MOMP(imei_idx, mo_mp)) { yyjson_mut_obj_remove_str(root, "tag"); yyjson_mut_obj_add_strcpy(doc, root, "tag", (mo_mp + ".humi_temp").c_str()); size_t len; auto json = yyjson_mut_write(doc, 0, &len); if (json) { auto pTemp = new uint8_t[200]; auto pData = pTemp + LWS_PRE; memcpy_s(pData, 200 - LWS_PRE, json, len); { lock_guard lock(m_mtxSession); for (const auto& it : m_mapLwsSession) { if (strstr(it.second.token, "BBBBBBBB")) { lws_write(it.first, pData, len, LWS_WRITE_TEXT); } } } delete[] pTemp; free((void*)json); } } imei_idx = string(imei) + ".2"; if (CMonitorObjectMng::Instance()->IMEI2MOMP(imei_idx, mo_mp)) { yyjson_mut_obj_remove_str(root, "tag"); yyjson_mut_obj_add_strcpy(doc, root, "tag", (mo_mp + ".humi_temp").c_str()); size_t len; auto json = yyjson_mut_write(doc, 0, &len); if (json) { auto pTemp = new uint8_t[200]; auto pData = pTemp + LWS_PRE; { memcpy_s(pData, MAX_PAYLOAD_SIZE, json, len); lock_guard lock(m_mtxSession); for (const auto& it : m_mapLwsSession) { if (strstr(it.second.token, "BBBBBBBB")) { lws_write(it.first, pData, len, LWS_WRITE_TEXT); } } } delete[] pTemp; free((void*)json); } } yyjson_mut_doc_free(doc); } int CLWSServer::SendUnAckAlarm(lws* wsi) { { lock_guard lock(m_mtxSession); auto ik = m_mapLwsSession.find(wsi); if (ik == m_mapLwsSession.end()) return 500; if (ik->second.isLogin == false) return 401; }{ uint8_t data[4096 + LWS_PRE]; lock_guard lock(CResistAlarmMng::Instance()->m_mtxAlarm); auto it = CResistAlarmMng::Instance()->m_lstUnConfirmAlarm.crbegin(); for (int i = 0; i < 10 && it != CResistAlarmMng::Instance()->m_lstUnConfirmAlarm.crend(); i++, it++) { auto& pAlarmInfo = *it; //TODO 根据用户过滤 rapidjson::StringBuffer buffer; auto ret = CResistAlarmMng::AlarmInfo2Pack(pAlarmInfo, buffer); const char* output = buffer.GetString(); int len = buffer.GetLength(); memcpy_s(data + LWS_PRE, 4096, output, len); auto sendlen = lws_write(wsi, data + LWS_PRE, len, LWS_WRITE_TEXT); if (sendlen <= 0) return 500; } } return 200; } bool CLWSServer::GeneralResistData(const string mo_mp, const int num, const int index, const std::vector& vctData0, const std::vector& vctData1, const std::vector& vctData2, const vector& vctResult, const CTime& atime, rapidjson::StringBuffer& strBuf) { char sz_utf_first[100]; char sz_utf_second[100]; char sz_utf_three[100]; string name1, name2, name3; CMonitorObjectMng::Instance()->GetNameByMoMp(mo_mp, name1, name2, name3); if (name1[0x00] == 0x00) gbk2utf8(sz_utf_first, 100, "1号测力曲线"); else gbk2utf8(sz_utf_first, 100, name1.c_str()); if (name2[0x00] == 0x00) gbk2utf8(sz_utf_second, 100, "2号测力曲线"); else gbk2utf8(sz_utf_second, 100, name2.c_str()); if (name3[0x00] == 0x00) gbk2utf8(sz_utf_three, 100, "转换阻力曲线"); else gbk2utf8(sz_utf_three, 100, name3.c_str()); int step = 1000 / num; uint64_t utime_t = atime.GetTime() * 1000; string up, momp_name; CMonitorObjectMng::Instance()->GetStationNameByMomP(mo_mp, up, momp_name); using namespace rapidjson; Writer writer(strBuf); writer.StartObject(); writer.Key("cmd"); writer.String("new_data_notify"); writer.Key("tag"); //sprintf_s(szInfo, 256, "%s.resist", mo_mp.c_str()); //gbk2utf8(sz_utf, 412, szInfo); writer.String((mo_mp + ".resist").c_str()); writer.Key("up"); writer.String(ANSItoUTF8(up).c_str()); writer.Key("tag_name"); writer.String(ANSItoUTF8(momp_name).c_str()); writer.Key("time"); writer.String(""); writer.Key("data_fmt"); writer.String("curve"); writer.Key("unit"); writer.String("N"); writer.Key("data"); writer.StartArray(); //1号测力点 writer.StartObject(); writer.Key("name"); writer.String(sz_utf_first); writer.Key("points"); writer.StartArray(); for (int i = 0; i < num; i++) { if (vctResult[i] == false) continue; if (vctData0[i] == INVALID_RESIST) continue; writer.StartArray(); writer.Uint64(utime_t + step* i); writer.Int(vctData0[i]); writer.EndArray(); } writer.EndArray(); writer.EndObject(); //2号测力点 writer.StartObject(); writer.Key("name"); writer.String(sz_utf_second); writer.Key("points"); writer.StartArray(); for (int i = 0; i < num; i++) { if (vctResult[i] == false) continue; if (vctData1[i] == INVALID_RESIST) continue; writer.StartArray(); writer.Uint64(utime_t + step* i); writer.Int(vctData1[i]); writer.EndArray(); } writer.EndArray(); writer.EndObject(); //3号测力点 writer.StartObject(); writer.Key("name"); writer.String(sz_utf_three); writer.Key("points"); writer.StartArray(); for (int i = 0; i < num; i++) { if (vctResult[i] == false) continue; if (vctData2[i] == false) continue; writer.StartArray(); writer.Uint64(utime_t + step* i); writer.Int(vctData2[i]); writer.EndArray(); } writer.EndArray(); writer.EndObject(); writer.EndArray(); writer.EndObject(); return true; }