// CcosChannel.cpp : 定义控制台应用程序的入口点。 // #include #include #include #include #include #include #include #include #include #include #include "CDI.h" #include "BusUnitClient.h" #include "LogicClient.h" #include "LocalConfig.h" #include "PacketAnalizer.h" #include "ConsoleThread.h" #include "AutoDmp.h" //#include "Vga_Demo.h" #include #include "common_api.h" #include #define CTRL_C_EVENT 0 #define CTRL_BREAK_EVENT 1 #define CTRL_CLOSE_EVENT 2 // 3 is reserved! // 4 is reserved! #define CTRL_LOGOFF_EVENT 5 #define CTRL_SHUTDOWN_EVENT 6 inline std::string CurrentDateTime() { // 获取当前时间点 auto now = std::chrono::system_clock::now(); // 将时间长度转换为微秒数 auto now_us = std::chrono::duration_cast(now.time_since_epoch()); // 再转成tm格式 auto now_time_t = std::chrono::system_clock::to_time_t(now); auto now_tm = std::localtime(&now_time_t); // 可以直接输出到标准输出 // std::cout << std::put_time(now_tm, "%Y-%m-%d %H:%M:%S.") << std::setfill('0') << std::setw(6) << now_us.count() % 1000000 << std::endl; // 格式化字符,年月日时分秒 std::string now_time_str; char buf[64]; std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", now_tm); now_time_str += buf; // 格式化微秒 snprintf(buf, sizeof(buf), ".%06ld ", now_us.count() % 1000000); now_time_str += buf; //printf("%s\n", now_time_str.c_str()); return now_time_str; } AutoDmp atdmp; //CommonLogicClient WheelClient; #define MAX_THREAD_TEST (1) DWORD ConsoleThreadCount = MAX_THREAD_TEST; ConsoleThread g_ConsoleThread[MAX_THREAD_TEST]; //UI_Thread g_UIThread; //Vga_Demo g_VgaDemoThread; bool StartConsoleThreads(bool start) { bool ret = true; //return ret;// for (DWORD i = 0; i < ConsoleThreadCount; i++) { if (start) { g_ConsoleThread[i].SetName("ConsoleThread"); ret &= (g_ConsoleThread[i]).StartThread(); printf("start console Thread:%lu!\n", i); } else { (g_ConsoleThread[i]).StopThread(100); } } return ret; } void ConsoleHandler(int signo) { // 处理常见的终止信号 switch (signo) { case SIGINT: // Ctrl+C (类似 Windows 的 CTRL_CLOSE_EVENT) case SIGTERM: // 终止信号 (类似 Windows 的 CTRL_SHUTDOWN_EVENT) printf("Received termination signal! Shutting down...\n"); // 停止控制台线程 StartConsoleThreads(false); // 等待命令分发系统退出,最多等待 500ms // 注意: Linux 下需要确保 WaitExit 的实现支持超时和强制退出参数 GetCommandDispathIF()->WaitExit(500, true); // 在 Linux 中,我们需要执行最终的清理并退出 // Windows 会自动终止进程,但 Linux 需要显式退出 exit(EXIT_SUCCESS); break; default: // 其他信号可以在这里处理 // 例如: SIGQUIT (Ctrl+\), SIGHUP (终端断开) 等 break; } } std::set g_arrWhiteDirectory; string procdir; void KeepParent(string dir) { if (dir == procdir) return; g_arrWhiteDirectory.insert(dir); string parent = GetFileDirectory(dir); if (parent == procdir || parent.length() <= 0) return; KeepParent(parent); } void CheckWhiteDir(ResDataObject & driverConf, string& driverPath, string& sdkPath) { if (driverConf.GetFirstOf("oemdriver") > 0) { driverPath = (const char*)driverConf["oemdriver"]; string temp("%ROOT%"); driverPath = ReplaceSubString(driverPath, temp, procdir); if (driverConf.GetFirstOf("SDKPath") > 0) { sdkPath = (const char*)driverConf["SDKPath"]; if (sdkPath.length() > 0) { if (sdkPath[0] != '\\') sdkPath = procdir + "\\" + sdkPath; else sdkPath = procdir + sdkPath; if (sdkPath[sdkPath.length() - 1] == '\\') sdkPath.erase(sdkPath.length() - 1, 1); } } } else if (driverConf.GetFirstOf("driver") > 0) { //普通驱动 driverPath = (const char*)driverConf["driver"]; string temp("%ROOT%"); driverPath = ReplaceSubString(driverPath, temp, procdir); } driverPath = GetFileDirectory(driverPath); g_arrWhiteDirectory.insert(driverPath); KeepParent(driverPath); cout<< endl << "Keep Driver White Path " << driverPath << endl; if (sdkPath.length() > 0) { bool isSub = false; string sdkPpath; sdkPpath = GetFileDirectory(sdkPath); if (sdkPpath.length() >= driverPath.length()) { //if (sdkPath.substr(0, driverPath.length()) == driverPath) if(sdkPpath == driverPath) { //sdk目录在driver子目录 isSub = true; } } if (!isSub) { g_arrWhiteDirectory.insert(sdkPath); KeepParent(sdkPath); cout << "Keep Driver S D K Path " << sdkPath << endl; } else { cout << "With Driver S D K Path " << sdkPath << endl; } } } /// /// 清理已安装Driver驱动目录,保留白名单驱动 /// /// void CleanDriver(ResDataObject* whitelist) { procdir = GetProcessDirectory(); ResDataObject fileList; GetSpecificDriverConfigFiles(fileList, false); for (int x = 0; x < fileList.size(); x++) { string filename = fileList.GetKey(x); bool bFind = false; //std::cout << "CleanDriver " << fileList.GetKey(x) << " white list " << whitelist->encode() << endl; for (int y = 0; y < whitelist->size(); y++) { string key = (*whitelist)[y].encode(); if (filename.find(key) != string::npos) { bFind = true; // } } ResDataObject driverConfFile; ResDataObject driverConf; string driverPath,sdkPath; if (driverConfFile.loadFile(filename.c_str())) { if (driverConfFile.GetFirstOf("CONFIGURATION") < 0) continue; driverConf = driverConfFile["CONFIGURATION"]; } if (!bFind) { remove(filename.c_str()); } else { CheckWhiteDir(driverConf, driverPath, sdkPath); } } } /// /// 校验驱动,不在列表的需要移除配置 /// /// 驱动配置文件列表in/out paht:bool /// 要保留的驱动目录out /// 当前要检查的驱动信息 in /// 驱动类型如Detector/SynBox等 /// bool CheckInDriver(ResDataObject& fileList, ResDataObject& driverList, ResDataObject& oneDriver, const char* driverType) { string procdir = GetProcessDirectory(); for (int x = 0; x < fileList.size(); x++) { ResDataObject driverConfFile; if (driverConfFile.loadFile(fileList.GetKey(x))) { ResDataObject driverConf; if (driverConfFile.GetFirstOf("CONFIGURATION") < 0) continue; driverConf = driverConfFile["CONFIGURATION"]; if (driverConf.GetFirstOf("MajorID") < 0) continue; string MajorID = (const char*)driverConf["MajorID"]; if (strcmp(driverType, MajorID.c_str()) != 0) { continue; } if (driverConf.GetFirstOf("VendorID") >= 0 && oneDriver.GetFirstOf("VendorID") >= 0) { if (driverConf.GetFirstOf("ProductID") >= 0 && oneDriver.GetFirstOf("ProductID") >= 0) { if (strcmp(driverConf["ProductID"], oneDriver["ProductID"]) == 0 && strcmp(driverConf["VendorID"], oneDriver["VendorID"]) == 0) { //匹配了 if (driverConf.GetFirstOf("oemdriver") > 0) { string sdkPath, driverPath = driverConf["oemdriver"].encode(); string temp("%ROOT%"); driverPath = ReplaceSubString(driverPath, temp, procdir); FILE* f = fopen(driverPath.c_str(), "r"); if (f != NULL) { fileList[x] = true; fclose(f); if (oneDriver.GetFirstOf("Install") >= 0) { const char* install = oneDriver["Install"]; if (strcmp(install, "true") == 0) { string FullConfig("%FullConfig%"); string DriverConfig("%DriverConfig%"); string dstPath = ReplaceSubString(fileList.GetKey(x), FullConfig, DriverConfig); //拷贝安装驱动到DriverConfig,暂时不预装 //CopyFile(fileList.GetKey(x), dstPath.c_str(), FALSE); //std::cout << "Install Driver: " << dstPath << endl; } } //记录驱动保留目录 //存在多个设备共享驱动情况 //只要有一个需要安装,驱动不能删除 driverPath = GetFileDirectory(driverPath); driverList.update(driverPath.c_str(), true); CheckWhiteDir(driverConf, driverPath, sdkPath); return true; } } } } } } } return false; } // 递归删除目录的回调函数 static int remove_directory_entry(const char* fpath, const struct stat* /*sb*/, int typeflag, struct FTW* /*ftwbuf*/) { int rv = 0; switch (typeflag) { case FTW_F: // 普通文件 rv = remove(fpath); break; case FTW_DP: // 空目录 rv = rmdir(fpath); break; default: std::cerr << "无法删除特殊文件: " << fpath << std::endl; rv = -1; } return rv; } // 删除文件或目录 // 参数: // strPath - 要删除的文件/目录路径 // bDelete - Linux环境忽略此参数(保留用于接口兼容) bool RecycleFileOrFolder(string strPath, bool bDelete = true) { if (!strPath.empty() && strPath.back() == '\0') { strPath.pop_back(); } struct stat path_stat; // 检查路径是否存在 if (lstat(strPath.c_str(), &path_stat) != 0) { perror(("检查路径失败: " + strPath).c_str()); return false; } int result = 0; if (S_ISDIR(path_stat.st_mode)) { // 递归删除目录及其内容 // FTW_DEPTH: 深度优先遍历(先处理子目录) // FTW_PHYS: 不解析符号链接 result = nftw(strPath.c_str(), remove_directory_entry, 64, FTW_DEPTH | FTW_PHYS); } else { // 删除单个文件 result = remove(strPath.c_str()); } if (result != 0) { perror(("删除失败: " + strPath).c_str()); return false; } std::cout << "已删除: " << strPath << std::endl; return true; } /// /// 移除驱动,配置文件和驱动目录 /// /// 要移除的驱动文件路径 /// 要保留的驱动目录列表 void DeleteDriver(const char* pszDriverConf, ResDataObject& resRetainDriverList) { string procdir = GetProcessDirectory(); ResDataObject driverConfFile; if (driverConfFile.loadFile(pszDriverConf)) { ResDataObject driverConf; if (driverConfFile.GetFirstOf("CONFIGURATION") >= 0) { driverConf = driverConfFile["CONFIGURATION"]; if (driverConf.GetFirstOf("oemdriver") > 0) { string driverPath = driverConf["oemdriver"].encode(); string temp("%ROOT%"); driverPath = ReplaceSubString(driverPath, temp, procdir); driverPath = GetFileDirectory(driverPath); if (resRetainDriverList.GetFirstOf(driverPath.c_str()) < 0) { RecycleFileOrFolder(driverPath.c_str()); std::cout << "Remove Driver Module: " << driverPath << endl; } } } } remove(pszDriverConf); std::cout << "Delete Driver Config: " << pszDriverConf << endl; } bool CopyFile(const std::string& source, const std::string& destination, bool overwrite = true) { // 检查源文件是否存在 if (!std::filesystem::exists(source)) { std::cerr << "错误: 源文件不存在 - " << source << std::endl; return false; } // 检查目标文件是否已存在 if (std::filesystem::exists(destination)) { if (overwrite) { // 删除已存在的目标文件 if (!std::filesystem::remove(destination)) { std::cerr << "警告: 无法覆盖已存在的文件 - " << destination << std::endl; return false; } } else { // 不覆盖已存在文件 std::cerr << "警告: 目标文件已存在且未设置覆盖 - " << destination << std::endl; return false; } } try { // 确保目标目录存在 std::filesystem::path destPath(destination); std::filesystem::create_directories(destPath.parent_path()); // 执行文件复制 std::filesystem::copy(source, destination, std::filesystem::copy_options::overwrite_existing); std::cout << "成功复制文件: " << source << " -> " << destination << std::endl; return true; } catch (const std::filesystem::filesystem_error& e) { std::cerr << "文件复制错误: " << e.what() << std::endl; return false; } catch (...) { std::cerr << "未知错误发生在文件复制过程中" << std::endl; return false; } } /// /// 校验驱动配置 /// /// 驱动配置文件名,不含路径,文件必须在设备目录里 void DefineDriver(const char* pszFileName) { string procdir = GetProcessDirectory(); ResDataObject resDriver; string driverFile = procdir + "\\" + pszFileName; g_arrWhiteDirectory.clear(); if (resDriver.loadFile(driverFile.c_str())) { string canInsstall = procdir + "\\DriverDefine\\DriverDefine.json"; CopyFile(driverFile.c_str(), canInsstall.c_str(), FALSE); //先清理已安装驱动 ResDataObject whitelist; if (resDriver.GetFirstOf("WhiteList") >= 0) { whitelist = resDriver["WhiteList"]; CleanDriver(&whitelist); } if (resDriver.GetFirstOf("Drivers") >= 0) { //获取所有配置 ResDataObject fileList, driverList; GetSpecificDriverConfigFiles(fileList, true); for (int fn = 0; fn < fileList.size(); fn++) { fileList[fn] = false; } //校验每个驱动 ResDataObject ResDrivers = resDriver["Drivers"]; for (int x = 0; x < ResDrivers.size(); x++) { //Detector/Generator/... ResDataObject resDrConf = ResDrivers[x]; for (int y = 0; y < resDrConf.size(); y++) { ResDataObject oneDriver = resDrConf[y]; CheckInDriver(fileList, driverList, oneDriver, ResDrivers.GetKey(x)); } } //移除没有驱动程序的驱动配置 //移除未在驱动配置列表的驱动 //白名单驱动要保留 for (int afn = 0; afn < fileList.size(); afn++) { if ((bool)fileList[afn] == false) { bool isWhite = false; string driverFile = fileList.GetKey(afn); for (int wn = 0; wn < whitelist.size(); wn++) { if (driverFile.find((const char*)whitelist[wn]) != string::npos) { isWhite = true; break; } } if (!isWhite) DeleteDriver(driverFile.c_str(), driverList); } } } } std::vector dirList; FindSubFiles(procdir + "\\OEMDrivers", dirList, true, "*");//, true, 3, 2 FindSubFiles(procdir + "\\ServiceDrivers", dirList, true, "*");//, true, 2, 2 FindSubFiles(procdir + "\\SystemDrivers", dirList, true, "*");//, true, 2, 2 cout << endl << "After Define Left Driver Dirs." << endl; for (string td : dirList) { cout << td << endl; string tmp = td.substr(td.length() - 4); //size_t pos = td.find_last_of("conf"); if (tmp == "conf" ) { g_arrWhiteDirectory.insert(td); cout << "Keeped." << endl; } else { if (tmp == "Conf") { g_arrWhiteDirectory.insert(td); cout << "Keeped." << endl; } else { if (g_arrWhiteDirectory.find(td) != g_arrWhiteDirectory.end()) { // cout << "Keeped." << endl; } else { cout << "Removed. Useless Dir" << endl; RecycleFileOrFolder(td); } } } } cout << endl < 1) { if (strcmp(argv[1], "test") == 0) { int nConnNum = 1; if (argc > 2) nConnNum = atoi(argv[2]); if (nConnNum > 20) { nConnNum = 20; } ccos_mqtt_connection** pConns = new ccos_mqtt_connection * [nConnNum]; for (int x = 0; x < nConnNum; x++) { sprintf(szName[x], "TEST_MQTT_Server_%d", x); // Lambda回调函数 - 处理收到的MQTT消息 auto callback = [szName, x, &count, &nTotal, &nMsgCount](ResDataObject* rsp, const char* topic, void* conn_void) { ccos_mqtt_connection* conn = (ccos_mqtt_connection*)conn_void; cout << "Server [" << szName[x] << "] " << CurrentDateTime() << " Get Msg from " << topic << " Msg Body " << rsp->encode() << endl; // 计算消息延迟 string tickSend = PacketAnalizer::GetPacketKey(rsp); DWORD dwTick = GetTickCount() - atoi(tickSend.c_str()); nTotal += dwTick; nMsgCount++; // 统计延迟分布 if (dwTick < 3) count[0]++; else if (dwTick < 5) count[1]++; else if (dwTick < 10) count[2]++; else if (dwTick < 15) count[3]++; else if (dwTick < 20) count[4]++; else { count[5]++; // 可选:打印长延迟消息 // cout << "Receive Packet Use Time [" << dwTick << "]ms" << endl; } // 处理响应包 if (PacketAnalizer::GetPacketType(rsp) == PACKET_TYPE_RES) { if (PacketAnalizer::GetPacketCmd(rsp) == PACKET_CMD_OPEN) { // 连接成功后订阅通知主题 string notifyTopic = "CCOS/Tetst//Notify/#"; SubscribeTopic(conn, notifyTopic.c_str()); } else { cout << szName[x] << CurrentDateTime() << " Try Conn callback get unknown packet" << endl; cout << "Unknown Packet: cmd [" << PacketAnalizer::GetPacketCmd(rsp) << "] packet key: " << PacketAnalizer::GetPacketKey(rsp) << endl; } } }; pConns[x] = NewConnection(szName[x], callback); // 订阅主题 char szTopic[256]; sprintf(szTopic, "CCOS/TEST/Notify/+/%d/#", x); SubscribeTopic(pConns[x], szTopic); SubscribeTopic(pConns[x], "CCOS/TEST/Action/#", true); } std::cout << "Waiting quit..." << endl; char cmd; while (1) { cmd = getchar(); if (cmd == 'q') break; else if (cmd == 'p') { std::cout << "Time < 3 : " << count[0] << endl; std::cout << "Time < 5 : " << count[1] << endl; std::cout << "Time < 10 : " << count[2] << endl; std::cout << "Time < 15 : " << count[3] << endl; std::cout << "Time < 20 : " << count[4] << endl; std::cout << "Time > 20 : " << count[5] << endl; // 计算平均延迟 if (nMsgCount > 0) { cout << "TotalTime " << nTotal << "ms, Msg count: " << nMsgCount << ", Average: " << (nTotal * 1.0 / nMsgCount) << "ms" << endl; } else { cout << "No messages received" << endl; } memset(count, 0, sizeof(count)); nTotal = nMsgCount = 0; } else if (cmd == 'x') { for (int x = 0; x < nConnNum; x++) { ResetConnection(pConns[x]); } } usleep(10000); } for (int x = 0; x < nConnNum; x++) { CloseConnection(pConns[x]); } delete[] pConns; std::cout << "Hello World!\n"; return 0; } else { std::cout << "Starting Process Driver Define....." << endl; DefineDriver(argv[1]); std::cout << "Driver Define Done." << endl; return 0; } } setLogRootpath(((string)getChannelRootpath()).c_str()); if (GetCommandDispathIF()->InitAs(CCOS_PROC_CHANNEL, (UINT64)getpid())) { // 设置信号处理 signal(SIGINT, ConsoleHandler); signal(SIGTERM, ConsoleHandler); LogicClient buClient("channel_temp", "", "", false); if (buClient.Open((const char*)getRootpath(), ALL_ACCESS) == RET_SUCCEED) { //buClient.ExitDriverProc(); buClient.Close(); /*DWORD count = buClient.GetDeviceCount(); for (DWORD i = 0; i < count; i++) { UINT64 ProcId, Addr; ResDataObject DevType,devpath, MachineId; buClient.GetDeviceDescript(i, devpath, DevType, MachineId, ProcId, Addr); printf("path:%s\nProc:%I64u\nAddr:%I64u\n", (const char*)devpath, ProcId, Addr); LogicClient DevClient("channel_exe_temp","channel"); if (DevClient.Open((const char*)devpath, ALL_ACCESS) >= RET_SUCCEED) { DevClient.Close(); printf("Open Succeed\n"); } else { printf("Open Failed\n"); } }*/ status = true; cout << "Channel initialization successful" << endl; } else { status = false; cerr << "Channel initialization failed" << endl; } //start work if (status) { if (StartConsoleThreads(true)) { cout << "Channel initialized. Entering main loop..." << endl; while (1) { if (GetCommandDispathIF()->WaitExit(500)) { StartConsoleThreads(false); cout << "Service shutdown complete" << endl; //ShareMemory_ServerStop(); return 0; } } } } cerr << "Service initialization failed. Exiting..." << endl; sleep(3); } //ShareMemory_ServerStop(); return 1; }