#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
系统配置常量
这些值在程序运行期间基本不变，或只在配置时改变
"""
from version import VERSION

# ==================== 应用配置 ====================
APP_VERSION = VERSION
APP_DIR = "/maixapp/apps/t11"
LOCAL_FILENAME = APP_DIR + "/main_tmp.py"

# ==================== 相机配置 ====================
# 相机初始化分辨率（CameraManager / main.py 使用）
CAMERA_WIDTH = 640
CAMERA_HEIGHT = 480

# 三角形检测缩图比例：默认按相机最长边缩到 1/2（性能更稳；可按需调整）
# 取值范围建议 (0.25 ~ 1.0]；1.0 表示不缩图
TRIANGLE_DETECT_SCALE = 0.4

# ==================== 服务器配置 ====================
# SERVER_IP = "stcp.shelingxingqiu.com"
SERVER_IP = "www.shelingxingqiu.com"
SERVER_PORT = 50005
HEARTBEAT_INTERVAL = 5  # 心跳间隔（秒）

# WiFi 质量评估（开机先尝试 WiFi；质量差且 4G 可用则切到 4G，本次上电直至关机锁定 4G）
WIFI_QUALITY_RTT_SAMPLES = 3  # 到业务服务器 TCP 建连耗时采样次数，取中位数
WIFI_QUALITY_RTT_BAD_MS = 600.0  # 中位数超过此值认为延迟过高
WIFI_QUALITY_RTT_WARN_MS = 350.0  # 与 RSSI 联合：超过此值且信号弱也判为差
WIFI_QUALITY_RSSI_BAD_DBM = -80.0  # 低于此 dBm（更负更差）视为信号弱
WIFI_QUALITY_USE_RSSI = True  # 是否把 RSSI 纳入综合判定

# WiFi 热点配网（手机连设备 AP，浏览器提交路由器 SSID/密码；仅 GET/POST，标准库 socket）
WIFI_CONFIG_AP_FALLBACK = False # # WiFi 配网失败时，是否退回热点模式，并等待重新配网
WIFI_AP_FALLBACK_WAIT_SEC = 5 # 等待5秒后再检测STA/4G
WIFI_CONFIG_AP_TIMEOUT = 5  # 热点模式超时时间（秒）
WIFI_CONFIG_AP_ENABLED = False  # True=启动时开热点并起迷你 HTTP 配网服务
WIFI_CONFIG_AP_SSID = "ArcherySetup"       # 设备发出的热点名称
WIFI_CONFIG_AP_PASSWORD = "12345678"       # 热点密码（WPA2 通常至少 8 位）
WIFI_CONFIG_HTTP_HOST = "0.0.0.0"          # HTTP 监听地址
WIFI_CONFIG_HTTP_PORT = 8080               # 默认 8080，避免占用 80 需 root
WIFI_CONFIG_AP_IP = "192.168.66.1"         # 与 MaixPy Wifi.start_ap 默认一致，手机访问 http://192.168.66.1:8080/
                                           # 这个地址需要和 /boot/wifi.ipv4_prefix 配合，才能正确访问。
                                           # 比如说 /boot/wifi.ipv4_prefix 需要写成 192.168.66 
# ===== TCP over SSL(TLS) 配置 =====
USE_TCP_SSL = True          # True=按手册走 MSSLCFG/MIPCFG 绑定 SSL
TCP_LINK_ID = 2             # 
TCP_SSL_PORT = 50006          # TLS 端口（不一定必须 443，以服务器为准）

# SSL profile
SSL_ID = 1                  # ssl_id=1
SSL_AUTH_MODE = 1           # 1=单向认证（验证服务器），2=双向
SSL_VERIFY_MODE = 1         # 0=不验（仅测试用）；1=写入并使用 CA 证书

SSL_CERT_FILENAME = "server.pem"      # 模组里证书名（MSSLCERTWR / MSSLCFG="cert" 用）
SSL_CERT_PATH = APP_DIR + "/server.pem"    # 设备文件系统里 CA 证书路径（你自己放进去）
# MIPOPEN 末尾的参数在不同固件里含义可能不同；按你手册例子保留
MIPOPEN_TAIL = ",,0"

# ==================== 文件路径配置 ====================
CONFIG_FILE = "/root/laser_config.json"
LOG_FILE = APP_DIR + "/app.log"
BACKUP_BASE = APP_DIR + "/backups"

# ==================== 硬件配置 ====================
# UART配置
UART4G_DEVICE = "/dev/ttyS2"
UART4G_BAUDRATE = 115200
DISTANCE_SERIAL_DEVICE = "/dev/ttyS1"
DISTANCE_SERIAL_BAUDRATE = 9600

# I2C：板载 WiFi 方案固定 I2C5，引脚 A15(SCL) / A27(SDA)，供 INA226 等
I2C_BUS_NUM = 5

INA226_ADDR = 0x40
# False=完全不访问 INA226（无电源计量板或未供电时避免 ~2.5s writeto 重试与底层 write failed 日志）；量产有芯片时设为 True
INA226_ENABLE = True
# True=整总线 I2C scan 探测 INA226（在部分平台上极慢，可达 ~90s+）；False=仅对 INA226_ADDR 快速探测（writeto 空写）
INA226_PROBE_FULL_BUS_SCAN = False
REG_CONFIGURATION = 0x00
REG_BUS_VOLTAGE = 0x02
REG_CURRENT = 0x04  # 电流寄存器
REG_CALIBRATION = 0x05
CALIBRATION_VALUE = 0x1400

# ==================== 空气传感器配置 ====================
ADC_TRIGGER_THRESHOLD = 2700 # TODO:4096只是用于测试，因为最大值是4095，这个值是永远不会触发的，最终需要改为正常值
AIR_PRESSURE_lOG = False # TODO: 在正式环境中关闭
AIR_PRESSURE_HARDWARE_MAX = 10
# ADC配置
ADC_CHANNEL = 0
ADC_LASER_THRESHOLD = 3000

# ==================== 激光配置 ====================
MODULE_ADDR = 0x00
LASER_ON_CMD = bytes([0xAA, MODULE_ADDR, 0x01, 0xBE, 0x00, 0x01, 0x00, 0x01, 0xC1])
LASER_OFF_CMD = bytes([0xAA, MODULE_ADDR, 0x01, 0xBE, 0x00, 0x01, 0x00, 0x00, 0xC0])
DISTANCE_QUERY_CMD = bytes([0xAA, MODULE_ADDR, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x21])  # 激光测距查询命令
DISTANCE_RESPONSE_LEN = 13  # 激光测距响应数据长度（字节）
DEFAULT_LASER_POINT =  (320, 245)   # 默认激光中心点

# 硬编码激光点配置
HARDCODE_LASER_POINT = True  # 是否使用硬编码的激光点（True=使用硬编码值，False=使用校准值）
HARDCODE_LASER_POINT_VALUE = (320, 296) # 硬编码的激光点坐标(315, 245) #   # 硬编码的激光点坐标 (x, y)

# 激光点检测配置
LASER_DETECTION_THRESHOLD = 140  # 红色通道阈值（默认120，可调整，范围建议：100-150）
LASER_RED_RATIO = 1.5  # 红色相对于绿色/蓝色的倍数要求（默认1.5，可调整，范围建议：1.3-2.0）
LASER_SEARCH_RADIUS = 50  # 搜索半径（像素），从图像中心开始搜索（默认20，限制激光点不能偏离中心太远）
LASER_MAX_DISTANCE_FROM_CENTER = 50  # 激光点距离中心的最大允许距离（像素），超过此距离则拒绝（默认20）
LASER_OVEREXPOSED_THRESHOLD = 200  # 过曝红色判断阈值（默认200，接近白色时的阈值）
LASER_OVEREXPOSED_DIFF = 10  # 过曝红色时，r 与 g/b 的最小差值（默认10）
LASER_REQUIRE_IN_ELLIPSE = False  # 是否要求激光点必须在黄心椭圆内（True=必须，False=不要求）
LASER_USE_ELLIPSE_FITTING = True  # 是否使用椭圆拟合方法查找激光点（True=椭圆拟合更准确，False=最亮点方法）
LASER_MIN_AREA = 5  # 激光点区域的最小面积（像素），小于此值认为是噪声（默认5）
LASER_DRAW_ELLIPSE = True  # 是否在图像上绘制激光点的拟合椭圆（True=绘制，False=不绘制）

# ==================== 视觉检测配置 ====================
FOCAL_LENGTH_PIX = 2250.0    # 焦距（像素）
REAL_RADIUS_CM = 20          # 靶心实际半径（厘米）

# 图像清晰度检测配置
IMAGE_SHARPNESS_THRESHOLD = 100.0  # 清晰度阈值，低于此值认为图像模糊
                                    # 清晰图像通常 > 200，模糊图像通常 < 100

# 激光与摄像头物理位置配置
LASER_CAMERA_OFFSET_CM = 1.4  # 激光在摄像头下方的物理距离（厘米），正值表示激光在摄像头下方
IMAGE_CENTER_X = 320  # 图像中心 X 坐标
IMAGE_CENTER_Y = 240  # 图像中心 Y 坐标

# ==================== 三角形四角标记：单应性偏移 + PnP 估距 ====================
# 依赖 cameraParameters.xml（相机内参）与 triangle_positions.json（四角物方坐标，厘米或毫米见 JSON 约定）。
# 部署时请把这两个文件放到 APP_DIR（与 main 同应用目录），或改下面路径为设备上的实际绝对路径。
USE_TRIANGLE_OFFSET = False  # False 时仅走黄心圆/椭圆 + 半径估距，不使用三角形路径
CAMERA_CALIB_XML = APP_DIR + "/cameraParameters.xml"
TRIANGLE_POSITIONS_JSON = APP_DIR + "/triangle_positions.json"
# 检测到的三角形边长在图像中的像素范围，分辨率或靶纸占比变化时可微调
TRIANGLE_SIZE_RANGE = (8, 500)
# PnP 距离合理性检查（可选）：超出范围时认为本次检测有误，回退圆心算法
# 设为 0 表示不启用（主要防线是单应矩阵 sx/sy 比值检查，无需提前知道距离）
# 如果射箭距离很固定，可设具体范围（如 min=2.5, max=6.0）作为额外保险
TRIANGLE_DISTANCE_MIN_M = 0.0   # 0=不启用下限检查
TRIANGLE_DISTANCE_MAX_M = 0.0   # 0=不启用上限检查
# 三角形检测兜底增强：CLAHE（更鲁棒但更慢）。颜色阈值修复后通常不需要，保持关闭以优先速度。
TRIANGLE_ENABLE_CLAHE_FALLBACK = False
# 三角形检测调试：保存 Otsu 二值化图像（临时调试用，定位后关闭）
TRIANGLE_SAVE_DEBUG_IMAGE = False
# 三角形颜色过滤阈值（三角形内部灰度判定）
# 如果三角形标记印刷较浅/环境较亮，可放宽：
#   max_interior_gray: 三角形内部平均灰度上限（越大越宽松，90→130 适应浅色印刷）
#   dark_pixel_gray: "暗像素"灰度判定阈值（越大越宽松，80→130）
#   min_dark_ratio: 暗像素占比下限（越小越宽松，0.70→0.30）
TRIANGLE_MAX_INTERIOR_GRAY = 130
TRIANGLE_DARK_PIXEL_GRAY = 130
TRIANGLE_MIN_DARK_RATIO = 0.30
# 三角形相对对比度阈值：内部比周围暗多少灰度值才认为有效（0=禁用相对对比度）
TRIANGLE_MIN_CONTRAST_DIFF = 15
# 三角形形状约束容差（等腰直角判定松紧度）
# 增大可容忍轮廓轻微变形（印刷不均、阴影局部切角），减少"差一点点就失败"的漏检
# 建议范围：0.20（原始/严格） ~ 0.30（宽松）；超过 0.35 容易误检非三角形
TRIANGLE_SHAPE_LEG_TOLERANCE = 0.25    # 两直角边长度比例容差（原 0.20）
TRIANGLE_SHAPE_HYP_TOLERANCE = 0.25    # 斜边与期望长度比例容差（原 0.20）
TRIANGLE_SHAPE_COS_TOLERANCE = 0.25    # 直角余弦绝对值上限（原 0.20，越小越严格）
# 三角形检测主超时（毫秒）：join 等待子线程的最长时间。
# 整段 try_triangle_scoring 含「多路径二值化 + C(n,4) 四角评分 + 单应性 + PnP」，往往比黄心圆检测慢。
# 建议设为实测最坏耗时的 1.2 倍；超时后圆心检测仍会并行跑完，跑完后若三角形已结束则优先用三角形。
TRIANGLE_TIMEOUT_MS = 1000
# True=打印各阶段耗时(ms)，用于定位瓶颈；稳定后可 False 减少日志
TRIANGLE_TIMING_LOG = True
# True=Stage2 每个子框内传统三角失败时打一条统计（Otsu/Adaptive 下轮廓数与各拒绝原因计数）
TRIANGLE_LOG_STAGE2_PATCH_REJECT = True

# 仅检出 3 个真实三角时：是否在预测位置附近做小 ROI（Otsu/adaptive）再搜第 4 个真实三角。
# False=跳过该搜索，直接用几何推算的虚拟第 4 点（offset_method=triangle_homography_3pt），省 ~10~120ms；若实测偏移可接受可关。
TRIANGLE_FOURTH_ROI_SEARCH_ENABLE = False

# ── 轻量锐化（Unsharp Mask）──────────────────────────────────────────────────
# 目的：轻度/中度模糊时增强边缘，让三角形轮廓更易被 approxPolyDP 检出。
# 严重运动模糊时反而会放大噪声，建议搭配 sharpness 检测自动触发（见下）。
# YOLO 裁切后图已较清晰时可 False，省去 Unsharp 开销并减轻振铃。
TRIANGLE_SHARPEN_ENABLE = False     # False=关闭锐化（彻底跳过计算，最省时）
# 仅当帧清晰度（Laplacian 方差）低于此值时才锐化；高于此值说明图片本身够清晰，不动
# 0=总是锐化；建议 50~150；对应日志中 [TRI] sharpness=xxx
TRIANGLE_SHARPEN_THRESHOLD = 0.0  # 0=总是锐化（不做 Laplacian 判断，省去计算）
# Unsharp Mask 高斯核 sigma（越大锐化越强，通常 1.0~3.0）
TRIANGLE_SHARPEN_SIGMA = 2.0
# Unsharp Mask 强度系数（越大锐化越猛，通常 1.2~2.0；>2 易产生振铃）
TRIANGLE_SHARPEN_STRENGTH = 1.5

# 三角形检测用灰度来源（ROI 裁切、缩放到 img_det 之后；与 vision 一致按 RGB 输入）
# rgb — 常规 cv2.cvtColor RGB2GRAY
# v_suppress — HSV 的 V：亮度 >= TRIANGLE_HSV_V_SUPPRESS_ABOVE 的像素灰度强制为 255，压制黄/红/蓝等亮环后再走原有 Otsu 流水线
# fallback_v_suppress — 先用 rgb 跑 detect；若检出三角形 <3，再用 v_suppress 重跑一遍（省平均耗时，坏帧可多救一点）
# try_both — rgb 与 v_suppress 各完整跑一遍 detect_triangle_markers，取检出数更多一侧（平局保留 rgb）；耗时约 2 倍，用于对比效果
TRIANGLE_GRAY_MODE = "v_suppress"
TRIANGLE_HSV_V_SUPPRESS_ABOVE = 200  # 0~255；偏高则环残留多，偏低则可能伤到暗三角边缘，建议 180~220 扫一圈

# 三角形检测性能/鲁棒性参数（偏向速度的默认值）
# 说明：
# - Otsu 是最快的全局阈值；adaptiveThreshold 更鲁棒但更慢
# - filtered 候选过多时，枚举 C(n,4) 会变慢，需限幅
TRIANGLE_EARLY_EXIT_CANDIDATES = 3          # 找到3个候选即停（第4个由几何推算）；原来4需跑完全adaptive
TRIANGLE_ADAPTIVE_BLOCK_SIZES = (11,)       # 只用1个block_size；原(11,21)跑两遍adaptive
TRIANGLE_MAX_FILTERED_FOR_COMBO = 10        # 参与四点组合评分的最大候选数（超过则截断到最可能的一部分）

# ROI 局部阈值：四个象限各自 Otsu（+ 可选 ROI 内 adaptive），再合并候选。
# 顺序：紧接在全局 Otsu 之后、整图 adaptive 之前（见 triangle_target.detect_triangle_markers）。
# 用途：阴阳脸/大阴影下往往比「先整图 adaptive」更省时间且更稳；整图 adaptive 最慢，作补充。
#
# YOLO 已裁到靶区时，整幅小图上单一全局 Otsu 容易把环与四角揉在一个阈值里；可跳过第一轮「全局轮廓提取」，
# 直接进入下面四象限 ROI Otsu（仍会算全局 b_otsu 供 relaxed approxPolyDP 回退）。整图模式勿开。
TRIANGLE_SKIP_GLOBAL_OTSU_EXTRACT_ON_YOLO_ROI = True

TRIANGLE_ROI_ENABLED = False
TRIANGLE_ROI_MIN_CANDIDATES = 3  # 候选数低于此值时启用 ROI 局部阈值（需至少 3 个点才能三角解算）
TRIANGLE_ROI_OVERLAP_RATIO = 0.08  # 象限 ROI 的重叠比例（避免角标落在分割边界被切断）
TRIANGLE_ROI_USE_ADAPTIVE = False  # ROI 内关闭 adaptive（只跑ROI Otsu，省去4×adaptive）；遇到阴阳脸再开

# 多路径融合：不同二值化路径若得到相近中心（dedup 格点），累加 path_votes，后续优先参与四点组合。
TRIANGLE_MULTI_PATH_VOTE = True

# 失败回退（仍不足 TRIANGLE_FALLBACK_MIN_CANDIDATES 时按序尝试，每条仅在前序仍不足时执行）
TRIANGLE_FALLBACK_MIN_CANDIDATES = 3
# 对同一幅 Otsu 二值图用更宽松的 approxPolyDP，找回被“切角”的轮廓
TRIANGLE_FALLBACK_RELAXED_EPS = True
TRIANGLE_RELAXED_POLY_EPS_SCALE = 1.65
# Black-hat（顶帽逆）：突出比周围暗的斑块，再 Otsu；对阴影/照度不均往往有效，略慢于纯 Otsu
TRIANGLE_FALLBACK_BLACKHAT = True
TRIANGLE_BLACKHAT_KERNEL_FRAC = 0.018  # 核大小 ≈ min(h,w)*frac，取奇数，范围约 [7, 31]

# ── YOLO(NPU) 靶环 ROI → 裁剪后再跑三角形（减小 CPU 处理面积）──────────────────
# 日志里 net_in=W×H 来自 .mud 模型（det.input_width/height），不是这里配置的。
TRIANGLE_YOLO_ROI_ENABLE = True
TRIANGLE_YOLO_MODEL_PATH = APP_DIR + "/model_270139.mud"
# 参与 ROI 的类别：多类时只填「整靶/靶环」的 id；不要填角标类，否则 union 仍可对，但 largest 会偏小。
TRIANGLE_YOLO_RING_CLASS_IDS = (0,)
TRIANGLE_YOLO_CONF_TH = 0.7
TRIANGLE_YOLO_IOU_TH = 0.45
# YOLO 首次/临界帧可能在高阈值下 0 框；启用后仅在 0 候选时用较低阈值重试一次。
# 后续仍会经过 min_box_side、ROI aspect、三角形几何校验，避免直接放大假阳性。
TRIANGLE_YOLO_RETRY_ON_EMPTY = True
TRIANGLE_YOLO_RETRY_CONF_TH = 0.5
TRIANGLE_YOLO_ROI_MARGIN_FRAC = 0.11
# union: 所有候选框外接矩形（一类多框：环+四角）；largest: 只取面积最大的框
TRIANGLE_YOLO_ROI_MERGE_MODE = "union"
# native: Maix 已将框映射到相机分辨率；letterbox: 框在网络输入坐标需逆变换（重复映射会出细条 ROI）
TRIANGLE_YOLO_COORD_MODE = "native"
# 参与 ROI 合并前丢弃过小的框（低 conf 时边角 1×1 假阳性）
TRIANGLE_YOLO_MIN_BOX_SIDE_PX = 8
TRIANGLE_YOLO_REJECT_BAD_ROI = True
# try_triangle_scoring 收到 ROI 后裁剪的最小边长（像素），过小则退回整图
TRIANGLE_CROP_ROI_MIN_SIDE_PX = 64
# 射箭保存图 / 预览上绘制 YOLO 靶环 ROI 矩形 (x0,y0,x1,y1)，核对是否裁准；不需要时改 False
TRIANGLE_YOLO_DRAW_ROI_ON_SHOT = True
# 物方采样调试：以靶心为中心，取半径 15cm 的圆周样本点，用于黑/白颜色对比
TRIANGLE_SAMPLE_RADIUS_CM = 15.0
TRIANGLE_SAMPLE_ANGLES_DEG = (0, 90, 180, 270)
TRIANGLE_SAMPLE_PATCH_HALF_PX = 2
# 开机阶段预加载 YOLO detector；detect 使用 dual_buff=False，避免返回上一帧结果。
TRIANGLE_YOLO_PRELOAD_ON_BOOT = False

# ── 第二段 YOLO：仅在 Stage1 裁切出的靶环图上推理（与合成 stage2 训练数据一致）→ 子框内传统算法取直角点 ──
# Stage1 靶环裁切内如何找黑三角标记（对比耗时时可切换）：
# "yolo" — 调 Stage2 黑三角模型得子框，再子框内传统提取（需 TRIANGLE_BLACK_YOLO_ENABLE=True）。
# "traditional" — 不调 Stage2 模型；仅在 Stage1 ROI 整幅上跑传统 detect_triangle_markers（与 yolo 路径对比用）。
TRIANGLE_BLACK_TRIANGLE_LOCATE_MODE = "traditional"
# True 时每箭另打一枪端到端耗时：yolo_ring + yolo_black + try_triangle_scoring 墙钟（毫秒）
TRIANGLE_LOG_E2E_TIMING = True
TRIANGLE_BLACK_YOLO_ENABLE = True
TRIANGLE_BLACK_YOLO_MODEL_PATH = APP_DIR + "/model_270820.mud"
TRIANGLE_BLACK_YOLO_CLASS_IDS = (0,)
TRIANGLE_BLACK_YOLO_CONF_TH = 0.5
TRIANGLE_BLACK_YOLO_IOU_TH = 0.45
# Maix YOLOv5 detect 返回的框已映射到传入的 Stage1 裁切图坐标；contain/letterbox 是模型内部预处理。
TRIANGLE_BLACK_YOLO_COORD_MODE = "native"
# 子框相对 YOLO 框的扩展（在靶环裁切图坐标系下），利于传统算法取边
TRIANGLE_BLACK_YOLO_BOX_MARGIN_FRAC = 0.08
TRIANGLE_BLACK_YOLO_MIN_BOX_SIDE_PX = 6.0
# 子框传统检测不足 3 个时是否回退为「整幅靶环 ROI」上的原 detect_triangle_markers
TRIANGLE_BLACK_YOLO_FALLBACK_ON_PATCH_FAIL = True
# Stage2 子框内传统提取使用的灰度（有缩略时默认在 Stage1 全分辨率灰度上切片）：
# "rgb" — 仅用 RGB→灰度（不再做 Unsharp、不做 V 抑制），最省 CPU（推荐子框已对准黑三角时）。
# "global" — 与整幅 ROI 三角流程同一张 gray（含 TRIANGLE_GRAY_MODE 的 v_suppress 与锐化）；更稳但更耗时。
TRIANGLE_BLACK_YOLO_PATCH_GRAY_SOURCE = "rgb"
# Stage2 子框内轮廓→三角形：approxPolyDP 的 ε=周长×FRAC×mult。边模糊时略增大 FRAC 或保留多级 mult。
TRIANGLE_PATCH_APPROXPOLY_FRAC = 0.055
TRIANGLE_PATCH_APPROXPOLY_RELAX_MULTS = (1.0, 1.3, 1.65)
# Otsu/Adaptive 前对子框灰度轻模糊：0=关闭；3 或 5=Gaussian ksize（须为奇数），压锯齿利于收成 3 顶点
TRIANGLE_PATCH_PRE_BLUR_KSIZE = 0
TRIANGLE_BLACK_YOLO_PRELOAD_ON_BOOT = True
# 每箭是否在日志中打印黑三角 detect 统计（raw/类过滤/是否在环内）；调通后可 False 减日志
TRIANGLE_BLACK_YOLO_LOG_EACH_SHOT = True
# True=每次射箭将 Stage1 裁切图（黑三角模型输入）存为 JPEG；调试用，量产请 False
TRIANGLE_BLACK_YOLO_SAVE_ROI_CROP = True
# 存盘目录；空字符串表示使用 PHOTO_DIR + "/stage2_roi"
TRIANGLE_BLACK_YOLO_ROI_CROP_DIR = ""
# 存盘 JPEG 上绘制 Stage2（黑三角 YOLO）最终子框（绿框 + s2_0… 标签）
TRIANGLE_BLACK_YOLO_SAVE_ROI_DRAW_BOXES = True

FLASH_LASER_WHILE_SHOOTING = False  # 是否在拍摄时闪一下激光（True=闪，False=不闪）
FLASH_LASER_DURATION_MS = 1000  # 闪一下激光的持续时间（毫秒）

# ==================== 显示配置 ====================
LASER_COLOR = (0, 255, 0)  # RGB颜色
LASER_THICKNESS = 1
LASER_LENGTH = 2

# ==================== 队列大小限制（防止内存泄漏） ====================
MAX_SEND_QUEUE_SIZE = 500       # 发送队列上限
MAX_TCP_PAYLOADS = 500          # AT TCP 载荷缓存上限
MAX_HTTP_EVENTS = 200           # AT HTTP 事件缓存上限
LOG_QUEUE_MAXSIZE = 10000       # 日志队列上限
MAX_CMD_THREADS = 10            # 并发命令线程上限（防止服务器下发命令时无限创建线程）

# ==================== 图像保存配置 ====================
SAVE_IMAGE_ENABLED = False  # 是否保存图像（True=保存，False=不保存）
SAVE_IMAGE_ON_FAILURE = True  # 检测失败时是否强制保存图像（供调试测试用）
PHOTO_DIR = "/root/phot"    # 照片存储目录
MAX_IMAGES = 1000
# Stage2 调试目录（默认 PHOTO_DIR/stage2_roi）内 JPEG 最多保留张数；None 表示与 MAX_IMAGES 相同
TRIANGLE_BLACK_YOLO_STAGE2_ROI_MAX_IMAGES = None

SHOW_CAMERA_PHOTO_WHILE_SHOOTING = False  # 是否在拍摄时显示摄像头图像（True=显示，False=不显示），建议在连着USB测试过程中打开

# ==================== OTA配置 ====================
MAX_BACKUPS = 5
LOG_MAX_BYTES = 10 * 1024 * 1024  # 10MB
LOG_BACKUP_COUNT = 5

# ==================== 引脚映射配置（板载 WiFi，I2C5）====================
PIN_MAPPINGS = {
    "A18": "UART1_RX",
    "A19": "UART1_TX",
    "A29": "UART2_RX",
    "A28": "UART2_TX",
    "A15": "I2C5_SCL",
    "A27": "I2C5_SDA",
    "A24": "GPIOA24",  # 电源板关机控制
}

# ==================== 电源配置 ====================
AUTO_POWER_OFF_IN_SECONDS = 10 * 60  # 自动关机时间（秒），0表示不自动关机

BATTERY_SOC_LPF_ALPHA = 0.5
BATTERY_SOC_AVG_WINDOW = 5

