#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 "jlinux_uart.h" #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]; static jbas_hdl_t jbas_handle; #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; std::vector ControlInstructions(16, 0x00); #define BAS_TEST_BUS_NAME "bastest" jbas_hdl_t g_jbas; #define PRSTR(val) printf("%s: %s\n", #val, (val) ? (val) : "(null)") using namespace cv; using namespace std; using json = nlohmann::json; // 定义GPIO控制引脚(假设GPIO2_B0已经设置好) #define RELAY_GPIO_PIN 116 // 使用GPIO 72控制继电器 void hexdump(const char *buf, int len) { //printf("hexdump: len:%d \n", len); for (int i = 0; i < len; i++) { printf("\033[0m\033[1;33m%02X \033[0m", buf[i], buf[i]); } printf("\n"); } // 控制继电器复位的函数 void reset_relay() { // 导出GPIO引脚 system("echo 116 > /sys/class/gpio/export"); // 设置GPIO引脚为输出 system("echo out > /sys/class/gpio/gpio116/direction"); // 复位继电器 system("echo 1 > /sys/class/gpio/gpio116/value"); // 设置高电平 usleep(1000000); // 等待1秒 system("echo 0 > /sys/class/gpio/gpio116/value"); // 设置低电平 std::cout << "Relay reset!" << std::endl; } // 播放音频的函数 void play_audio(const std::string& file_path, jspk_hdl_t jspk) { JES_SPK_PlayFile(jspk, file_path.c_str()); while (JES_SPK_IsBusy(jspk)) { sleep(1); } std::cout << "Audio played: " << file_path << 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() { try { ifstream file(CONFIG_FILE); if (!file) { throw runtime_error("Config file not found"); } json config = json::parse(file); 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(); } 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 g_camera_number = 1; std::string generateIndices(char result[4], Alarm* Alarm) { std::string indices(16, '0'); int CA_ID = g_camera_number; int start = (CA_ID - 1) * 4; for (int i = 0; i < 4; ++i) { if (result[i] == '1') { indices[start + i] = '1'; Alarm->ifalarm = 1; } } return indices; } 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 < line3) { result_now[0] = '0'; } if (x2 < line2) { result_now[0] = '0'; result_now[1] = '0'; } if (x2 < line1) { result_now[0] = '0'; result_now[1] = '0'; result_now[2] = '0'; } result[0] = result[0] | result_now[0]; result[1] = result[1] | result_now[1]; result[2] = result[2] | result_now[2]; result[3] = result[3] | result_now[3]; } //用于resul_warn和result_fire的与操作。 void and_result(char result1[4], char result2[4]) { result1[0] = result1[0] & result2[0]; result1[1] = result1[1] & result2[1]; result1[2] = result1[2] & result2[2]; result1[3] = result1[3] & result2[3]; std::string resultString(result1, 4); // 打印结果字符串 std::cout << "与后结果: " << resultString << std::endl; } //用于resul_warn和result_fire的与操作。 void or_result(char result1[4], char result2[4]) { result1[0] = result1[0] | result2[0]; result1[1] = result1[1] | result2[1]; result1[2] = result1[2] | result2[2]; result1[3] = result1[3] | result2[3]; std::string resultString(result1, 4); // 打印结果字符串 std::cout << "或后结果: " << resultString << std::endl; } void getLabels(const char* path, char labels[2][20]) { if (strcmp(path, modelpath_fire) == 0) { std::cout << "Labels for fire model" << std::endl; strcpy(labels[0], labels_fire[0]); strcpy(labels[1], labels_fire[1]); } else { std::cout << "Null labels" << std::endl; strcpy(labels[0], "null"); strcpy(labels[1], "null"); } } static Scalar colorArray[10] = { Scalar(255, 0, 0, 255), Scalar(0, 255, 0, 255), Scalar(0,0,139,255), Scalar(0,100,0,255), Scalar(139,139,0,255), Scalar(209,206,0,255), Scalar(0,127,255,255), Scalar(139,61,72,255), Scalar(0,255,0,255), Scalar(255,0,0,255), }; int plot_one_box(Mat src, int x1, int x2, int y1, int y2, char* label, char colour) { int tl = round(0.002 * (src.rows + src.cols) / 2) + 1; rectangle(src, cv::Point(x1, y1), cv::Point(x2, y2), colorArray[colour], 3); int tf = max(tl - 1, 1); int base_line = 0; cv::Size t_size = getTextSize(label, FONT_HERSHEY_SIMPLEX, (float)tl / 3, tf, &base_line); int x3 = x1 + t_size.width; int y3 = y1 - t_size.height - 3; rectangle(src, cv::Point(x1, y1), cv::Point(x3, y3), colorArray[colour], -1); putText(src, label, cv::Point(x1, y1 - 2), FONT_HERSHEY_SIMPLEX, (float)tl / 3, cv::Scalar(255, 255, 255, 255), tf, 8); return 0; } bool directoryExists(const std::string& path) { struct stat info; if (stat(path.c_str(), &info) != 0) { return false; // 文件夹不存在 } else if (info.st_mode & S_IFDIR) { return true; // 文件夹存在 } return false; // 存在但不是文件夹 } bool createDirectory(const std::string& path) { if (!directoryExists(path)) { if (mkdir(path.c_str(), 0755) == 0) { std::cout << "文件夹创建成功: " << path << std::endl; return true; } else { std::cerr << "文件夹创建失败: " << strerror(errno) << std::endl; return false; } } else { std::cout << "文件夹已存在: " << path << std::endl; return true; } } //计算校验和 uint8_t calculateChecksum(const std::vector& 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; } // 获取设备信息 jbus_hdl_t jbus = jbus_init("devinfo_test_app"); if (!jbus) { fprintf(stderr, "Error: jbus_init() failed.\n"); return EXIT_FAILURE; } jbas_handle = JES_BAS_Init(jbus); if (!jbas_handle) { fprintf(stderr, "Error: JES_BAS_Init() failed.\n"); jbus_cleanup(jbus); return EXIT_FAILURE; } JBASDevInfo_t devinfo; int results = JES_BAS_GetDevInfo(jbas_handle, &devinfo, JFALSE); if (results == 0) { printf("Successfully retrieved device information:\n"); PRSTR(devinfo.devname); string CA_ID = devinfo.devname; PRSTR(devinfo.language); //获取设备 // 提取设备名称中的摄像头编号 if (!CA_ID.empty()) { char lastChar = CA_ID.back(); // 获取最后一个字符 if (isdigit(lastChar) && lastChar >= '1' && lastChar <= '4') { g_camera_number = lastChar - '0'; // 转换为整数,例如 '2' -> 2 } else { g_camera_number = 1; // 默认值 fprintf(stderr, "Warning: Invalid device name format: %s\n", CA_ID.c_str()); } } else { g_camera_number = 1; // 默认值 fprintf(stderr, "Warning: Device name is empty\n"); } // 打印验证 printf("Camera number: %d\n", g_camera_number); } // 打开 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 << endl; cout << SERIAL_PORT_SOLENOID << endl; try { const string device_id = getDeviceID(); const string mac = getMACAddress(); cout << "Device ID: " << device_id << "\nMAC: " << mac << endl; // 验证RSA加密 // cout << "\n--- RSA Encryption Test ---" << endl; // string test_data = device_id + "|" + mac; // cout << "[TEST] Original data: " << test_data << endl; // string encrypted = CryptoUtil::rsaEncrypt(test_data); // cout << "[TEST] Encrypted data (Base64): " << encrypted << endl; // cout << "[TEST] URL Encoded data: " << CryptoUtil::urlEncode(encrypted) << endl; // 执行激活流程 cout << "\n--- Activation Process ---" << endl; ActivationManager activator(device_id, mac); if (!activator.checkActivation()) { cerr << "[FATAL] Activation failed" << endl; return EXIT_FAILURE; } cout << "\nStarting algorithm..." << endl; // 主程序逻辑 g_jbus = jbus_init(MSS_TEST_BUS_NAME); printf("jbus_init success\n"); g_jmss = JES_MSS_Init(g_jbus); printf("JES_MSS_Init success\n"); g_jisp = JES_ISP_Init(g_jbus); printf("JES_ISP_Init success\n"); char ispver[128] = {}; JES_ISP_GetVersion(g_jisp, 0, ispver, sizeof(ispver)); printf("ispver: %s\n", ispver); sleep(1); JMediaRawFrameType_e type = argc >= 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 << std::endl; char model_fire[] = modelpath_fire; pthread_t rtsp_tidp; pthread_t fire_rknn_tidp; pthread_t smog_rknn_tidp; pthread_t heart_beat_tidp; pthread_t storage_serial; pthread_create(&storage_serial, NULL, storage_serial_thread, NULL); pthread_create(&fire_rknn_tidp, NULL, rkmedia_rknn_thread, model_fire); // pthread_create(&heart_beat_tidp, NULL, heart_beat, NULL); //串口读数据线程 pthread_t read_serial; pthread_create(&read_serial, NULL, read_serial_thread, NULL); printf("%s initial finish\n", __func__); while (!quit) { usleep(500000); } JES_MSS_Deinit(g_jmss); JES_ISP_Deinit(g_jisp); jbus_cleanup(g_jbus); } catch (const exception& e) { cerr << "[FATAL] " << e.what() << endl; return EXIT_FAILURE; } return EXIT_SUCCESS; } void* rkmedia_rknn_thread(void* args) { pthread_detach(pthread_self()); //初始化协议信息 // 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; // // int JES_MCS_GetLinkageList(jmcs_hdl_t hdl, JMCSLinkageList_t *list); // JBOOL reverse = JTRUE; // JBASDevInfo_t devinfo; // JES_BAS_GetDevInfo(g_jbas, &devinfo, JTRUE); // PRSTR(devinfo.devname); // PRSTR(devinfo.language); 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; // ControlInstructions[7]=0x00; // ControlInstructions[8]=0x00; // ControlInstructions[9]=0x00; // ControlInstructions[10]=0x00; // ControlInstructions[11]=0x00; // ControlInstructions[12]=0x00; // ControlInstructions[13]=0x00; // ControlInstructions[14]=0x00; // ControlInstructions[15]=0x00; // ControlInstructions[16]=0x00; // ControlInstructions[17]=0x00; // ControlInstructions[18]=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) << endl; //处理ControlInstructions数据 //if (result[0] == '1') ControlInstructions[(g_camera_number - 1) * 4] = 0x01; //if (result[1] == '1') ControlInstructions[(g_camera_number - 1) * 4 + 1] = 0x01; //if (result[2] == '1') ControlInstructions[(g_camera_number - 1) * 4 + 2] = 0x01; //if (result[3] == '1') ControlInstructions[(g_camera_number - 1) * 4 + 3] = 0x01; if (result[0] == '1') ControlInstructions[0] = 0x01; if (result[1] == '1') ControlInstructions[1] = 0x01; if (result[2] == '1') ControlInstructions[2] = 0x01; if (result[3] == '1') ControlInstructions[3] = 0x01; std::string indices = generateIndices(result, &Alarm); std::cout << "结果: " << indices << std::endl; Alarm.alarmCoverage = indices; } if (time2run && Alarm.ifalarm) { printf("******************************\n"); // 创建第一个子进程:控制继电器 pid_t relay_pid = fork(); if (relay_pid == 0) { printf("kongzhi jidianqi\n"); reset_relay(); exit(0); // 子进程完成继电器控制后退出 } // 创建第二个子进程:播放音频 pid_t audio_pid = fork(); if (audio_pid == 0) { printf("yuyin bobao\n"); jbus_hdl_t jbus = jbus_init("spktest"); jmss_hdl_t jms = JES_MSS_Init(jbus); jspk_hdl_t jspk = JES_SPK_Init(jbus); JMediaAencParam_t adec; JES_SPK_GetParam(jspk, &adec, JFALSE); adec.attr.volume = 80; adec.attr.encType = JVMEDIA_AUDIO_TYPE_G711_A; JES_SPK_SetParam(jspk, &adec); // 播放音频 play_audio("/demo/bin/Sound.g711u", jspk); // 清理 JES_SPK_Deinit(jspk); JES_MSS_Deinit(jms); jbus_cleanup(jbus); exit(0); // 子进程完成音频播放后退出 } cv::Mat rgb_img; cv::cvtColor(src, rgb_img, COLOR_BGR2RGB); // std::string filename = "result" + std::string(labels[name_int]) + ".jpg"; std::string filename = "/demo/pic/" + Get_Time(2) + ".jpg"; cv::imwrite(filename, rgb_img, compression_params); std::ifstream file(filename, std::ios::in | std::ios::binary); std::ostringstream oss; oss << file.rdbuf(); std::string orig_data = oss.str(); // 编码图片数据为base64格式 std::string encoded_data = base64_encode(reinterpret_cast(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 << std::endl; std::string MessageString = R"({ "cameraid": ")" + cameraId + R"(", "controllerId": ")" + controllerId + R"(", "msg": ")" + msg + R"(", "type": ")" + type + R"(", "errNum": ")" + Coverage + R"(", "img": ")" + img + R"(", "time": ")" + time + R"(" })"; CURL* curl; CURLcode res; curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST"); curl_easy_setopt(curl, CURLOPT_URL, upload_url); /* 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_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); 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 << "Failed to perform cURL request: " << curl_easy_strerror(res) << std::endl; } else { std::cout << "Request successful!" << std::endl; std::cout << "Response: " << response << std::endl; } curl_easy_cleanup(curl); } curl_global_cleanup(); } void* upload_message_controller(void* args) { pthread_detach(pthread_self()); 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 Coverage = (alarm->alarmCoverage).c_str(); std::cout << "cameraid: " << cameraId << " errNum: " << Coverage << std::endl; std::string MessageString = R"({ "cameraid": ")" + cameraId + R"(", "errNum": ")" + Coverage + 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/alarm"); /* 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()); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10L); // std::string response; // 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 << "controller: Failed to perform cURL request: " << curl_easy_strerror(res) << std::endl; } else { std::cout << "controller: Request successful!" << std::endl; // std::cout << "controller: Response: " << response << std::endl; } curl_easy_cleanup(curl); } curl_global_cleanup(); } void* heart_beat(void* args) { pthread_detach(pthread_self()); auto last_time = std::chrono::high_resolution_clock::now();// 记录开始时间 int time2run = 1; while (!quit) { auto current_time = std::chrono::high_resolution_clock::now(); auto elapsed_time = std::chrono::duration_cast(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; } fd_set readfds; struct timeval timeout; int selectResult; 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; } } } // pthread_t storage_serial; // pthread_create(&storage_serial, NULL, storage_serial_thread, NULL); // 首先定义协议相关的常量 #define PROTOCOL_HEAD 0x7E #define PROTOCOL_VERSION 1 #define PROTOCOL_LENGTH 22 #define SOLENOID_VALVE_COUNT 16 #define COMMAND_QUERY 1 #define COMMAND_RESPONSE 2 // 定义协议结构体 typedef struct tagCamera485Protocol { uint8_t m_head; // 协议头 0x7e uint8_t m_version; // 版本1~255 uint8_t m_length; // 协议总长度,包含校验位 uint8_t m_address; // 地址0~255 uint8_t m_command; // 操作指令 uint8_t m_solenoidValve[SOLENOID_VALVE_COUNT]; // 电磁阀状态 uint8_t m_checkSum; // 校验和 } CCamera485Protocol; // 优化后的storage_serial_thread函数 void* storage_serial_thread(void* args) { pthread_detach(pthread_self()); // { // test *ptest1 = NULL; // test *ptest2[2] = {}; // if (ptest1 == ptest2[0]) // { // printf("ptest1 == ptest2"); // } // else // { // printf("ptest1 != ptest2"); // } // return 0; // } juart_hdl_t hdl = juart_open("/dev/ttyS5"); JUartAttr_t attr = {.baudrate = 9600, .datawidth = 8, .stopbit = 1, .parity = 0}; juart_set_attr(hdl, &attr); juart_set_rs485(hdl, 0); unsigned char hexData[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0xC4, 0x0B}; juart_send(hdl, (char*)hexData, sizeof(hexData)); printf("send: "); hexdump((char*)hexData, sizeof(hexData)); while (1) { CCamera485Protocol protocol; int len = juart_recv(hdl, (char *)&protocol, sizeof(CCamera485Protocol), 30); // if (len <= 0) // { // printf("==============>>>: %s,%d: recv timeout!\n", strrchr(__FILE__,'/'),__LINE__); // } if (len == sizeof(CCamera485Protocol)) { hexdump((char*)&protocol,len); // 处理协议 if (protocol.m_head == PROTOCOL_HEAD && protocol.m_command == COMMAND_QUERY && protocol.m_address == (g_camera_number - 1)) { // 构造响应 uint8_t response_array[22] = {0}; // 1. 填充头部 response_array[0] = PROTOCOL_HEAD; // 协议头 response_array[1] = PROTOCOL_VERSION; // 版本 response_array[2] = PROTOCOL_LENGTH; // 长度 response_array[3] = g_camera_number - 1; // 地址 response_array[4] = COMMAND_RESPONSE; // 命令 // 2. 填充电磁阀状态 mtx.lock(); for (int i = 0; i < SOLENOID_VALVE_COUNT; i++) { response_array[5 + i] = ControlInstructions[i]; } mtx.unlock(); // 3. 计算校验和(前21字节累加和) uint8_t sum = 0; for (int i = 0; i < 21; i++) { sum += response_array[i]; } response_array[21] = sum; // 校验和 juart_send(hdl, (char*)response_array, sizeof(response_array)); hexdump((char*)&response_array,sizeof(response_array)); std::fill(ControlInstructions.begin(), ControlInstructions.end(), 0x00); //sleep(2); } } } juart_close(hdl); return 0; }