| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801 |
- /**
- * common.h — 公共类型定义、枚举、结构体、全局变量声明
- * v43.2 模块化拆分 (编译修复版)
- */
- #ifndef COMMON_H
- #define COMMON_H
- #include <iostream>
- #include <iomanip>
- #include <sstream>
- #include <fstream>
- #include <thread>
- #include <mutex>
- #include <condition_variable>
- #include <deque>
- #include <list>
- #include <stdexcept>
- #include <unistd.h>
- #include <chrono>
- #include <time.h>
- #include <functional>
- #include <cmath>
- #include <climits>
- #include <sys/stat.h>
- #include <cstdlib>
- #include <cstring>
- #include <unordered_set>
- #include <unordered_map>
- #include <memory>
- #include <atomic>
- #include <csignal>
- #include <algorithm>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <assert.h>
- #include <errno.h>
- #include <ctype.h>
- #include <vector>
- #include <string>
- #include <map>
- #include <utility>
- #include <ctime>
- #include <limits.h>
- #include <curl/curl.h>
- #include <cjson/cJSON.h>
- #include "opencv2/opencv.hpp"
- #include <sqlite3.h>
- #include <openssl/md5.h>
- extern "C" {
- #include <libavformat/avformat.h>
- #include <libavcodec/avcodec.h>
- #include <libavutil/avutil.h>
- #include <libavutil/hwcontext.h>
- #include <libavutil/hwcontext_drm.h>
- #include <libavutil/imgutils.h>
- #include <libswscale/swscale.h>
- }
- // HyperLPR3 SDK
- #include "hyper_lpr_sdk.h"
- // httplib 前向声明(避免在所有模块中包含大头文件)
- namespace httplib { class Server; }
- // ==================== 全局常量定义 ====================
- // ✅ fix24-v16: Web服务端口从config.ini [server] ip字段解析,不再硬编码
- #define WEB_SERVER_PORT_DEFAULT 8080
- #define MAX_DB_RECORDS 10000
- #define INTERVAL_SECONDS (5 * 60)
- #define KEYVALLEN 100
- extern int g_max_photo_groups;
- const int MAX_UPLOAD_FAIL = 5;
- const int BLOCK_TIMEOUT_SEC = 300;
- const int PLATE_DUPLICATE_INTERVAL_MS = 2000;
- const int REQUIRED_SUCCESS_GROUPS = 2;
- const int PHOTO_RETRY_COUNT = 2;
- const int HTTP_STATUS_OK = 200;
- const int BUSINESS_ERROR_CODE = 257;
- const int DB_CLEANUP_THRESHOLD_MB = 500;
- const long long DB_CLEANUP_THRESHOLD_BYTES = (long long)DB_CLEANUP_THRESHOLD_MB * 1024 * 1024;
- const int TOKEN_EXPIRE_SECONDS = 7200;
- const int TOKEN_REFRESH_BUFFER_SECONDS = 300;
- const int MAX_BILL_COUNT_PER_WINDOW = 1;
- const int MAX_RETRY_COUNT = 5;
- const int MAX_UPLOAD_PER_CYCLE = 2;
- const int PLATE_CLEANUP_TIMEOUT_SEC = 60;
- const int DAILY_CLEANUP_HOUR = 23;
- const int DAILY_CLEANUP_MINUTE = 10;
- const int STATUS_CLEANUP_INTERVAL_SEC = 600;
- const int MAIN_LOOP_BLOCK_THRESHOLD_MS = 500;
- const int DB_INSERT_RETRY_COUNT = 1;
- const int DB_BUSY_TIMEOUT_MS = 100;
- const int DB_HEALTH_CHECK_INTERVAL_SEC = 60;
- // ==================== 每日文件清理配置(fix19修改) ====================
- const int FILE_CLEANUP_HOUR = 2; // 凌晨2点执行文件清理
- const int FILE_CLEANUP_MINUTE = 0;
- // 照片清理:按容量阈值(MB),默认1GB,可通过config.ini配置
- extern long long g_photo_max_capacity_mb;
- // 日志清理:按天数,默认30天,可通过config.ini配置
- extern int g_log_retention_days;
- // ==================== 错误码定义 ====================
- enum class ErrorCode {
- SUCCESS = 0,
- NETWORK_ERROR = -1,
- BUSINESS_ERROR = -2,
- PARSE_ERROR = -3,
- INVALID_PARAM = -4,
- BLOCKED = -5,
- QUOTA_EXCEEDED = -6,
- DB_ERROR = -7,
- PERMANENT_FAILURE = -8
- };
- // ==================== 照片上传结果结构体 ====================
- struct PhotoUploadResult {
- bool lo_success;
- bool hi_success;
- int success_groups;
- PhotoUploadResult() : lo_success(false), hi_success(false), success_groups(0) {}
- };
- // ==================== 核心:进站/出站完全独立的状态管理 ====================
- struct ScenePlateStatus {
- private:
- std::unordered_set<std::string> blocked_plates;
- std::unordered_map<std::string, int> fail_count;
- std::unordered_map<std::string, time_t> block_time;
- mutable std::mutex mtx;
- public:
- bool is_blocked(const std::string& plate) {
- std::lock_guard<std::mutex> lock(mtx);
- auto it = blocked_plates.find(plate);
- if (it == blocked_plates.end()) return false;
- if (time(nullptr) >= block_time[plate]) {
- blocked_plates.erase(it);
- fail_count.erase(plate);
- block_time.erase(plate);
- return false;
- }
- return true;
- }
- void add_fail(const std::string& plate) {
- std::lock_guard<std::mutex> lock(mtx);
- fail_count[plate]++;
- if (fail_count[plate] >= MAX_UPLOAD_FAIL) {
- blocked_plates.insert(plate);
- block_time[plate] = time(nullptr) + BLOCK_TIMEOUT_SEC;
- }
- }
- void reset(const std::string& plate) {
- std::lock_guard<std::mutex> lock(mtx);
- blocked_plates.erase(plate);
- fail_count.erase(plate);
- block_time.erase(plate);
- }
- void cleanup_expired() {
- std::lock_guard<std::mutex> lock(mtx);
- time_t now = time(nullptr);
- for (auto it = block_time.begin(); it != block_time.end(); ) {
- if (now >= it->second) {
- blocked_plates.erase(it->first);
- fail_count.erase(it->first);
- it = block_time.erase(it);
- } else ++it;
- }
- }
- };
- extern ScenePlateStatus g_in_plate_status;
- extern ScenePlateStatus g_out_plate_status;
- // ==================== ROI配置结构体(v43新增) ====================
- struct ROIConfig {
- int x = 0;
- int y = 0;
- int width = 0;
- int height = 0;
- bool enabled = false;
- bool isFullFrame() const {
- return x == 0 && y == 0 && width == 0 && height == 0;
- }
- cv::Rect getRect(int img_w, int img_h) const {
- return cv::Rect(
- std::max(0, std::min(x, img_w - 1)),
- std::max(0, std::min(y, img_h - 1)),
- std::min(width > 0 ? width : img_w, img_w - std::max(0, std::min(x, img_w - 1))),
- std::min(height > 0 ? height : img_h, img_h - std::max(0, std::min(y, img_h - 1)))
- );
- }
- std::string toString() const {
- return "[" + std::to_string(x) + "," + std::to_string(y) + ","
- + std::to_string(width) + "," + std::to_string(height) + "]"
- + (enabled ? " ON" : " OFF");
- }
- };
- // ==================== 解码模式枚举(v43新增) ====================
- enum class DecodeMode {
- AUTO = 0,
- SOFT = 1,
- DRM = 2
- };
- // ==================== 进站/出站交替锁定机制 ====================
- enum class StationMode : int {
- INBOUND_ALLOWED = 0,
- OUTBOUND_ALLOWED = 1
- };
- struct PlateStationState {
- std::string plate;
- time_t last_in_time;
- time_t last_out_time;
- StationMode current_mode;
- PlateStationState() : last_in_time(0), last_out_time(0),
- current_mode(StationMode::INBOUND_ALLOWED) {}
- };
- // ==================== 联单缓存结构 ====================
- struct InBillCacheEntry {
- std::string tb_num;
- time_t create_time;
- int hit_count;
- int photo_count;
- bool bill_created;
- };
- struct OutBillCacheEntry {
- std::string tb_num;
- time_t create_time;
- int hit_count;
- int photo_count;
- bool bill_created;
- };
- // ==================== 错误恢复策略 ====================
- enum class UploadError {
- SUCCESS = 0,
- NETWORK_TIMEOUT,
- NETWORK_CONNECTION_FAILED,
- SERVER_ERROR_4XX,
- SERVER_ERROR_5XX,
- AUTH_FAILED,
- INVALID_RESPONSE,
- IMAGE_TOO_LARGE,
- UNKNOWN_ERROR
- };
- struct RecoveryStrategy {
- int max_retries;
- int retry_delay_ms;
- bool should_retry;
- };
- // ==================== 场景上传记录(TIME_WINDOW持久化) ====================
- struct SceneUploadRecord {
- int bill_count;
- time_t last_time;
- time_t trigger_time;
- bool bill_created;
- int photo_success_count;
- bool feishu_sent;
- int generation;
- time_t create_time;
- std::string tb_num;
- SceneUploadRecord() : bill_count(0), last_time(0), trigger_time(0),
- bill_created(false), photo_success_count(0), feishu_sent(false),
- generation(0), create_time(time(NULL)) {}
- };
- // ==================== 监控指标 ====================
- struct MonitorMetrics {
- std::atomic<int> createbill_total{ 0 };
- std::atomic<int> createbill_success{ 0 };
- std::atomic<int> createbill_business_error{ 0 };
- std::atomic<int> createbill_quota_exceeded{ 0 };
- std::deque<std::pair<time_t, int>> upload_time_records;
- std::mutex upload_time_mtx;
- std::atomic<int> time_window_hits{ 0 };
- std::atomic<int> in_cache_hits{ 0 };
- std::atomic<int> in_cache_misses{ 0 };
- std::atomic<int> out_cache_hits{ 0 };
- std::atomic<int> out_cache_misses{ 0 };
- std::atomic<int> upload_errors{ 0 };
- std::atomic<int> network_timeouts{ 0 };
- std::atomic<int> server_errors{ 0 };
- std::atomic<int> in_station_count{ 0 };
- std::atomic<int> out_station_count{ 0 };
- std::atomic<int> feishu_success_count{ 0 };
- std::deque<time_t> five_min_upload_times;
- std::mutex five_min_mtx;
- time_t start_time{ 0 };
- std::atomic<long long> main_loop_block_count{ 0 };
- std::atomic<long long> main_loop_max_block_ms{ 0 };
- std::atomic<int> photo_lo_success{ 0 };
- std::atomic<int> photo_hi_success{ 0 };
- std::atomic<int> photo_group_success{ 0 };
- std::atomic<int> db_duplicate_skip_count{ 0 };
- std::atomic<int> dir_create_error_count{ 0 };
- std::atomic<int> db_insert_error_count{ 0 };
- std::atomic<int> db_insert_retry_success{ 0 };
- std::atomic<int> permanent_failure_count{ 0 };
- std::atomic<int> alert_sent_count{ 0 };
- std::atomic<int> db_health_check_count{ 0 };
- // v42新增:交替锁定监控指标
- std::atomic<int> station_lock_in_count{ 0 };
- std::atomic<int> station_lock_out_count{ 0 };
- std::atomic<int> station_in_block_count{ 0 };
- std::atomic<int> station_out_block_count{ 0 };
- std::atomic<int> station_timeout_cleanup_count{ 0 };
- // v43新增:ROI监控指标
- std::atomic<int> roi_in_crop_count{ 0 };
- std::atomic<int> roi_out_crop_count{ 0 };
- std::atomic<int> roi_in_fullframe_count{ 0 };
- std::atomic<int> roi_out_fullframe_count{ 0 };
- // v43新增:飞书/解码/Web监控指标
- std::atomic<int> feishu_skip_count{ 0 };
- std::atomic<int> drm_decode_count{ 0 };
- std::atomic<int> soft_decode_count{ 0 };
- std::atomic<int> web_retry_count{ 0 };
- std::atomic<int> web_retry_success_count{ 0 };
- // fix20新增:推理耗时追踪
- std::deque<std::pair<time_t, int>> infer_time_records;
- std::mutex infer_time_mtx;
- void record_roi_crop(bool is_in) {
- is_in ? roi_in_crop_count++ : roi_out_crop_count++;
- }
- void record_roi_fullframe(bool is_in) {
- is_in ? roi_in_fullframe_count++ : roi_out_fullframe_count++;
- }
- void record_feishu_skip() { feishu_skip_count++; }
- void record_drm_decode() { drm_decode_count++; }
- void record_soft_decode() { soft_decode_count++; }
- void record_web_retry(bool success) {
- web_retry_count++;
- if (success) web_retry_success_count++;
- }
- void record_station_lock(bool is_in) {
- is_in ? station_lock_in_count++ : station_lock_out_count++;
- }
- void record_station_block(bool is_in) {
- is_in ? station_in_block_count++ : station_out_block_count++;
- }
- void record_station_timeout_cleanup() {
- station_timeout_cleanup_count++;
- }
- void record_upload_time(int duration_ms) {
- std::lock_guard<std::mutex> lock(upload_time_mtx);
- upload_time_records.push_back({ time(NULL), duration_ms });
- if (upload_time_records.size() > 10) {
- upload_time_records.pop_front();
- }
- }
- void record_createbill(bool success, bool is_business_error = false, bool is_quota_exceeded = false) {
- createbill_total++;
- if (success) createbill_success++;
- if (is_business_error) createbill_business_error++;
- if (is_quota_exceeded) createbill_quota_exceeded++;
- }
- void record_cache_hit(bool is_in, bool hit) {
- if (is_in) hit ? in_cache_hits++ : in_cache_misses++;
- else hit ? out_cache_hits++ : out_cache_misses++;
- }
- void record_error(UploadError error) {
- upload_errors++;
- switch (error) {
- case UploadError::NETWORK_TIMEOUT: network_timeouts++; break;
- case UploadError::SERVER_ERROR_5XX: server_errors++; break;
- default: break;
- }
- }
- void record_station(bool is_in) {
- is_in ? in_station_count++ : out_station_count++;
- }
- void record_feishu_success() { feishu_success_count++; }
- void record_photo_upload(bool lo_success, bool hi_success, bool group_success) {
- if (lo_success) photo_lo_success++;
- if (hi_success) photo_hi_success++;
- if (group_success) photo_group_success++;
- }
- void record_main_loop_block(long long duration_ms) {
- main_loop_block_count++;
- if (duration_ms > main_loop_max_block_ms.load()) {
- main_loop_max_block_ms.store(duration_ms);
- }
- if (duration_ms > MAIN_LOOP_BLOCK_THRESHOLD_MS) {
- std::cerr << "[告警] 主循环阻塞 " << duration_ms << "ms,超过阈值 "
- << MAIN_LOOP_BLOCK_THRESHOLD_MS << "ms" << std::endl;
- }
- }
- void record_db_duplicate_skip() { db_duplicate_skip_count++; }
- void record_dir_create_error() { dir_create_error_count++; }
- void record_db_insert_error() { db_insert_error_count++; }
- void record_db_insert_retry_success() { db_insert_retry_success++; }
- void record_permanent_failure() { permanent_failure_count++; }
- void record_alert_sent() { alert_sent_count++; }
- void record_db_health_check() { db_health_check_count++; }
- void record_inference_time(int duration_ms) {
- std::lock_guard<std::mutex> lock(infer_time_mtx);
- infer_time_records.push_back({ time(NULL), duration_ms });
- if (infer_time_records.size() > 20) {
- infer_time_records.pop_front();
- }
- }
- int get_avg_inference_time() {
- std::lock_guard<std::mutex> lock(infer_time_mtx);
- if (infer_time_records.empty()) return 0;
- int total = 0;
- for (auto& p : infer_time_records) total += p.second;
- return total / (int)infer_time_records.size();
- }
- int get_last_inference_time() {
- std::lock_guard<std::mutex> lock(infer_time_mtx);
- if (infer_time_records.empty()) return 0;
- return infer_time_records.back().second;
- }
- int get_avg_upload_time() {
- std::lock_guard<std::mutex> lock(upload_time_mtx);
- if (upload_time_records.empty()) return 0;
- int total = 0;
- for (auto& p : upload_time_records) total += p.second;
- return total / upload_time_records.size();
- }
- float get_createbill_success_rate() {
- int total = createbill_total.load();
- return total > 0 ? (float)createbill_success.load() / total : 0.0f;
- }
- float get_cache_hit_rate(bool is_in) {
- if (is_in) {
- int total = in_cache_hits.load() + in_cache_misses.load();
- return total > 0 ? (float)in_cache_hits.load() / total : 0.0f;
- } else {
- int total = out_cache_hits.load() + out_cache_misses.load();
- return total > 0 ? (float)out_cache_hits.load() / total : 0.0f;
- }
- }
- std::string get_uptime_string() {
- if (start_time == 0) return "0h00m00s";
- auto secs = time(NULL) - start_time;
- int h = secs / 3600; int m = (secs % 3600) / 60; int s = secs % 60;
- std::ostringstream oss;
- oss << h << "h" << std::setfill('0') << std::setw(2) << m << "m" << std::setw(2) << s << "s";
- return oss.str();
- }
- void print_report();
- };
- extern MonitorMetrics g_metrics;
- // ==================== C风格枚举和结构体 ====================
- typedef enum {
- BUILDING = 1,
- DOCK = 2,
- BACKFILL = 3
- } WTYPE;
- typedef enum {
- STATION_IN = 1,
- STATION_OUT = 2
- } DTYPE;
- typedef enum {
- POSITION_LO = 1,
- POSITION_HI = 2
- } GTYPE;
- typedef enum {
- CAPTURE_NORMAL = 1,
- CAPTURE_CAMERA_OFFLINE,
- CAPTURE_STORAGE_ERROR,
- CAPTURE_LENS_OBSTRUCTED,
- CAPTURE_ANGLE_ABNORMAL
- } CaptureStatus;
- typedef struct {
- WTYPE wtype;
- DTYPE dtype;
- GTYPE gtype;
- CaptureStatus status;
- time_t capture_time = 0; // ✅ fix23: 抓拍时间戳,保存帧被捕获时的时间
- } CaptureInfo;
- typedef struct {
- std::string tb_num;
- float confidence = 0.0f;
- std::string type;
- std::string code;
- cv::Mat image_front;
- cv::Mat image_side;
- int count = 0;
- bool is_report = false;
- std::string pic_path_front;
- std::string pic_path_side;
- int retry_count = 0;
- std::unique_ptr<CaptureInfo> cap_info_copy;
- time_t first_seen_time = 0;
- int db_id = 0;
- bool is_inbound = false;
- bool is_outbound = false;
- bool photo_saved = false;
- time_t last_station_blocked_time = 0; // ✅ fix11: 交替锁定拦截时间戳,防止被拦截后空转
- bool blocked_by_station_lock = false; // ✅ fix13: 区分BLOCKED来源(true=交替锁定, false=is_blocked)
- std::atomic<bool> upload_in_progress{false}; // ✅ fix18-P0: 上传进行中标志,防止peek与try_lock竞态
- time_t upload_complete_time = 0; // ✅ fix24-v6: 上传完成时间戳,防止刚上传完就被peek重置导致重复保存
- time_t db_capture_time = 0; // ✅ fix24-v18: 照片保存时固定的capture_time,防止识别线程竞态覆盖导致DB时间不一致
- } CarPlateInfo;
- // ==================== RTSPCapture 前向声明 ====================
- class RTSPCapture;
- // ==================== PlateRecApp 结构体 ====================
- typedef struct {
- P_HLPR_Context hlpr_ctx;
- RTSPCapture* capture_front_in = nullptr;
- RTSPCapture* capture_front_out = nullptr;
- RTSPCapture* capture_side_in = nullptr;
- RTSPCapture* capture_side_out = nullptr;
- CaptureInfo front_info_in;
- CaptureInfo front_info_out;
- CaptureInfo side_info_in;
- CaptureInfo side_info_out;
- time_t timer_front_in;
- time_t timer_front_out;
- std::mutex map_mtx;
- std::unordered_map<std::string, std::shared_ptr<CarPlateInfo>> map;
- } PlateRecApp;
- // ==================== 全局变量 extern 声明 ====================
- // 路径
- extern std::string pathComm;
- extern std::string model_path;
- // 配置变量
- extern std::string project_name;
- extern std::string point_number;
- extern std::string throughway;
- extern std::string rtsp_url_front_in;
- extern std::string rtsp_url_front_out;
- extern std::string rtsp_url_side_in;
- extern std::string rtsp_url_side_out;
- extern std::string app_api;
- extern std::string app_key;
- extern std::string app_secret;
- extern int DEBUG_LOG;
- extern std::atomic<int> TestFlag;
- extern int g_wType;
- extern int g_time_window_min;
- extern double g_PLATE_CONFIDENCE_THRESHOLD;
- extern double g_PLATE_LOG_THRESHOLD;
- // v43新增全局变量
- extern bool g_alternating_merge_enabled;
- extern ROIConfig g_roi_in;
- extern ROIConfig g_roi_out;
- extern bool g_roi_debug_enabled;
- extern DecodeMode g_hw_decode_mode;
- extern std::string g_hw_decode_device;
- extern std::string g_rtsp_transport;
- extern bool g_suppress_emergency_alert;
- extern int g_in_out_interval_sec;
- // fix24-v8: 共享摄像头模式(进站和出站共用同一个前向摄像头)
- // 启用后,根据交替锁定状态自动判断检测到的车牌是进站还是出站
- extern bool g_shared_capture_mode;
- // fix24-v14: 本地时区偏移(秒),用于SQLite中create_time字符串转Unix时间戳的校正
- extern int g_tz_offset_seconds;
- // fix18: config.ini路径(用于ROI写回)
- extern std::string g_config_ini_path;
- // fix18: 称重系统全局变量(config.ini key映射已在config.cpp中匹配)
- extern bool g_weight_enabled;
- extern bool g_flag_weight; // fix27: 飞书消息是否包含重量信息(config.ini: flagWeight=1)
- extern double g_weight_threshold_in;
- extern double g_weight_threshold_out;
- extern double g_weight_default_entry;
- extern double g_weight_default_exit;
- extern int g_weight_detection_time;
- extern int g_weight_tcp_connect_timeout;
- extern std::string g_weight_server_ip;
- extern int g_weight_server_port;
- extern double g_weight_max_kg;
- extern double g_weight_min_kg;
- extern int g_weight_stable_samples;
- extern double g_weight_stable_threshold;
- extern int g_weight_candidate_count;
- extern int g_weight_max_retries;
- extern int g_weight_retry_delay_ms;
- // fix18: MQTT全局变量
- extern bool g_mqtt_enabled;
- extern std::string g_mqtt_host;
- extern int g_mqtt_port;
- extern std::string g_mqtt_username;
- extern std::string g_mqtt_password;
- extern std::string g_mqtt_topic;
- extern std::string g_mqtt_client_id;
- // MQTT消息附加字段(从[MQTT]节点读取)
- extern std::string g_plate_color;
- extern std::string g_vehicle_type;
- // ==================== fix24 v43: [sync] 并行同步配置 ====================
- extern bool g_sync_parallel_enabled; // [sync] enabled (0=退回v41串行, 1=启用v43并行)
- extern int g_sync_reporter_timeout_sec; // Reporter 等待两路结果超时(秒)
- extern int g_sync_weight_retry_max; // 重量独立重试最大次数
- extern int g_sync_weight_retry_interval_sec; // 重量重试间隔(秒)
- extern int g_sync_tb_num_dedup_sec; // tb_num 去重窗口(秒)
- extern int g_sync_weight_snapshot_max_age_sec; // fix24 v43 Bug#18: 重量快照最大年龄(秒)
- // ==================== fix24 v44 P0: 预检测锁定配置 ====================
- // 地磅场景:车辆整体开上秤台,重量一次性加载,不存在半上秤误判
- // TCP线程每200ms采样,连续 prelock_stable_samples 个样本稳定且 > prelock_threshold_kg 即锁定
- // 车牌检测后优先消费预锁定值(0等待),未命中再走快照→阻塞等待
- extern double g_weight_prelock_threshold_kg; // 预检测触发阈值(kg),0=禁用
- extern int g_weight_prelock_stable_samples; // 预检测锁定时需要的连续稳定样本数
- // 交替锁定
- extern std::map<std::string, PlateStationState> g_plate_station_cache;
- extern std::mutex g_station_cache_mtx;
- extern const int STATION_CLEANUP_INTERVAL_SEC;
- const int STATION_LOCK_EXPIRE_SEC = 7200; // ✅ fix18: 交替锁定记录2小时过期,超时清零
- // ✅ fix16: 移除OUT_NO_RECORD_TIMEOUT_SEC和g_out_no_record_first_seen
- // 出站无进站记录永远拦截,不再需要超时放行机制
- // 帧级别去重
- extern std::unordered_map<std::string, time_t> g_in_plate_last_processed;
- extern std::unordered_map<std::string, time_t> g_out_plate_last_processed;
- extern std::mutex g_in_plate_last_processed_mtx;
- extern std::mutex g_out_plate_last_processed_mtx;
- // 飞书
- extern bool g_feishu_enabled; // fix27: 飞书消息独立开关(config.ini: [feishu] ENABLED=1)
- extern std::string g_feishu_app_id;
- extern std::string g_feishu_app_secret;
- extern std::string g_feishu_chat_id;
- extern long g_feishu_timeout_second;
- // 联单缓存
- extern std::unordered_map<std::string, InBillCacheEntry> g_in_bill_cache;
- extern std::mutex g_in_bill_cache_mtx;
- extern std::unordered_map<std::string, OutBillCacheEntry> g_out_bill_cache;
- extern std::mutex g_out_bill_cache_mtx;
- extern std::unordered_map<std::string, int> g_in_record;
- extern std::mutex g_in_record_mtx;
- extern std::unordered_map<std::string, int> g_out_record;
- extern std::mutex g_out_record_mtx;
- // 场景上传记录
- extern std::unordered_map<std::string, SceneUploadRecord> g_in_upload_records;
- extern std::unordered_map<std::string, SceneUploadRecord> g_out_upload_records;
- // 特殊车牌
- extern std::vector<std::string> g_special_plates;
- extern std::mutex g_special_plates_mtx;
- // 重试队列
- extern std::deque<std::shared_ptr<CarPlateInfo>> g_retry_queue;
- extern std::mutex g_retry_queue_mtx;
- // 数据库
- extern sqlite3* g_db;
- extern std::mutex g_db_mtx;
- extern std::string g_db_path;
- // Token
- extern std::string g_tenant_token;
- extern std::atomic<time_t> g_token_expire_time;
- extern std::mutex g_token_mtx;
- // 全局状态
- extern volatile std::sig_atomic_t g_running;
- extern std::atomic<time_t> g_last_data_activity_time;
- // PlateRecApp实例
- extern PlateRecApp plate_rec_app;
- extern uint32_t count;
- extern std::atomic<int> g_active_detach_threads;
- // Web服务器
- extern std::unique_ptr<std::thread> g_web_server_thread;
- extern std::unique_ptr<httplib::Server> g_web_server;
- extern std::atomic<bool> g_web_server_running;
- extern std::atomic<bool> g_web_server_initialized;
- // ✅ fix24-v19: HTTP重定向服务器(HTTP->HTTPS自动跳转)
- extern std::unique_ptr<std::thread> g_http_redirect_thread;
- extern std::unique_ptr<httplib::Server> g_http_redirect_server;
- // fix24-v12: HTTPS/SSL配置
- extern bool g_ssl_enabled;
- extern std::string g_ssl_cert_path;
- extern std::string g_ssl_key_path;
- // ✅ fix24-v16: Web服务端口(从config.ini [server] ip字段解析)
- extern int g_web_server_port;
- // ✅ fix24 功能一:登录认证系统全局对象
- // 必须在 httplib.h 被 include 之前定义 OpenSSL 宏(auth_middleware.h 会触发 httplib.h 包含)
- #ifndef CPPHTTPLIB_OPENSSL_SUPPORT
- #define CPPHTTPLIB_OPENSSL_SUPPORT
- #endif
- #include "auth_db.h"
- #include "auth_session.h"
- #include "auth_rate_limiter.h"
- #include "auth_middleware.h"
- extern auth::AuthDB *g_auth_db;
- extern auth::SessionManager *g_session_mgr;
- extern auth::RateLimiter *g_rate_limiter;
- extern auth::AuthMiddleware *g_auth_middleware;
- extern bool g_auth_enabled; // 是否启用认证(config.ini [auth] enabled)
- extern std::string g_auth_db_path; // 认证数据库路径(config.ini [auth] db_path)
- // ==================== 系统监控配置 (config.ini [system]) ====================
- extern int g_sys_monitor_interval; // 监控采样间隔(秒)
- extern int g_sys_temp_alert_threshold; // 温度告警阈值(°C)
- extern int g_sys_cpu_alert_threshold; // CPU告警阈值(%)
- extern std::string g_sys_db_path; // 系统监控数据库路径
- extern int g_sys_history_retention_days; // 全量数据保留天数
- extern int g_sys_aggregation_retention_days; // 聚合数据保留天数
- extern std::string g_sys_flush_time; // 每日刷盘时间(HH:MM,默认23:20)
- // ==================== frpc 管理配置 (config.ini [frpc]) ====================
- extern std::string g_frpc_config_path; // frpc.toml 路径
- extern std::string g_frpc_backup_path; // 备份路径
- extern std::string g_frpc_protected_tunnels; // 受保护隧道列表
- extern int g_frpc_restart_check_timeout; // 重启后等待检测时间(秒)
- extern bool g_frpc_auto_rollback; // 重启失败自动回滚
- extern bool g_frpc_web_enabled; // Web管理页面开关
- extern std::string g_frpc_admin_addr; // frpc admin API 地址
- extern int g_frpc_admin_port; // frpc admin API 端口
- extern std::string g_frpc_admin_user; // frpc admin 用户名
- extern std::string g_frpc_admin_password; // frpc admin 密码
- // ==================== 终端/SSH 配置 (config.ini [terminal]) ====================
- extern int g_ttyd_port; // ttyd 端口
- extern std::string g_ttyd_credential; // ttyd 凭证 (user:pass)
- extern int g_ttyd_max_clients; // ttyd 最大客户端数
- extern std::string g_ssh_keys_path; // authorized_keys 路径
- // ==================== 日志管理配置 (config.ini [log]) ====================
- extern int g_log_buffer_size_mb; // 日志缓冲区大小(MB)
- extern std::string g_log_flush_time; // 日志写回时间(HH:MM)
- extern std::string g_log_file; // 日志文件路径
- // g_log_retention_days 已在 fix19 中声明(第106行),此处不重复声明
- extern bool g_log_redirect_stdout; // 是否重定向 stdout/stderr
- // ✅ fix24-v36: 内存日志缓冲新增配置
- extern bool g_log_enabled; // 是否启用内存日志模式(1=内存, 0=直写文件)
- extern bool g_log_auto_flush_on_exit; // 程序退出时是否自动刷盘
- // 数据库记录结构
- struct DbRecord {
- int id;
- std::string create_time;
- time_t capture_time = 0; // ✅ fix24-v13: 抓拍时刻Unix时间戳
- std::string plate_number;
- std::string tb_num;
- int station_type;
- std::string lo_photo_path;
- std::string hi_photo_path;
- int lo_upload_status;
- int hi_upload_status;
- int feishu_status;
- int retry_count;
- };
- // 重试结果
- struct RetryResult {
- bool success = false;
- std::string message;
- std::string tb_num;
- int uploaded_photos = 0;
- };
- #endif // COMMON_H
|