#include "main.h" //4 13 22 31 #include #include #include #include"yolov5_detect.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MSS_TEST_BUS_NAME "yolov5test" static jbus_hdl_t g_jbus; static jmss_hdl_t g_jmss; static jisp_hdl_t g_jisp; static bool g_running; jmss_stm_t *g_stm[5]; //配置文件路径 #define modelpath_fire "/demo/bin/fire2025_pre.rknn" #define DOWNLOAD_VERSION_PATH "/tmp/version" #define ID_FILE_PWD "/etc/DeviceID" std::string DeviceID; std::string response_controllerId = "NULL"; static char labels_fire[2][20] = {"fire", "any"}; static char labels_smog[2][20] = {"smog", "any"}; #define SERIAL_PORT_INFRARED_SENSOR "/dev/ttyS4" #define SERIAL_PORT_SOLENOID "/dev/ttyS5" #define BAUD_RATE B115200 static int serialPortInfraredSensor; static int serialPortSolenoid; float temperature_img[24][32]; unsigned char buffer[1544]; std::mutex mtx; using namespace cv; using namespace std; using json = nlohmann::json; //使用nlohmann JSON 库 // 定义GPIO控制引脚(假设GPIO2_B0已经设置好) #define RELAY_GPIO_PIN 72 // 使用GPIO 72控制继电器 // 控制继电器复位的函数 void reset_relay() { // 导出GPIO引脚 system("echo 72 > /sys/class/gpio/export"); // 设置GPIO引脚为输出 system("echo out > /sys/class/gpio/gpio72/direction"); // 复位继电器 system("echo 1 > /sys/class/gpio/gpio72/value"); // 设置高电平 usleep(1000000); // 等待1秒 system("echo 0 > /sys/class/gpio/gpio72/value"); // 设置低电平 std::cout << "Relay reset!" << std::endl; } constexpr auto CONFIG_FILE = "/demo/bin/jh.json"; constexpr auto ID_FILE_PATH = "/etc/DeviceID"; constexpr auto LICENSE_FILE = "/demo/bin/activation.lic"; constexpr auto ENCRYPT_KEY = "YourSecretKey1234567890ABCDEF"; // 24字节密钥 // RSA公钥(PEM格式) const string PUBLIC_KEY = R"( -----BEGIN PUBLIC KEY----- MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAK+UGGqE+K12kd5F5AH3GQNMSKZjq0l+IBTzF28YWTz+CWtRQ78eKOp3/fXZ8UBRQc2/nRT9Us24l9kPGJ2qUYECAwEAAQ== -----END PUBLIC KEY----- )"; // 全局变量 mutex activation_mutex; class Config { public: static string getActivationUrl() { // 静态成员函数,用于获取激活 URL try { ifstream file(CONFIG_FILE); if (!file) { throw runtime_error("Config file not found"); } json config = json::parse(file); // 使用 nlohmann JSON 库解析配置文件 if (config.contains("activation_url")) { string url = config["activation_url"]; cout << "[INFO] Using activation URL from JSON config: " << url << endl; return url; } throw runtime_error("activation_url not found in config"); } catch (const exception& e) { cerr << "[WARN] " << e.what() << " - Using default URL" << endl; //捕获异常 return "http://183.238.1.242:8889/api/label/security"; } } }; class CryptoUtil { public: // 异或加密(保留原有逻辑) static string xorEncrypt(const string& plaintext) { string encrypted = xorCipher(plaintext, ENCRYPT_KEY); return base64Encode(encrypted); } static string xorDecrypt(const string& ciphertext) { string decoded = base64Decode(ciphertext); return xorCipher(decoded, ENCRYPT_KEY); } // URL编码 static string urlEncode(const string& value) { ostringstream escaped; escaped.fill('0'); escaped << hex; for (char c : value) { if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') { escaped << c; } else { escaped << '%' << setw(2) << int((unsigned char)c); } } return escaped.str(); } // 新增RSA加密 static string rsaEncrypt(const string& plaintext) { RSA* rsa = nullptr; BIO* bio = nullptr; string result; try { bio = BIO_new_mem_buf(PUBLIC_KEY.c_str(), -1); // rsa = PEM_read_bio_RSA_PUBKEY(bio, nullptr, nullptr, nullptr); rsa = PEM_read_bio_RSA_PUBKEY(bio, nullptr, nullptr, nullptr); if (!rsa) throw runtime_error("PEM_read_bio_RSA_PUBKEY failed"); int keySize = RSA_size(rsa); vector encrypted(keySize); int len = RSA_public_encrypt( plaintext.size(), reinterpret_cast(plaintext.c_str()), encrypted.data(), rsa, RSA_PKCS1_PADDING ); if (len == -1) throw runtime_error("RSA encryption failed"); result = base64Encode(encrypted.data(), len); } catch (const exception& e) { cerr << "[ERROR] RSA encryption failed: " << e.what() << endl; ERR_print_errors_fp(stderr); result.clear(); } if (rsa) RSA_free(rsa); if (bio) BIO_free_all(bio); return result; } private: static string xorCipher(const string& data, const string& key) { string result; for (size_t i = 0; i < data.size(); ++i) { result += data[i] ^ key[i % key.size()]; } return result; } static string base64Encode(const string& data) { BIO *bio, *b64; BUF_MEM *bufferPtr; b64 = BIO_new(BIO_f_base64()); bio = BIO_new(BIO_s_mem()); bio = BIO_push(b64, bio); BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); BIO_write(bio, data.c_str(), data.size()); BIO_flush(bio); BIO_get_mem_ptr(bio, &bufferPtr); BIO_set_close(bio, BIO_NOCLOSE); BIO_free_all(bio); return string(bufferPtr->data, bufferPtr->length); } static string base64Encode(const unsigned char* data, size_t len) { BIO* b64 = BIO_new(BIO_f_base64()); BIO* mem = BIO_new(BIO_s_mem()); BIO_push(b64, mem); BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); BIO_write(b64, data, len); BIO_flush(b64); char* ptr; long size = BIO_get_mem_data(mem, &ptr); string result(ptr, size); BIO_free_all(b64); return result; } static string base64Decode(const string& encoded) { BIO *bio, *b64; char* buffer = (char*)malloc(encoded.size()); memset(buffer, 0, encoded.size()); bio = BIO_new_mem_buf(encoded.c_str(), -1); b64 = BIO_new(BIO_f_base64()); bio = BIO_push(b64, bio); BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); int len = BIO_read(bio, buffer, encoded.size()); BIO_free_all(bio); string result(buffer, len); free(buffer); return result; } }; class NetworkUtil { public: static int postRequest(const string& url, const string& postData, string& response) { CURL* curl = curl_easy_init(); if (!curl) return CURLE_FAILED_INIT; // 使用RSA加密数据 string encryptedData = CryptoUtil::rsaEncrypt(postData); string urlEncodedData = CryptoUtil::urlEncode(encryptedData); struct curl_slist* headers = nullptr; headers = curl_slist_append(headers, "Accept: application/json"); // 修改Content-Type const string full_url = url + "?id=" + urlEncodedData; // cout << "[DEBUG] full_url: " << full_url << endl; curl_easy_setopt(curl, CURLOPT_URL, full_url.c_str()); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); CURLcode res = curl_easy_perform(curl); curl_easy_cleanup(curl); curl_slist_free_all(headers); return res; } private: static size_t writeCallback(void* contents, size_t size, size_t nmemb, string* output) { output->append(static_cast(contents), size * nmemb); return size * nmemb; } }; class ActivationManager { public: explicit ActivationManager(string device_id, string mac) : device_id_(move(device_id)), mac_(move(mac)) {} bool checkActivation() { lock_guard lock(activation_mutex); if (checkLocalLicense()) { cout << "[INFO] Device already activated" << endl; return true; } return processOnlineActivation(); } // 内部函数实现:checkLocalLicense, validateLicense, processOnlineActivation, generateLicenseFile private: string device_id_; string mac_; bool checkLocalLicense() { ifstream file(LICENSE_FILE, ios::binary); if (!file) return false; string encrypted((istreambuf_iterator(file)), istreambuf_iterator()); return validateLicense(encrypted); } bool validateLicense(const string& encrypted) { // 修改为使用xorDecrypt string decrypted = CryptoUtil::xorDecrypt(encrypted); auto pos = decrypted.find('|'); if (pos == string::npos) return false; string storedId = decrypted.substr(0, pos); string storedMac = decrypted.substr(pos + 1); return (storedId == device_id_ && storedMac == mac_); } bool processOnlineActivation(int retry_count = 3) { string activation_url = Config::getActivationUrl(); const string post_data = device_id_ + "|" + mac_; cout << "[DEBUG] Original POST data: " << post_data << endl; for (int i = 0; i < retry_count; ++i) { string response; int curl_code = NetworkUtil::postRequest(activation_url, post_data, response); if (curl_code != CURLE_OK) { cerr << "[ERROR] Network error: " << curl_easy_strerror((CURLcode)curl_code) << endl; continue; } try { auto json_resp = json::parse(response); int code = json_resp["code"].get(); if (code == 0) { generateLicenseFile(device_id_ + "|" + mac_); return true; } if (code == 60001 || code == 60002) { cerr << "[FATAL] Activation failed: " << json_resp["msg"].get() << endl; return false; } if (code == 60003 && i < retry_count - 1) { cout << "[WARN] Retrying... (" << i+1 << "/" << retry_count << ")" << endl; this_thread::sleep_for(chrono::seconds(1)); continue; } return false; } catch (const json::exception& e) { cerr << "[ERROR] JSON parse error: " << e.what() << endl; } } return false; } void generateLicenseFile(const string& data) { ofstream file(LICENSE_FILE, ios::binary); // 修改为使用xorEncrypt string encrypted = CryptoUtil::xorEncrypt(data); file.write(encrypted.data(), encrypted.size()); cout << "[INFO] License file created successfully" << endl; } }; string getDeviceID() { ifstream file(ID_FILE_PATH); string id; if (!getline(file, id)) throw runtime_error("Failed to read device ID"); return id; } string getMACAddress() { const vector interfaces = {"eth0", "eth1", "enp0s3", "wlan0"}; for (const auto& iface : interfaces) { ifstream file("/sys/class/net/" + iface + "/address"); if (file) { string mac; getline(file, mac); mac.erase(remove(mac.begin(), mac.end(), '\n'), mac.end()); if (mac.length() == 17 && count(mac.begin(), mac.end(), ':') == 5) { return mac; } } } throw runtime_error("No valid MAC address found"); } int ALARM_TEMPERATURE; int WARN_TEMPERATURE; int MOVE_THRESHOLD; int IGNORE_TEMPERATURE; double Confidence_Threshold; vector> last_result; auto last_result_time = std::chrono::high_resolution_clock::now();// 时间 vector> now_result; int width = 1920, height = 1080; JMediaRawFrameType_e type = JMEDIA_RAWFRAMETYPE_NV12; //查看是否重合 bool check_whether_in_last_result(vector> &last_result, vector &now, std::ofstream& temperature_log){ if(last_result.empty()) return true; //查找now的框坐标是否有出现在上一帧 for(auto i : last_result){ //范围5像素以内都视为不变 if(abs(i[0] - now[0]) <= MOVE_THRESHOLD && abs(i[1] - now[1]) <= MOVE_THRESHOLD && abs(i[2] - now[2]) <= MOVE_THRESHOLD && abs(i[3] - now[3]) <= MOVE_THRESHOLD){ temperature_log << "有重复 此帧结果:(" << now[0] << " " << now[1] << ") (" << now[2] << " " << now[3] << ")" << " 上帧结果:(" << i[0] << " " << i[1] << ") (" << i[2] << " " << i[3] << ")"<< endl; cout << "上帧结果:(" << i[0] << " " << i[1] << ") (" << i[2] << " " << i[3] << ")" << endl; cout << "此帧结果:(" << now[0] << " " << now[1] << ") (" << now[2] << " " << now[3] << ")" << endl; return true; } } cout << "无重复 此帧结果:(" << now[0] << " " << now[1] << ") (" << now[2] << " " << now[3] << ")" << endl; temperature_log << "无重复 此帧结果:(" << now[0] << " " << now[1] << ") (" << now[2] << " " << now[3] << ")" << endl; return false; } //获取当前系统时间 string Get_Time(int input){ // 获取当前系统时间 std::time_t alarmTime_std = std::time(nullptr); // 将时间转换为本地时间 std::tm* localTime = std::localtime(&alarmTime_std); // 从本地时间结构中获取时间信息 int year = localTime->tm_year + 1900; int month = localTime->tm_mon + 1; int day = localTime->tm_mday; int hour = localTime->tm_hour; int minute = localTime->tm_min; int second = localTime->tm_sec; // 拼接成字符串 std::ostringstream oss_alarmTime; if(input == 1){ oss_alarmTime << std::setfill('0') << std::setw(4) << year << "-" << std::setw(2) << month << "-" << std::setw(2) << day << " " << std::setw(2) << hour << ":" << std::setw(2) << minute << ":" << std::setw(2) << second; }else{ oss_alarmTime << std::setfill('0') << std::setw(2) << month << "_" << std::setw(2) << day << "_" << std::setw(2) << hour << "_" << std::setw(2) << minute << "_" << std::setw(2) << second; } // 获取拼接后的字符串 std::string formattedTime = oss_alarmTime.str(); return formattedTime; } double calibration(double x){ double p1 = -9.052e-08; double p2 = 8.313e-05; double p3 = -0.02813; double p4 = 4.16; double p5 = -219.7; double res = p1*pow(x, 4) + p2*pow(x, 3) + p3*pow(x, 2) + p4*x + p5; return res; } size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* response){ size_t totalSize = size * nmemb; response->append(static_cast(contents), totalSize); return totalSize; } bool _geturlFromfile(const char * filepath,char *url, int maxLength) { if (filepath == NULL) { printf("getrulVersion is error, url == null.\n"); return false; } FILE *fp = fopen(filepath, "r"); if (fp == NULL) { printf("open %s failed, error is %s.\n", filepath, strerror(errno)); return false; } int iffind=0; char *line = NULL; size_t len = 0; size_t read; while ((read = getline(&line, &len, fp)) != -1) { if (read == 0 || line[0] == '#') { continue; } char *pline = strstr(line, "upload_url"); if (pline != NULL && (pline = strstr(pline, "=")) != NULL) { pline++; //过滤掉等于号 //过滤掉空格 while (*pline == ' ') { pline++; } int pline_len = strlen(pline) - 1; int version_len = (pline_len > maxLength ? maxLength:pline_len); memcpy(url, pline, version_len); printf("upload_url = %s\n", url); iffind=1; break; } } if (iffind == 0 ){ printf("Can not find upload_url\n"); return false; } free(line); fclose(fp); return true; } // 函数用于读取文件并将其内容保存在全局字符串变量中 void readFileAndStoreInGlobal(const std::string& filename) { std::ifstream file(filename); if (file.is_open()) { std::getline(file, DeviceID); // 读取一行并存储在全局字符串中 file.close(); } else { std::cerr << "无法打开文件: " << filename << std::endl; } } std::string generateIndices(char result[4],Alarm* Alarm) { std::string indices; for (int i = 0; i < 4; ++i) { if (result[i] == '1') { // 将索引值加入到生成的字符串中 indices += std::to_string(i + 1); Alarm->ifalarm = 1; } } return indices; } void checkCoverage(int x1, int x2, int width, char result[4]) { // 初始化为 '1',表示覆盖 // std::string resultString1(result, 4); // std::cout << "result in: " << resultString1 << std::endl; char result_now[4]={'1','1','1','1'}; int line1 = width*7/32; int line2 = width/2; int line3 = width*25/32; if(x1>line1){ result_now[3] = '0'; } if(x1>line2){ result_now[3] = '0'; result_now[2] = '0'; } if(x1>line3){ result_now[3] = '0'; result_now[2] = '0'; result_now[1] = '0'; } if(x2& data) { uint16_t sum = 0; for (size_t i = 0; i < data.size()-1; ++i) { sum += data[i]; } return static_cast(sum & 0xFF); } void printVector(const std::vector& vec) { std::cout << "Vector contents: "; for (const auto& byte : vec) { std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast(byte) << " "; } std::cout << std::dec << std::endl; // 切换回十进制 } int main(int argc, char **argv) { std::string folderPath = "/demo/pic"; //保存图片的文件夹路径 if(!createDirectory(folderPath)){ return 0; } // 打开 JSON 文件 cout << "解析JSON文件" << endl; std::ifstream file("/demo/bin/config.json"); // 检查文件是否成功打开 if (!file.is_open()) { std::cerr << "Failed to open json file" << std::endl; return 1; } try { // 解析 JSON 文件 json Config_jsonData; file >> Config_jsonData; // 关闭文件 // 赋值给全局常量 WARN_TEMPERATURE = Config_jsonData["WARN_TEMPERATURE"]; ALARM_TEMPERATURE = Config_jsonData["ALARM_TEMPERATURE"]; MOVE_THRESHOLD = Config_jsonData["MOVE_THRESHOLD"]; IGNORE_TEMPERATURE = Config_jsonData["IGNORE_TEMPERATURE"]; Confidence_Threshold = Config_jsonData["Confidence_Threshold"]; } catch (const json::parse_error& e) { std::cerr << "JSON parsing error: " << e.what() << std::endl; return 0; } file.close(); cout << "配置 WARN_TEMPERATURE :" << WARN_TEMPERATURE << endl; cout << "配置 ALARM_TEMPERATURE :" << ALARM_TEMPERATURE << endl; cout << "配置 MOVE_THRESHOLD :" << MOVE_THRESHOLD << endl; cout << "配置 IGNORE_TEMPERATURE :" << IGNORE_TEMPERATURE << endl; cout << "配置 Confidence_Threshold :" << Confidence_Threshold << endl; cout << SERIAL_PORT_INFRARED_SENSOR <=2?(JMediaRawFrameType_e)atoi(argv[1]):JMEDIA_RAWFRAMETYPE_NV12; int width = 1920, height = 1080; jmss_raw_t *rawchn = JES_MSS_RawOpen(g_jmss, 0, width, height, type); if(rawchn == NULL){ printf("==============>>>: %s:%d open rawchn failed\n", strrchr(__FILE__,'/'),__LINE__); return -1; } int ret; readFileAndStoreInGlobal((char *)ID_FILE_PWD); // 打印全局字符串变量 std::cout << "ID内容:" << DeviceID < ControlInstructions(20,0x00); ControlInstructions[0] = 0xCA; //协议头 ControlInstructions[1] = 0x14; //总长度 ControlInstructions[2] = 0x01; //操作指令 //打开JES的通道 jmss_raw_t *rawchn = JES_MSS_RawOpen(g_jmss, 0, width, height, type); if(rawchn == NULL){ printf("==============>>>: %s:%d open rawchn failed\n", strrchr(__FILE__,'/'),__LINE__); } //日志相关内容 std::string filename = "/demo/bin/temperature_log.txt"; std::ofstream temperature_log(filename, std::ios::out | std::ios::trunc); temperature_log << "配置 WARN_TEMPERATURE :" << WARN_TEMPERATURE << endl; temperature_log << "配置 ALARM_TEMPERATURE :" << ALARM_TEMPERATURE << endl; temperature_log << "配置 MOVE_THRESHOLD :" << MOVE_THRESHOLD << endl; temperature_log << "配置 IGNORE_TEMPERATURE :" << IGNORE_TEMPERATURE << endl; temperature_log << "配置 Confidence_Threshold :" << Confidence_Threshold << endl; //环境温度 double temp_env = 0; auto last_time = std::chrono::high_resolution_clock::now();// 记录开始时间 // 创建一个 Alarm 结构体对象 Alarm Alarm; // 调用初始化函数来初始化结构体成员 initializeAlarm(&Alarm); //用于从全局buffer中复制数据 unsigned char copyBuffer[1544]; /* 参数初始化 */ int output_nboxes_left =0; yolov5_detect_result_group_t detect_result_group; /* 算法模型初始化 */ char *path = reinterpret_cast(args); printf("loading model %s\n",path); rknn_context ctx; yolov5_detect_init(&ctx, path); // yolov5_detect_init(&ctx, "./fire_rv1126.rknn"); //配置label char labels[2][20]; getLabels(path, labels); // 设置压缩质量 std::vector compression_params; compression_params.push_back(cv::IMWRITE_JPEG_QUALITY); compression_params.push_back(30); // 设置压缩质量,范围为 0-100 int overtem_cnt = 0; std::vector over_tmp_deque(10, 0); /* 算法运行 */ while(!quit){ int time2run = 1; // auto current_time = std::chrono::high_resolution_clock::now(); // auto elapsed_time = std::chrono::duration_cast(current_time - last_time);// 计算距离开始时间的时间差 // if (elapsed_time.count() - 1000 > 0) { // last_time = current_time; // time2run = 1; // } sleep(2); //获取摄像头buffer JVMediaFrame_t frm; if(JES_MSS_RawGetFrame(rawchn,&frm) < 0){ sleep(1); continue; } int overtmp_falg = 0; Alarm.ifalarm = 0; Alarm.ifwarn = 0; Mat src; NV12ToRGB(width, height, frm.buffer, src); //裁剪 cv::Rect roi(220, 130, 1480, 570); src = src(roi); //固定时间间隔去处理红外参数 char result[4]={'0','0','0','0'}; char result_warn[4]={'0','0','0','0'}; char result_fire_rknn[4]={'0','0','0','0'}; //初始化ControlInstructions ControlInstructions[3]=0x00; ControlInstructions[4]=0x00; ControlInstructions[5]=0x00; ControlInstructions[6]=0x00; if(time2run){ cout << "run ." << endl; mtx.lock(); memcpy(copyBuffer, buffer, sizeof(buffer)); mtx.unlock(); //计算温度 double temperature; int Col,Row; int j = 0; double max_temperature = 0; for (int i = 4; i < 1540; i += 2) { // temperature = calibration((buffer[i+1]*256+buffer[i])/100.0); temperature = (buffer[i+1]*256+buffer[i])/100.0 + 6; // cout << (buffer[i+1]*256+buffer[i])/100.0 << " " << temperature << endl; //按视觉顺序存入数组 Col = 31-(j)%32; Row = (j)/32; temperature_img[Row][Col] = temperature; j++; } temp_env = (buffer[1541]*256+buffer[1540])/100.0; WARN_TEMPERATURE = (temp_env*2)>WARN_TEMPERATURE? (temp_env*2):WARN_TEMPERATURE; // ALARM_TEMPERATURE = WARN_TEMPERATURE + 20; //截去上下5行数据 for(int i=5; i<19; i++){ for(j=0; j<32; j++){ if(temperature_img[i][j] > IGNORE_TEMPERATURE) continue; if(temperature_img[i][j] > max_temperature) max_temperature = temperature_img[i][j]; if(temperature_img[i][j] > ALARM_TEMPERATURE){ overtmp_falg = 1; if (0 <= j && j <= 6) result[0] = '1'; else if (6 < j && j <= 15) result[1] = '1'; else if (15 < j && j <= 24) result[2] = '1'; else if (24 < j && j <= 31) result[3] = '1'; } if(temperature_img[i][j] > WARN_TEMPERATURE){ Alarm.ifwarn = 1; if (0 < j && j <= 6) result_warn[0] = '1'; else if (6 < j && j <= 15) result_warn[1] = '1'; else if (13 < j && j <= 24) result_warn[2] = '1'; else if (24 < j && j <= 31) result_warn[3] = '1'; } } } int overtem_cnt_for_log; if(overtmp_falg){ over_tmp_deque.push_back(1); if (over_tmp_deque.size() > 10) { over_tmp_deque.erase(over_tmp_deque.begin()); } overtem_cnt = 0; for (int i = 0; i < over_tmp_deque.size(); ++i) { if (over_tmp_deque[i] == 1) { overtem_cnt++; } } overtem_cnt_for_log = overtem_cnt; if(overtem_cnt >= 3){ Alarm.ifalarm = 1; over_tmp_deque.assign(9, 0); over_tmp_deque.push_back(1); }else{ memset(result, '0', 4*sizeof(char)); } }else{ over_tmp_deque.push_back(0); // 保持队列长度为10,如果超过长度则移除最前面的元素 if (over_tmp_deque.size() > 10) { over_tmp_deque.erase(over_tmp_deque.begin()); } } // temp_env = (buffer[1541]*256+buffer[1540])/100.0; cout << "最大温度: " << max_temperature << endl; cout << "环境温度" << temp_env << endl; cout << "预警温度: " << WARN_TEMPERATURE << endl; cout << "直接喷水温度: " << ALARM_TEMPERATURE << endl; if(max_temperature>WARN_TEMPERATURE){ temperature_log << endl << "---------------------------------------------------" << endl; temperature_log << Get_Time(1) << endl; temperature_log << "最大温度: " << max_temperature << endl; temperature_log << "环境温度: " << temp_env << endl; temperature_log << "预警温度: " << WARN_TEMPERATURE << endl; temperature_log << "直接喷水温度: " << ALARM_TEMPERATURE << endl; temperature_log << "超温队列:"; for (int i = 0; i < over_tmp_deque.size(); ++i) { temperature_log << over_tmp_deque[i] << " "; } temperature_log << endl; } if(Alarm.ifalarm){ printf("temprature > %d°C !\n", ALARM_TEMPERATURE); // 将字符数组拼接成字符串 std::string resultString(result, 4); std::cout << ALARM_TEMPERATURE <<"度结果: " << resultString << std::endl; temperature_log << ALARM_TEMPERATURE <<"度结果: " << resultString << std::endl; std::string resultString_warn(result_warn, 4); std::cout << WARN_TEMPERATURE << "度结果: " << resultString_warn << std::endl; temperature_log << WARN_TEMPERATURE <<"度结果: " << resultString_warn << std::endl; }else if(Alarm.ifwarn){ printf("temprature > %d°C !\n", WARN_TEMPERATURE); std::string resultString_warn(result_warn, 4); std::cout << WARN_TEMPERATURE << "结果: " << resultString_warn << std::endl; temperature_log << WARN_TEMPERATURE << "结果: " << resultString_warn << std::endl; } } if(Alarm.ifwarn){ struct timeval start; struct timeval end; now_result.clear(); temperature_log << "上帧总的结果:" << endl; for(auto i : last_result){ temperature_log << "(" << i[0] << " " << i[1] << ") (" << i[2] << " " << i[3] << ")" << endl; } printf("%s_rknn_run\n",labels[0]); yolov5_detect_run(ctx, src, &detect_result_group); } //计算时间差 if( detect_result_group.count > 0 ){ auto current_time_now = std::chrono::high_resolution_clock::now();// 时间 auto value_time = std::chrono::duration_cast(current_time_now - last_result_time);// 计算距离开始时间的时间差 if (value_time.count() - 10000 > 0) { //如果上下帧大于十秒,则清除上一帧 last_result.clear(); } } /* 算法结果在图像中画出并保存 */ int name_int = 0; // char result[4]={'0','0','0','0'}; for (int i = 0; i < detect_result_group.count; i++) { yolov5_detect_result_t *det_result = &(detect_result_group.results[i]); if( det_result->prop < Confidence_Threshold ) { continue; } cout << "Detected object: " << det_result->name << endl; //报警打印 if(Alarm.ifwarn){ printf("%s @ (%d %d %d %d) %f\n", det_result->name, det_result->box.left, det_result->box.top, det_result->box.right, det_result->box.bottom, det_result->prop); vector now; now.push_back(det_result->box.left); now.push_back(det_result->box.top); now.push_back(det_result->box.right); now.push_back(det_result->box.bottom); now_result.push_back(now); if(check_whether_in_last_result(last_result,now,temperature_log)){ continue; } } int x1 = det_result->box.left; int y1 = det_result->box.top; int x2 = det_result->box.right; int y2 = det_result->box.bottom; //检测区域 if(Alarm.ifwarn){ checkCoverage(x1, x2, 1480, result_fire_rknn); } char label_text[50]; memset(label_text, 0 , sizeof(label_text)); sprintf(label_text, "%s %0.2f",det_result->name, det_result->prop); plot_one_box(src, x1, x2, y1, y2, label_text, i%10); } if(Alarm.ifwarn){ // if(!now_result.empty()){ // last_result.clear(); // last_result = now_result; // } //若上帧结果为空,依然清理结果队列 --2024.11.4 last_result.clear(); last_result = now_result; last_result_time = std::chrono::high_resolution_clock::now();// 时间 std::string resultString_fire(result_fire_rknn, 4); std::cout << "rknn检测结果: " << resultString_fire << std::endl; temperature_log << "rknn检测结果: " << resultString_fire << std::endl; //对45度区域和火焰检测区域做出 与操作 and_result(result_warn,result_fire_rknn); //对火与45度结果 与 60 度结果 做或操作 or_result(result,result_warn); temperature_log << "报警输入:" << string(result, 4) <(orig_data.c_str()), orig_data.length()); Alarm.alarmBase64 = encoded_data; Alarm.alarmMsg = std::string(labels[0]); Alarm.alarmMsg = std::string(labels[name_int]); pthread_t upload_message_tidp; pthread_create(&upload_message_tidp, NULL, upload_message, static_cast(&Alarm)); pthread_t upload_message_controller_tidp; int ret =pthread_create(&upload_message_controller_tidp, NULL, upload_message_controller, static_cast(&Alarm)); if (ret != 0) { std::cerr << "Error creating controller thread: " << strerror(ret) << std::endl; } else { std::cerr << "success creating controller thread" << std::endl; } } } /* 算法模型空间释放 */ yolov5_detect_release(ctx); //文件关闭 temperature_log.close(); return 0; } void *upload_message(void *args) { pthread_detach(pthread_self()); // 获取上报url char upload_url[200] = {0}; if(!_geturlFromfile(DOWNLOAD_VERSION_PATH,upload_url,sizeof(upload_url))){ printf("结束进程\n"); return 0; } Alarm* alarm = static_cast(args); // 获取当前系统时间 std::time_t alarmTime_std = std::time(nullptr); // 将时间转换为本地时间 std::tm* localTime = std::localtime(&alarmTime_std); // 从本地时间结构中获取时间信息 int year = localTime->tm_year + 1900; int month = localTime->tm_mon + 1; int day = localTime->tm_mday; int hour = localTime->tm_hour; int minute = localTime->tm_min; int second = localTime->tm_sec; // 拼接成字符串 std::ostringstream oss_alarmTime; oss_alarmTime << std::setfill('0') << std::setw(4) << year << "-" << std::setw(2) << month << "-" << std::setw(2) << day << " " << std::setw(2) << hour << ":" << std::setw(2) << minute << ":" << std::setw(2) << second; // 获取拼接后的字符串 std::string formattedTime = oss_alarmTime.str(); std::string cameraId = DeviceID; std::string controllerId = response_controllerId; std::string msg = (alarm->alarmMsg).c_str(); std::string type = "1"; std::string time = formattedTime; std::string img = (alarm->alarmBase64).c_str(); std::string Coverage = (alarm->alarmCoverage).c_str(); std::cout << "cameraId: " << cameraId << " msg: " << msg << " type: " << type << " time: " << time <(args); // 获取当前系统时间 std::time_t alarmTime_std = std::time(nullptr); // 将时间转换为本地时间 std::tm* localTime = std::localtime(&alarmTime_std); // 从本地时间结构中获取时间信息 int year = localTime->tm_year + 1900; int month = localTime->tm_mon + 1; int day = localTime->tm_mday; int hour = localTime->tm_hour; int minute = localTime->tm_min; int second = localTime->tm_sec; // 拼接成字符串 std::ostringstream oss_alarmTime; oss_alarmTime << std::setfill('0') << std::setw(4) << year << "-" << std::setw(2) << month << "-" << std::setw(2) << day << " " << std::setw(2) << hour << ":" << std::setw(2) << minute << ":" << std::setw(2) << second; // 获取拼接后的字符串 std::string formattedTime = oss_alarmTime.str(); std::string cameraId = DeviceID; std::string Coverage = (alarm->alarmCoverage).c_str(); std::cout << "cameraid: " << cameraId << " errNum: " << Coverage <(current_time - last_time);// 计算距离开始时间的时间差 if (elapsed_time.count() - 30000 > 0) { last_time = current_time; time2run = 1; } if(time2run){ std::cout << "心跳上报" << std::endl; std::string cameraId = DeviceID; std::string IP = "987654"; int state = 1; std::string http_address = "http"; std::string MessageString = R"({ "cameraId": ")" + cameraId + R"(", "IP": ")" + IP + R"(", "state": )" + std::to_string(state) + R"(, "http_address": ")" + http_address + R"(" })"; CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET"); curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.1.23:9527/device/heartbeat"); /* Now specify the POST data */ struct curl_slist *plist = nullptr; plist = curl_slist_append(plist, "Content-Type:application/json;charset=UTF-8"); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, plist); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, MessageString.c_str()); std::string response; curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); res = curl_easy_perform(curl); /* Check for errors */ // if(res != CURLE_OK) // fprintf(stderr, "curl_easy_perform() failed: %s\n",curl_easy_strerror(res)); if (res != CURLE_OK) { std::cerr << "heart beat: Failed to perform cURL request: " << curl_easy_strerror(res) << std::endl; } else { std::cout << "heart beat: Request successful!" << std::endl; std::cout << "heart beat: Response: " << response << std::endl; // 解析 JSON 字符串 try { json jsonData = json::parse(response); // 提取 controllerId 字段的内容 response_controllerId = jsonData["controllerId"]; std::cout << "Controller ID: " << response_controllerId << std::endl; } catch (const json::parse_error& e) { std::cerr << "JSON parsing error: " << e.what() << std::endl; } } curl_easy_cleanup(curl); } curl_global_cleanup(); } time2run = 0; } } void *read_serial_thread(void *args) { pthread_detach(pthread_self()); ssize_t bytesRead; // 打开红外传感器对应的串口设备 serialPortInfraredSensor = open(SERIAL_PORT_INFRARED_SENSOR, O_RDWR | O_NOCTTY | O_NDELAY); if (serialPortInfraredSensor == -1) { printf("Failed to open serial port: %s\n", SERIAL_PORT_INFRARED_SENSOR); return 0; } struct termios tty; memset(&tty, 0, sizeof(tty)); // 初始化配置结构体,清零 if (tcgetattr(serialPortInfraredSensor, &tty) != 0) { printf("Failed to get serial port attributes\n"); close(serialPortInfraredSensor); return 0; } // 设置串口输入和输出波特率 cfsetospeed(&tty, BAUD_RATE); cfsetispeed(&tty, BAUD_RATE); tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; tty.c_cflag &= ~(PARENB | PARODD); tty.c_cflag &= ~CSTOPB; tty.c_cflag |= CREAD | CLOCAL; tty.c_iflag = IGNPAR; tty.c_oflag = 0; tty.c_lflag = 0; if (tcsetattr(serialPortInfraredSensor, TCSANOW, &tty) != 0) { printf("Failed to set serial port attributes\n"); close(serialPortInfraredSensor); return 0; } // while(1){ // mtx.lock(); // bytesRead = read(serialPortInfraredSensor, buffer, sizeof(buffer)); // mtx.unlock(); // if (bytesRead>0) { // if((buffer[0]== 0x5a)&&(buffer[1]==0x5a)) { // // printf("readed serialPortInfraredSensor date\n"); // }else{ // // printf("read failed\n"); // } // }else{ // // printf("empty to read\n"); // } // } // 设置文件描述符集合和超时时间,准备使用 select() 进行串口数据的检测 fd_set readfds; struct timeval timeout; int selectResult; // 此处后续可以继续添加使用 select() 监听串口数据的逻辑… while (1) { FD_ZERO(&readfds); FD_SET(serialPortInfraredSensor, &readfds); timeout.tv_sec = 5; // 5秒超时 timeout.tv_usec = 0; selectResult = select(serialPortInfraredSensor + 1, &readfds, NULL, NULL, &timeout); if (selectResult > 0) { if (FD_ISSET(serialPortInfraredSensor, &readfds)) { mtx.lock(); bytesRead = read(serialPortInfraredSensor, buffer, sizeof(buffer)); mtx.unlock(); if (bytesRead > 0) { if (buffer[0] == 0x5a && buffer[1] == 0x5a) { // printf("readed serialPortInfraredSensor date\n"); } else { // printf("read failed\n"); } } } } else if (selectResult == 0) { // 超时,没有数据可读 // printf("Timeout, no data available\n"); } else { // select出错 printf("select() failed\n"); break; } } }