Commit Graph

162 Commits

Author SHA1 Message Date
95c58e8b3f 添加 mysql-connector-python 依赖(IoT数据库连接需要) 2026-03-31 15:28:05 +08:00
fa1a0b96c0 修复:IoT数据库连接支持mysql-connector-python驱动
腾讯云MySQL需要use_pure+ssl_disabled参数才能认证通过,
当URL使用mysqlconnector驱动时自动添加connect_args
2026-03-31 15:15:32 +08:00
cd1ccd6912 清理旧Agent工具文件
删除已被 order_query.py / order_action.py 替代的旧文件:
- alarm_query.py
- alarm_action.py
- order_tools.py
2026-03-31 10:51:34 +08:00
63a8d5a8f2 告警-工单解耦:企微交互+Agent全面切换到工单驱动
Part A: 数据层
- 新增 WechatCardState 模型(order_id ↔ alarm_id 映射 + response_code)
- 新建 models_iot.py(IoT 工单只读 ORM:ops_order + security_ext + clean_ext)
- config.py 新增 IOT_DATABASE_URL 配置

Part B: 企微解耦(alarm_id → order_id)
- wechat_service: response_code 存储迁移到 wechat_card_state,集中 helper
- 卡片发送/更新方法改用 order_id,按钮 key: confirm_{order_id}
- wechat_callback: 按钮解析改 order_id,反查 alarm_id(可空)
- wechat_notify_api: send-card/sync-status 以 orderId 为主键
- yudao_aiot_alarm: 卡片操作改用 order_id,删重复 helper

Part C: Agent 工具全面改为工单驱动
- 新建 order_query.py(查 IoT ops_order,支持安保+保洁工单)
- 新建 order_action.py(操作工单状态 + 提交处理结果)
- 更新 prompts.py 为工单助手
- 更新工具注册(__init__.py)

Part D: 日报改为工单驱动
- daily_report_service 从查 alarm_event 改为查 IoT ops_order + 扩展表
- 支持安保+保洁工单统计
2026-03-31 10:49:42 +08:00
93148fe85b 增强:工单创建增加重试机制(最多2次重试)
IoT ops 服务偶发 500 异常(auto_complete 后状态污染),
添加 3s/6s 间隔重试,避免暂时性故障导致工单丢失。
2026-03-31 09:37:33 +08:00
9513951b1b 修复:企微群聊不发送告警截图
根因:_get_presigned_url 对完整 COS 永久 URL 直接原样返回,
未重新生成预签名 URL,导致私有桶的图片下载失败(403)。

修复:
1. _get_presigned_url 增加 COS URL 识别,提取 object key 重新签名
2. 新增 _extract_cos_object_key 解析两种 COS URL 格式
3. send-card 增加截图诊断日志(追踪 IoT/DB 来源和最终 URL)
4. upload_media_from_url 增加下载/上传诊断日志
2026-03-30 14:30:01 +08:00
342fbd87b5 修复:告警列表状态筛选映射错误 — handled应映射CLOSED,新增processing映射CONFIRMED 2026-03-30 11:31:14 +08:00
afa463ac65 修复:send-card 群聊通知三个问题
1. 告警告警重复:用 alarm_type_code 映射而非 IoT 的 title
2. 摄像头未知:从告警表查 device_id 获取摄像头名称
3. 截图403:从告警表取 object key 生成预签名 URL(IoT 传的永久URL无签名)
2026-03-30 11:17:21 +08:00
961a387957 修复:resolve_alarm 添加 vehicle_left 和 congestion_cleared 状态处理
违停车辆离开和拥堵消散的 resolve 事件没有匹配到对应的状态分支,
导致告警只更新了 duration_ms 但 alarm_status 没改为 CLOSED。
2026-03-27 15:20:01 +08:00
3a62202406 修复:恢复 send-card 接口,dispatched 只记录日志不发企微 2026-03-27 14:11:03 +08:00
058fc0dbaf 优化:edge resolve 只调 IoT 自动结单,去掉降级卡片更新 2026-03-27 13:16:21 +08:00
e6fd316036 重构 sync-status 接口:按状态分流处理,删除 send-card 接口
- dispatched: 发企微群聊+私发卡片(不更新告警)
- confirmed: 仅更新卡片到第二步(不更新告警)
- 终态(completed/false_alarm/auto_resolved): 更新告警+卡片
- 删除 send-card 接口和 SendCardRequest 类(企微由 dispatched 触发)
2026-03-27 13:12:29 +08:00
e8e075efd6 重构通知调度:去掉企微直发,工单创建后改告警为 CONFIRMED
- 删除企微群聊组合消息和降级卡片发送逻辑
- 删除 get_wechat_service、event_time_str 格式化等相关代码
- 工单创建成功后调用 _set_alarm_confirmed 将告警改为 CONFIRMED/HANDLING
- 新增 _set_alarm_confirmed 辅助函数
- 企微通知改由 IoT 工单回调驱动
2026-03-27 12:53:40 +08:00
f96d692dd9 修复:EdgeAlarmReport 添加 area_id 字段,告警创建时优先从顶层取 area_id 2026-03-27 11:09:47 +08:00
e7c9ee126f 移除调试代码,清理 send-card/wechat_service 调试日志和端点 2026-03-26 13:39:20 +08:00
0bde8c03a4 修复企微服务热重载后丢失初始化的问题
get_wechat_service() 增加 _initialized 检查,
未初始化时自动调用 init(settings.wechat),
避免 uvicorn 热重载后单例重建但未 init 导致 enabled=False。
2026-03-26 13:24:58 +08:00
9370c2f2ec 修复日报定时任务 MySQL 连接断开问题(BrokenPipe)
添加 pool_recycle=1800 和 pool_pre_ping=True,
防止 MySQL 长时间空闲后连接被服务端关闭导致 BrokenPipeError。
2026-03-26 09:08:06 +08:00
e874a35c12 调试:添加 IoT 回调请求详细日志,排查 body 为空问题 2026-03-25 17:11:25 +08:00
6fcd8f68bf 修复 IoT 回调 send-card/sync-status 返回 422 的问题
IoT Java 客户端发送的请求体格式不被 FastAPI Pydantic 自动解析,
改为手动解析 request body,兼容 JSON/form/query params 三种格式。
同时添加 dispatched 状态映射,记录请求日志便于调试。
2026-03-25 17:04:30 +08:00
3a9595de7c 切换到 IoT 工单驱动模式:所有状态变更由 IoT 回调驱动
1. notify_dispatch: 工单优先于卡片发送,创建成功则跳过直发卡片(等IoT回调send-card)
2. wechat_callback: IoT API 成功后直接返回,等 sync-status 回调更新告警+卡片
3. edge_compat: 启用工单自动结单,成功后等 sync-status 回调
4. yudao_aiot_alarm: 前端操作优先调 IoT 工单 API,降级直接更新卡片
5. wechat_notify_api: 修复 confirmed 的 card_action 为 None 导致卡片不更新的 bug

所有路径均保留降级逻辑:IoT 失败或工单未启用时直接处理告警+更新卡片
2026-03-25 15:38:52 +08:00
5a64e2fe11 功能:前端处理/误报后同步更新企微卡片到终态
handle_alarm 执行后,若为终态操作(CLOSED/FALSE),
异步调用 update_alarm_card_terminal 同步企微卡片按钮状态,
避免前端已处理但企微卡片按钮仍可点击的不一致问题。
2026-03-25 15:19:43 +08:00
adf8d63da6 回滚:移除告警处理图片字段,告警只记录状态
告警只需记录处理状态(已处理/误报),图片等信息在工单体系中管理。
移除 handle_image_url 字段、自动迁移和相关参数。
2026-03-25 15:10:40 +08:00
d623f6b340 修复:告警状态流转统一 — 前端处理直接结单(CLOSED),支持处理图片上传
1. handle接口状态映射:handled→CLOSED(而非CONFIRMED),ignored→FALSE
2. handle_status同步设置:handled→DONE,ignored→IGNORED
3. 新增handle_image_url字段支持处理图片存储
4. 自动迁移:启动时自动ALTER TABLE添加新列
2026-03-25 15:01:35 +08:00
369b70a1fa 放宽 openai 版本约束,兼容 langgraph 依赖 2026-03-25 14:36:18 +08:00
6848eaeabf 修复告警状态映射:CONFIRMED 应为 processing 而非 handled
CONFIRMED 表示"已确认接单/处理中",之前错误映射为 handled(已处理),
导致前端显示"已处理"但 Agent 仍能查到该工单为待处理。
2026-03-25 14:34:26 +08:00
5557ad053b 优化提示词:强制数据来源于工具,禁止编造
- 明确"所有数据必须来自工具调用结果"
- 不知道的直接说不知道,不要猜测
- 图片分析不清晰时不猜测
- 限定只回答安防相关问题
2026-03-25 14:21:54 +08:00
6087066a91 调低 temperature=0.1,减少大模型胡编乱造
涉及三处 LLM 调用:
- LangGraph Agent 对话(graph.py)
- VLM 图片分析(agent_dispatcher.py)
- VLM 告警复核(vlm_service.py)
2026-03-25 14:20:19 +08:00
836ced9270 移除 Legacy FC 模式,只保留 LangGraph
删除 USE_LANGGRAPH 开关、_legacy_chat、_legacy_execute_tool、
_get_legacy_tools 等全部旧代码,agent_dispatcher 精简为纯
LangGraph 入口适配层。
2026-03-25 13:56:24 +08:00
8156f54004 重构 Agent:引入 LangGraph StateGraph 替代手写 FC 循环
架构变更:
- 新增 app/services/agent/ 模块(state/prompts/graph/tools)
- 7 个工具从 _tool_xxx 方法提取为 @tool 装饰器函数
- 构建 assistant + ToolNode 的 ReAct 图
- agent_dispatcher.py 改为薄壳入口,支持 USE_LANGGRAPH 开关
- MemorySaver checkpoint 持久化对话(thread_id=wechat-{user_id})
- 新增依赖:langchain-core, langchain-openai, langgraph

向后兼容:
- USE_LANGGRAPH=false 可切回旧版 FC 循环
- LangGraph 初始化失败自动降级到 Legacy 模式
- 企微图片处理/VLM分析逻辑不变
2026-03-25 13:52:55 +08:00
d1aa14bb23 修复 submit_order_result 缺少告警存在性检查
LLM 传错 alarm_id 时 handle_alarm 静默返回 None,
但函数仍返回 success:true 误导用户。添加前置检查。
2026-03-25 12:41:47 +08:00
eb2d74bd4c 修复 Agent 对接 IoT 工单平台:状态同步、图片持久化、roiId 字段
1. agent_dispatcher: IoT 成功与否都更新本地告警状态,不再依赖回调同步
2. agent_dispatcher: submit_order_result 持久化图片 URL 到 alarm_event_ext
3. work_order_client: create_order 添加 roi_id/source_type 参数
4. notify_dispatch: 创建工单时传 scene_id 作为 roiId
2026-03-25 12:37:00 +08:00
7d4c916055 修复:IoT回调接口422错误,字段改为Optional兼容null值 2026-03-25 10:56:12 +08:00
5a7b098663 优化:日报增加按边缘节点分组汇总(各节点告警数、类型分布、Top设备) 2026-03-25 10:07:55 +08:00
50f016e9fb 功能:添加日报手动触发接口 POST /api/wechat/notify/daily-report 2026-03-25 09:21:36 +08:00
b13d86f0a6 文档:全面重写 README.md,反映当前项目架构
- 更新架构图:HTTP 上报替代 MQTT,新增 VLM/企微/工单/日报模块
- 补充完整 API 接口清单(边缘上报、告警管理、企微、工单等)
- 详述告警三表数据模型 + 工单/通知配置表
- 完善项目结构树(17 个 service + 11 个 router)
- 列出全部环境变量分组说明
- 描述告警处理全链路和企微交互流程
- 添加系统集成关系矩阵
2026-03-25 09:12:04 +08:00
2a36bd4ffc 功能:每日告警日报定时推送到企微群聊
- 新增 DailyReportConfig 配置(DAILY_REPORT_ENABLED/HOUR/MINUTE)
- 新增 daily_report_service:asyncio 定时调度,每日生成前一天告警汇总
- 日报内容:告警总数、环比变化、处理状态分布、类型分布、设备 Top5、平均响应时长
- lifespan 中启动/停止定时任务
2026-03-24 17:43:52 +08:00
5972d97ff9 修复:企微私聊卡片发送失败(card_action缺少url)
FC升级时删除了card_action中的url字段,但type=1要求必须提供url,
导致企微API拒绝发送个人卡片。恢复url兜底值。
2026-03-24 16:43:04 +08:00
0f27caf0b5 修复:摄像头名称显示全链路修复
- config.py: 简化 CameraNameConfig,删除 display_format/name_field_priority
- camera_name_service.py: 重写名称解析,固定优先级 cameraName→gbName→device_id,
  删除废弃的 app/stream 格式解析和 extract_name 方法
- yudao_aiot_alarm.py: 删除 stream→cameraId 的错误映射,cameraId 直接用 device_id
- agent_dispatcher.py: query_camera 删除技术字段返回,list_my_orders 添加摄像头名称解析
2026-03-24 13:38:45 +08:00
fbdd340a8e 修复:Agent禁用markdown语法 + 告警详情自动发送截图图片
- 系统提示词禁止markdown图片语法,企微不支持渲染
- 告警详情查询时截图自动通过企微图片消息发送
- 工具返回中用has_snapshot替代snapshot_url,避免模型输出链接
2026-03-24 11:50:54 +08:00
b51c5cc46d 修复:摄像头名称匹配改为cam前缀统一识别 + 响应时间排除>6h异常值
- camera_name_service: device_id前缀匹配从cam_/CAM改为cam(不区分大小写),修复cam2026格式设备无法查询名称的问题
- alarm_event_service: 平均响应时间排除超过6小时的异常值
2026-03-24 11:24:24 +08:00
7c7b7455f6 优化:平均响应时间只统计近7天且排除>6h异常值
避免历史旧数据和长时间未处理告警拉高平均响应时间
2026-03-24 11:17:23 +08:00
731a6d631c 重构:Agent升级为Qwen3.5-Plus Function Calling架构
- config: AgentConfig新增model(qwen3.5-plus)和timeout(30s)字段
- agent_dispatcher: 完全重写,替换意图标记为原生FC,实现7个工具
  (query_alarm_stats/list_alarms/get_alarm_detail/update_alarm_status/
   list_my_orders/submit_order_result/query_camera)
- session_manager: 移除waiting_location/waiting_confirm状态,新增pending_images
- wechat_service: 禁用H5跳转,card_action移除URL,step2提示改为对话框操作
- wechat_callback: 图片消息智能路由(有待处理工单→暂存,无→VLM分析)
2026-03-24 11:17:12 +08:00
12860a0c83 修复:camera_name 为 default 时降级到 gbName
梦中心摄像头的 camera_name 列值为 "default"(无效值),
导致前端告警列表显示 CAM 编码而不是中文名。
现在将 "default" 视为无效值,降级使用 gbName。
2026-03-24 09:37:32 +08:00
b97517c680 撤销:移除区域查询相关功能,测试阶段手动写死 area_id
移除 area_api.py、IotDbConfig、WVP 降级查询,
保留 Edge Token 认证功能。区域绑定等 WVP 迁移到 IoT 后再做。
2026-03-23 17:04:16 +08:00
5b83e38f25 重构:区域列表改为直接查 IoT 数据库
去掉 httpx 调 IoT HTTP 接口的方式,改为通过 IOT_DATABASE_URL
直接查询 IoT MySQL 的 ops_area 表,更简单可靠。
2026-03-23 16:53:45 +08:00
7235a20e25 功能:区域绑定工单链路 + Edge API 认证
1. Edge Token 认证:edge_compat.py 新增 _verify_edge_token 依赖,
   通过 EDGE_AUTH_TOKEN 环境变量配置共享 Token,保护告警上报接口
2. 区域列表 API:新增 /api/area/list 代理查询 IoT 平台区域数据,
   供前端摄像头页面选择区域使用(带 5 分钟缓存)
3. 降级查询:notify_dispatch.py 中 area_id 为空时从 WVP API 查询兜底
4. 配置新增:EdgeAuthConfig(token + enabled)、IotDbConfig
2026-03-23 16:50:07 +08:00
6bc71a9991 修复:Agent意图识别优先于位置状态机,防止查询被误判为位置
- 新增 _looks_like_new_intent() 方法,识别查询/取消等明确非位置意图
- 收紧 _looks_like_location() 规则,去掉2-30字的宽松兜底,必须包含位置关键词
- waiting_location 状态下先判断新意图,再判断位置,最后兜底退出状态机
- 修复「今天有多少告警」被当成位置信息创建工单的问题
2026-03-23 15:01:48 +08:00
eabff3b920 功能:H5 工单页企微 OAuth2 认证接口(code 换 userid) 2026-03-23 12:59:47 +08:00
be059b47b0 功能:H5 工单处理 API(detail/submit/upload-image)
- GET /api/work-order/detail — 告警+工单详情
- POST /api/work-order/submit — 提交处理结果,调 IoT /submit
- POST /api/work-order/upload-image — 上传照片到 COS
- IoT 失败时降级直接更新告警状态
2026-03-23 12:00:04 +08:00
d9ad321f24 功能:卡片 URL 改为 H5 工单页,step2 提示"请点击卡片提交处理结果" 2026-03-23 11:56:35 +08:00