1822 lines
60 KiB
C++
1822 lines
60 KiB
C++
#include "main.h"
|
||
//4 13 22 31
|
||
#include <opencv2/opencv.hpp>
|
||
#include <stdio.h>
|
||
#include <sys/time.h>
|
||
#include"yolov5_detect.h"
|
||
|
||
#include <iostream>
|
||
#include <chrono>
|
||
#include <thread>
|
||
#include <fstream>
|
||
#include <cstdio>
|
||
#include <iostream>
|
||
#include <fstream>
|
||
#include <cstring>
|
||
#include <vector>
|
||
#include <iomanip>
|
||
#include <filesystem>
|
||
#include <algorithm>
|
||
|
||
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <dlfcn.h>
|
||
#include <vector>
|
||
#include <string>
|
||
#include <stdbool.h>
|
||
#include <iostream>
|
||
#include <sys/stat.h>
|
||
#include <curl/curl.h>
|
||
#include <openssl/rsa.h>
|
||
#include <openssl/pem.h>
|
||
#include <openssl/err.h>
|
||
#include <nlohmann/json.hpp>
|
||
|
||
#include <jvbase/jlog.h>
|
||
#include <jvbase/jvtypes.h>
|
||
#include <jvbase/jstring.h>
|
||
#include <jbus.h>
|
||
#include <jes/jes_mss.h>
|
||
#include <jes/jes_isp.h>
|
||
#include <jes/jes_spk.h>
|
||
#include <jes/jes_bas.h>
|
||
#include "jlinux_uart.h"
|
||
|
||
#include <termios.h>
|
||
#include <cmath>
|
||
|
||
#include <nlohmann/json.hpp>
|
||
#include <mutex>
|
||
|
||
#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<uint8_t> 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<unsigned char> encrypted(keySize);
|
||
|
||
int len = RSA_public_encrypt(
|
||
plaintext.size(),
|
||
reinterpret_cast<const unsigned char*>(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<char*>(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<mutex> 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<char>(file)), istreambuf_iterator<char>());
|
||
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<int>();
|
||
|
||
if (code == 0) {
|
||
generateLicenseFile(device_id_ + "|" + mac_);
|
||
return true;
|
||
}
|
||
|
||
if (code == 60001 || code == 60002) {
|
||
cerr << "[FATAL] Activation failed: " << json_resp["msg"].get<string>() << 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<string> 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<vector<int>> last_result;
|
||
auto last_result_time = std::chrono::high_resolution_clock::now();// 时间
|
||
vector<vector<int>> now_result;
|
||
|
||
int width = 1920, height = 1080;
|
||
JMediaRawFrameType_e type = JMEDIA_RAWFRAMETYPE_NV12;
|
||
|
||
|
||
bool check_whether_in_last_result(vector<vector<int>>& last_result, vector<int>& 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<char*>(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<uint8_t>& data) {
|
||
uint16_t sum = 0;
|
||
for (size_t i = 0; i < data.size() - 1; ++i) {
|
||
sum += data[i];
|
||
}
|
||
return static_cast<uint8_t>(sum & 0xFF);
|
||
}
|
||
|
||
|
||
void printVector(const std::vector<uint8_t>& vec) {
|
||
std::cout << "Vector contents: ";
|
||
for (const auto& byte : vec) {
|
||
std::cout << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(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<char*>(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<int> compression_params;
|
||
compression_params.push_back(cv::IMWRITE_JPEG_QUALITY);
|
||
compression_params.push_back(30); // 设置压缩质量,范围为 0-100
|
||
int overtem_cnt = 0;
|
||
std::vector<int> 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<std::chrono::milliseconds>(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<std::chrono::milliseconds>(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<int> 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] = 0x01;
|
||
if (result[2] == '1') ControlInstructions[(g_camera_number - 1) * 4] = 0x01;
|
||
if (result[3] == '1') ControlInstructions[(g_camera_number - 1) * 4] = 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<const unsigned char*>(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<void*>(&Alarm));
|
||
pthread_t upload_message_controller_tidp;
|
||
int ret = pthread_create(&upload_message_controller_tidp, NULL, upload_message_controller, static_cast<void*>(&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<Alarm*>(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<Alarm*>(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<std::chrono::milliseconds>(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), 6000);
|
||
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;
|
||
} |