Add WebSocket, multi API key, geocoding proxy, beacon map picker, and comprehensive bug fixes
- Multi API Key + permission system (read/write/admin) with SHA-256 hash - WebSocket real-time push (location, alarm, device_status, attendance, bluetooth) - Geocoding proxy endpoints for Amap POI search and reverse geocode - Beacon modal map-based location picker with search and click-to-select - GCJ-02 ↔ WGS-84 bidirectional coordinate conversion - Data cleanup scheduler (configurable retention days) - Fix GPS longitude sign inversion (course_status bit 11: 0=East, 1=West) - Fix 2G CellID 2→3 bytes across all protocols (0x28, 0x2C, parser.py) - Fix parser loop guards, alarm_source field length, CommandLog.sent_at - Fix geocoding IMEI parameterization, require_admin import - Improve API error messages for 422 validation errors - Remove beacon floor/area fields (consolidated into name) via [HAPI](https://hapi.run) Co-Authored-By: HAPI <noreply@hapi.run>
This commit is contained in:
220
CLAUDE.md
220
CLAUDE.md
@@ -20,12 +20,13 @@ KKS P240/P241 蓝牙工牌管理后台,基于 FastAPI + SQLAlchemy + asyncio T
|
||||
│ ├── main.py # FastAPI 应用入口, 挂载静态文件, 启动TCP服务器
|
||||
│ ├── config.py # 配置 (pydantic-settings, .env支持, 端口/API密钥/缓存/限流)
|
||||
│ ├── database.py # SQLAlchemy async 数据库连接
|
||||
│ ├── dependencies.py # FastAPI 依赖 (API Key 认证)
|
||||
│ ├── dependencies.py # FastAPI 依赖 (多API Key认证 + 权限控制: read/write/admin)
|
||||
│ ├── extensions.py # 共享实例 (rate limiter, 真实IP提取)
|
||||
│ ├── models.py # ORM 模型 (Device, LocationRecord, AlarmRecord, HeartbeatRecord, AttendanceRecord, BluetoothRecord, BeaconConfig, CommandLog)
|
||||
│ ├── websocket_manager.py # WebSocket 连接管理器 (topic订阅, 实时广播)
|
||||
│ ├── models.py # ORM 模型 (Device, LocationRecord, AlarmRecord, HeartbeatRecord, AttendanceRecord, BluetoothRecord, BeaconConfig, CommandLog, ApiKey)
|
||||
│ ├── schemas.py # Pydantic 请求/响应模型
|
||||
│ ├── tcp_server.py # TCP 服务器核心 (~2400行), 管理设备连接、协议处理、数据持久化
|
||||
│ ├── geocoding.py # 地理编码服务 (基站/WiFi → 经纬度) + 逆地理编码 (经纬度 → 地址)
|
||||
│ ├── geocoding.py # 高德地理编码服务 (基站/WiFi → 经纬度 + 经纬度 → 地址)
|
||||
│ │
|
||||
│ ├── protocol/
|
||||
│ │ ├── constants.py # 协议常量 (协议号、告警类型snake_case、信号等级等)
|
||||
@@ -41,14 +42,16 @@ KKS P240/P241 蓝牙工牌管理后台,基于 FastAPI + SQLAlchemy + asyncio T
|
||||
│ │ └── tcp_command_service.py # TCP指令抽象层 (解耦routers↔tcp_server)
|
||||
│ │
|
||||
│ ├── routers/
|
||||
│ │ ├── devices.py # /api/devices (含 /stats, /batch, /batch-delete)
|
||||
│ │ ├── devices.py # /api/devices (含 /stats, /batch, /batch-delete, /all-latest-locations)
|
||||
│ │ ├── commands.py # /api/commands (含 /send, /message, /tts, /batch)
|
||||
│ │ ├── locations.py # /api/locations (含 /latest, /track, /{id})
|
||||
│ │ ├── alarms.py # /api/alarms (含 acknowledge)
|
||||
│ │ ├── locations.py # /api/locations (含 /latest, /batch-latest, /track, /{id})
|
||||
│ │ ├── alarms.py # /api/alarms (含 acknowledge, alarm_source过滤)
|
||||
│ │ ├── attendance.py # /api/attendance (含 /stats, /{id})
|
||||
│ │ ├── bluetooth.py # /api/bluetooth (含 /{id})
|
||||
│ │ ├── bluetooth.py # /api/bluetooth (含 beacon_mac过滤, /{id})
|
||||
│ │ ├── heartbeats.py # /api/heartbeats (心跳记录查询)
|
||||
│ │ └── beacons.py # /api/beacons (信标管理 CRUD)
|
||||
│ │ ├── beacons.py # /api/beacons (信标管理 CRUD)
|
||||
│ │ ├── api_keys.py # /api/keys (API密钥管理 CRUD, admin only)
|
||||
│ │ └── ws.py # /ws (WebSocket实时推送, topic订阅)
|
||||
│ │
|
||||
│ └── static/
|
||||
│ └── admin.html # 管理后台 SPA (暗色主题, 8个页面)
|
||||
@@ -84,7 +87,7 @@ KKS P240/P241 蓝牙工牌管理后台,基于 FastAPI + SQLAlchemy + asyncio T
|
||||
- `app/config.py` 使用 **pydantic-settings** (`BaseSettings`),支持 `.env` 文件覆盖默认值
|
||||
- `.env.example` 提供所有可配置项模板,复制为 `.env` 使用
|
||||
- DATABASE_URL 使用绝对路径 (基于 `__file__` 计算项目根目录)
|
||||
- 所有 API 密钥 (天地图/Google/Unwired/高德) 集中在 `config.py`,`geocoding.py` 从 `settings` 导入
|
||||
- 高德 API 密钥集中在 `config.py`,`geocoding.py` 从 `settings` 导入
|
||||
- 端口号有 pydantic 校验 (ge=1, le=65535)
|
||||
|
||||
## 启动服务
|
||||
@@ -186,34 +189,47 @@ KKS 二进制协议,详见 `doc/KKS_Protocol_P240_P241.md`
|
||||
- GPS 定位 (0x22/0xA0): 直接包含经纬度坐标,精度最高 (~10m)
|
||||
- LBS 基站定位 (0x28/0xA1): 包含 MCC/MNC/LAC/CellID,需要地理编码转换为经纬度
|
||||
- WiFi 定位 (0x2C/0xA2): 包含基站数据 + WiFi AP MAC地址列表,需要地理编码
|
||||
- **所有地理编码服务统一使用高德 (Amap)**
|
||||
- **前向地理编码** (`geocode_location`): 基站/WiFi → 经纬度
|
||||
- **高德智能硬件定位 (待接入)**: `apilocate.amap.com/position`,需企业认证,WiFi+基站混合定位精度 ~30m
|
||||
- **Mylnikov.org (当前使用)**: 免费无需Key,中国基站精度较差 (~16km)
|
||||
- Google Geolocation API / Unwired Labs API (备选,需配置Key)
|
||||
- **高德智能硬件定位**: `apilocate.amap.com/position`,需企业认证 (认证中,个人账号返回 10012)
|
||||
- WiFi+基站混合定位精度 ~30m,企业认证通过后自动生效
|
||||
- **逆地理编码** (`reverse_geocode`): 经纬度 → 中文地址
|
||||
- **天地图 (已接入)**: 免费1万次/天,WGS84原生坐标系,无需坐标转换
|
||||
- **高德**: `restapi.amap.com/v3/geocode/regeo`,需 WGS84→GCJ02 坐标转换 (服务端 Python 实现)
|
||||
- 缓存策略: 坐标四舍五入到3位小数 (~100m) 作为缓存key
|
||||
- 地址格式: `省市区街道路门牌号 (附近POI)`
|
||||
- 内置缓存机制,避免重复请求相同基站/坐标
|
||||
|
||||
### 天地图 API
|
||||
- **服务端 Key**: `439fca3920a6f31584014424f89c3ecc` (用于逆地理编码)
|
||||
- **浏览器端 Key**: `1918548e81a5ae3ff0cb985537341146` (用于前端地图瓦片,暂未使用)
|
||||
- **API地址**: `http://api.tianditu.gov.cn/geocoder?postStr={JSON}&type=geocode&tk={KEY}`
|
||||
- **坐标系**: WGS84 (与GPS/Leaflet一致,无需转换)
|
||||
- **配额**: 免费 10,000 次/天
|
||||
- **注意**: postStr 参数需使用双引号JSON并URL编码
|
||||
- 内置 LRU 缓存 (maxsize=10000),避免重复请求相同基站/坐标
|
||||
- **WGS84→GCJ02 服务端转换**: geocoding.py 内置 `wgs84_to_gcj02()` 函数 (与前端 JS 版一致)
|
||||
- **高德数字签名**: 参数按key排序拼接 + AMAP_SECRET → MD5 → sig 参数
|
||||
|
||||
### API 认证与限流
|
||||
- **认证**: 设置 `API_KEY` 环境变量后,所有 `/api/` 请求需携带 `X-API-Key` 请求头
|
||||
- **多 API Key**: 支持 master key (环境变量) + 数据库管理的 API Key (SHA-256 hash)
|
||||
- **权限级别**: `read` (只读) < `write` (读写) < `admin` (管理,含 key 管理)
|
||||
- **权限控制**: 所有 POST/PUT/DELETE 端点需要 `write` 权限,`/api/keys` 需要 `admin` 权限
|
||||
- **Key 管理**: `POST /api/keys` 创建 key (返回明文一次), `GET /api/keys` 列表, `PUT /api/keys/{id}` 更新, `DELETE /api/keys/{id}` 停用
|
||||
- **限流**: 全局 60/min (default_limits),写操作 30/min (`@limiter.limit`)
|
||||
- **真实 IP**: 从 `X-Forwarded-For` → `CF-Connecting-IP` → `request.client.host` 提取
|
||||
- **CORS**: `CORS_ORIGINS=*` 时自动禁用 `allow_credentials`
|
||||
|
||||
### WebSocket 实时推送
|
||||
- **端点**: `ws://host/ws?api_key=xxx&topics=location,alarm`
|
||||
- **Topics**: location, alarm, device_status, attendance, bluetooth
|
||||
- **认证**: query param api_key (支持 master key + DB key)
|
||||
- **最大连接**: 100 个 WebSocket 连接
|
||||
- **消息格式**: JSON `{"topic": "...", "data": {...}, "timestamp": "..."}`
|
||||
- **广播点**: 位置存储、报警存储、设备上下线、考勤存储、蓝牙存储
|
||||
- **Ping/Pong**: 客户端发送 "ping" 保活,服务器回复 "pong"
|
||||
|
||||
### 数据清理
|
||||
- **自动清理**: 后台定时任务,每 `DATA_CLEANUP_INTERVAL_HOURS`(默认24) 小时执行
|
||||
- **保留天数**: `DATA_RETENTION_DAYS`(默认90) 天,删除过期的 location/heartbeat/alarm/attendance/bluetooth 记录
|
||||
- **手动清理**: `POST /api/system/cleanup` (admin only)
|
||||
|
||||
### 批量操作 API
|
||||
- `POST /api/devices/batch` — 批量创建 (最多500),输入去重 + DB去重,结果按输入顺序
|
||||
- `PUT /api/devices/batch` — 批量更新,单次 WHERE IN 查询 + 单次 flush
|
||||
- `POST /api/devices/batch-delete` — 批量删除 (最多100),通过 body 传 device_ids
|
||||
- `POST /api/locations/batch-latest` — 批量获取多设备最新位置 (最多100)
|
||||
- `GET /api/devices/all-latest-locations` — 获取所有在线设备最新位置
|
||||
- `POST /api/commands/batch` — 批量发送指令 (最多100),`model_validator` 互斥校验
|
||||
- 所有批量操作使用 WHERE IN 批量查询,避免 N+1
|
||||
|
||||
@@ -254,12 +270,13 @@ KKS 二进制协议,详见 `doc/KKS_Protocol_P240_P241.md`
|
||||
- 子协议 0x0A: IMEI(8字节) + IMSI(8字节) + ICCID(10字节)
|
||||
- 子协议 0x09: GPS 卫星状态
|
||||
- 子协议 0x00: ICCID(10字节)
|
||||
- 子协议 0x04: 设备配置上报 `ALM2=40;ALM4=E0;MODE=03;IMSI=...`
|
||||
|
||||
### 前端字段映射 (admin.html)
|
||||
- 设备信号: `d.gsm_signal` (非 `d.signal_strength`)
|
||||
- 指令响应: `c.response_content` (非 `c.response`)
|
||||
- 响应时间: `c.response_at || c.sent_at` (非 `c.updated_at`)
|
||||
- 位置地址: `l.address` (天地图逆地理编码结果)
|
||||
- 位置地址: `l.address` (高德逆地理编码结果)
|
||||
- 卫星数: `l.gps_satellites` (非 `l.accuracy`)
|
||||
- 记录时间: `l.recorded_at` (非 `l.timestamp`)
|
||||
- 报警来源: `a.alarm_source` (非 `a.source`)
|
||||
@@ -292,42 +309,20 @@ remotePort = 5001
|
||||
|
||||
## 高德地图 API
|
||||
|
||||
### 已有 Key
|
||||
### Key
|
||||
- **Web服务 Key**: `a9f4e04f5c8e739e5efb07175333f30b`
|
||||
- **安全密钥**: `bfc4e002c49ab5f47df71e0aeaa086a5`
|
||||
- **账号类型**: 个人认证开发者 (正在申请企业认证)
|
||||
|
||||
### 已验证可用的 API
|
||||
- **反地理编码** (`restapi.amap.com/v3/geocode/regeo`): 经纬度 → 地址文本
|
||||
- **坐标转换** (`restapi.amap.com/v3/assistant/coordinate/convert`): WGS-84 → GCJ-02
|
||||
|
||||
### 待企业认证后启用
|
||||
- **智能硬件定位** (`apilocate.amap.com/position`): WiFi+基站 → 经纬度 (需企业认证, 错误码 10012)
|
||||
- v1.0 GET: `apilocate.amap.com/position`
|
||||
- v2.0 POST: `restapi.amap.com/v5/position/IoT`
|
||||
- 参数格式: `bts=mcc,mnc,lac,cellid,signal` / `macs=mac,signal,ssid|mac,signal,ssid|`
|
||||
### 已接入服务
|
||||
- **✅ 逆地理编码** (`restapi.amap.com/v3/geocode/regeo`): 经纬度 → 地址文本,服务端 WGS84→GCJ02 坐标转换
|
||||
- **✅ 智能硬件定位** (`apilocate.amap.com/position`): WiFi+基站 → 经纬度 (代码就绪,企业认证通过前返回 10012)
|
||||
- **✅ 前端地图瓦片**: 高德瓦片 (GCJ-02, 标准Mercator),前端 WGS84→GCJ02 坐标转换
|
||||
- **数字签名**: `_amap_sign()` — 参数按key排序拼接 + AMAP_SECRET → MD5 → sig 参数
|
||||
|
||||
### 配额 (个人认证开发者)
|
||||
- 基础LBS服务: 5,000 次/日 (反地理编码、坐标转换等)
|
||||
- 在线定位: 50,000 次/日
|
||||
|
||||
### 接入步骤 (企业认证通过后)
|
||||
1. 在 `app/geocoding.py` 中设置 `AMAP_KEY`
|
||||
2. 实现 `_geocode_amap()` 函数调用智能硬件定位 API
|
||||
3. 注意返回坐标为 GCJ-02,需转换为 WGS-84 用于 Leaflet 地图
|
||||
4. 高德数字签名: 参数按key排序拼接 + 安全密钥 → MD5 → sig 参数
|
||||
|
||||
## 百度地图 API
|
||||
|
||||
### Key
|
||||
- **服务端 AK**: `nZ4AyCm7FTn85HbFuQjw0ItSYkgxEuhA`
|
||||
|
||||
### 已接入服务
|
||||
- **✅ 逆地理编码**: `api.map.baidu.com/reverse_geocoding/v3` — 经纬度 → 地址 (coordtype=wgs84ll, 无需坐标转换)
|
||||
- 优先级: 百度 > 天地图 (fallback)
|
||||
- 配额: 5,000次/日 (个人开发者)
|
||||
- **注意**: 百度内部使用 BD-09 坐标系,但逆地理编码接口支持 `coordtype=wgs84ll` 直接传入 WGS-84 坐标
|
||||
- 百度**无服务端基站/WiFi定位API**,基站定位仍用 Mylnikov
|
||||
- 基础LBS服务: 5,000 次/日 (逆地理编码等)
|
||||
- 在线定位: 50,000 次/日 (企业认证后 1,000,000 次/日)
|
||||
|
||||
## 已知限制
|
||||
|
||||
@@ -335,8 +330,7 @@ remotePort = 5001
|
||||
2. **Cloudflare Tunnel 仅代理 HTTP** - TCP 流量必须通过 FRP 转发
|
||||
3. **SQLite 单写** - 高并发场景需切换 PostgreSQL
|
||||
4. **设备最多 100 台列表** - 受 page_size 限制,超过需翻页查询
|
||||
5. **基站定位精度差** - 当前 Mylnikov API 中国基站精度 ~16km,待接入高德智能硬件定位后可达 ~30m
|
||||
6. **天地图逆地理编码使用 HTTP** - API不支持HTTPS,Key在URL中明文传输 (低风险: 免费Key, 已降级为备选)
|
||||
5. **基站/WiFi定位需企业认证** - 高德智能硬件定位 API 已接入但个人账号返回 10012,企业认证通过后自动生效
|
||||
|
||||
## 已修复的问题 (Bug Fix 记录)
|
||||
|
||||
@@ -359,7 +353,7 @@ remotePort = 5001
|
||||
|
||||
### 定位功能修复
|
||||
12. **WiFi/LBS 无坐标** - 添加 wifi/wifi_4g 解析分支 (原代码缺失)
|
||||
13. **地理编码集成** - 集成 Mylnikov.org API,LBS/WiFi 定位数据自动转换为经纬度坐标
|
||||
13. **地理编码集成** - LBS/WiFi 定位数据自动转换为经纬度坐标
|
||||
14. **邻近基站和WiFi数据** - 存储到 LocationRecord 的 neighbor_cells 和 wifi_data 字段
|
||||
|
||||
### 告警功能修复
|
||||
@@ -372,7 +366,7 @@ remotePort = 5001
|
||||
21. **LBS/WiFi 报警定位** - 为无GPS的报警添加前向地理编码
|
||||
|
||||
### 逆地理编码
|
||||
22. **天地图集成** - 位置和报警记录自动获取中文地址 (天地图逆地理编码)
|
||||
22. **逆地理编码集成** - 位置和报警记录自动获取中文地址 (高德逆地理编码)
|
||||
23. **地址字段** - LocationRecord 新增 address 字段,前端位置表/报警表/地图弹窗显示地址
|
||||
|
||||
### 蓝牙与考勤功能
|
||||
@@ -410,43 +404,101 @@ remotePort = 5001
|
||||
49. **前端侧边面板** - 位置追踪/信标管理页面添加左侧设备/信标列表面板,自动选中最近活跃设备
|
||||
50. **前端面板解耦** - 提取 PANEL_IDS 配置 + _initPanelRender 通用函数,toggleSidePanel 仅在 locations 页调用 invalidateSize
|
||||
|
||||
### 百度地图接入 & 连接修复 (2026-03-19)
|
||||
51. **百度逆地理编码** - 接入百度地图 reverse_geocoding/v3 API (coordtype=wgs84ll),优先于天地图
|
||||
52. **PROTO_ADDRESS_REPLY_EN 未导入** - 0xA5 报警地址回复时 NameError,补充 import
|
||||
53. **心跳自动恢复 online** - 心跳处理时自动将设备 status 设为 online + 重新注册 connections
|
||||
54. **高德地图瓦片** - 替换天地图瓦片为高德 (GCJ-02, 标准Mercator),添加 WGS84→GCJ02 坐标转换,可切换 provider (`MAP_PROVIDER` 变量)
|
||||
### 连接修复 (2026-03-19)
|
||||
51. **PROTO_ADDRESS_REPLY_EN 未导入** - 0xA5 报警地址回复时 NameError,补充 import
|
||||
52. **心跳自动恢复 online** - 心跳处理时自动将设备 status 设为 online + 重新注册 connections
|
||||
|
||||
### 全面切换高德 API (2026-03-23)
|
||||
53. **高德逆地理编码** - 接入 restapi.amap.com/v3/geocode/regeo,服务端 WGS84→GCJ02 坐标转换
|
||||
54. **高德智能硬件定位** - 接入 apilocate.amap.com/position (基站+WiFi定位,企业认证通过前返回 10012)
|
||||
55. **高德数字签名** - 实现 `_amap_sign()` 函数 (参数排序 + AMAP_SECRET + MD5)
|
||||
56. **服务端坐标转换** - geocoding.py 内置 `wgs84_to_gcj02()` Python 实现
|
||||
57. **高德地图瓦片** - 前端替换为高德瓦片 (GCJ-02, 标准Mercator),前端 WGS84→GCJ02 坐标转换
|
||||
58. **移除第三方地理编码** - 清理天地图/百度/Google/Unwired/Mylnikov,统一使用高德
|
||||
|
||||
### API 安全加固 & 批量管理 (2026-03-20)
|
||||
55. **API Key 认证** - `dependencies.py` 实现 X-API-Key 头认证,`secrets.compare_digest` 防时序攻击
|
||||
56. **CORS + 限流** - `SlowAPIMiddleware` 全局限流 (60/min),写操作独立限速 (30/min)
|
||||
57. **限流器真实 IP** - `extensions.py` 从 `X-Forwarded-For` / `CF-Connecting-IP` 提取真实客户端 IP
|
||||
58. **全局异常处理** - 拦截未处理异常返回 500,不泄露堆栈;放行 HTTPException/ValidationError
|
||||
59. **Schema 校验加强** - IMEI pattern、经纬度范围、Literal 枚举、command max_length、BeaconConfig MAC/UUID pattern
|
||||
60. **Health 端点增强** - `/health` 检测数据库连通性 + TCP 连接设备数
|
||||
61. **批量设备创建** - `POST /api/devices/batch` (最多500台),WHERE IN 单次查询去重,输入列表内 IMEI 去重
|
||||
62. **批量设备更新** - `PUT /api/devices/batch`,单次查询 + 批量更新 + 单次 flush
|
||||
63. **批量设备删除** - `POST /api/devices/batch-delete`,通过 body 传递避免 URL 长度限制
|
||||
64. **批量指令发送** - `POST /api/commands/batch` (最多100台),`model_validator` 互斥校验 device_ids/imeis
|
||||
65. **Heartbeats 路由** - 新增 `GET /api/heartbeats` 心跳记录查询 + 按 ID 获取
|
||||
66. **按 ID 查询端点** - locations/{id}, attendance/{id}, bluetooth/{id} 放在路由末尾避免冲突
|
||||
67. **Beacons double-commit 修复** - 移除 router 层多余的 flush/refresh,依赖 service 层
|
||||
59. **API Key 认证** - `dependencies.py` 实现 X-API-Key 头认证,`secrets.compare_digest` 防时序攻击
|
||||
60. **CORS + 限流** - `SlowAPIMiddleware` 全局限流 (60/min),写操作独立限速 (30/min)
|
||||
61. **限流器真实 IP** - `extensions.py` 从 `X-Forwarded-For` / `CF-Connecting-IP` 提取真实客户端 IP
|
||||
62. **全局异常处理** - 拦截未处理异常返回 500,不泄露堆栈;放行 HTTPException/ValidationError
|
||||
63. **Schema 校验加强** - IMEI pattern、经纬度范围、Literal 枚举、command max_length、BeaconConfig MAC/UUID pattern
|
||||
64. **Health 端点增强** - `/health` 检测数据库连通性 + TCP 连接设备数
|
||||
65. **批量设备创建** - `POST /api/devices/batch` (最多500台),WHERE IN 单次查询去重,输入列表内 IMEI 去重
|
||||
66. **批量设备更新** - `PUT /api/devices/batch`,单次查询 + 批量更新 + 单次 flush
|
||||
67. **批量设备删除** - `POST /api/devices/batch-delete`,通过 body 传递避免 URL 长度限制
|
||||
68. **批量指令发送** - `POST /api/commands/batch` (最多100台),`model_validator` 互斥校验 device_ids/imeis
|
||||
69. **Heartbeats 路由** - 新增 `GET /api/heartbeats` 心跳记录查询 + 按 ID 获取
|
||||
70. **按 ID 查询端点** - locations/{id}, attendance/{id}, bluetooth/{id} 放在路由末尾避免冲突
|
||||
71. **Beacons double-commit 修复** - 移除 router 层多余的 flush/refresh,依赖 service 层
|
||||
|
||||
### 0x94 子协议 0x04
|
||||
- 设备配置上报: `ALM2=40;ALM4=E0;MODE=03;IMSI=460240388355286`
|
||||
- 在设备重连/重启后上报
|
||||
### 全面改进 (2026-03-22)
|
||||
|
||||
#### Protocol 修复
|
||||
72. **parser.py 0x22 CellID** - 从2字节改为3字节解析
|
||||
73. **parser.py 0xA5 LBS告警** - 移除错误的 datetime+lbs_length 前缀
|
||||
74. **parser.py 0xA9 WiFi告警** - 完全重写为 datetime+MCC/MNC+cell_type+cell_count+基站+TA+WiFi+alarm_code
|
||||
75. **parser.py voltage** - 0xA3/0xA5/0xA9 voltage 从2字节改为1字节
|
||||
76. **parser.py 0xA4** - 新增多围栏告警解析器 (含 fence_id)
|
||||
77. **parser.py 0xB2** - 完整 iBeacon 解析 (RSSI/MAC/UUID/Major/Minor/Battery)
|
||||
78. **parser.py 0xB3** - beacon_count + 每信标30字节解析
|
||||
79. **parser.py 0xB0/0xB1** - 补充 gps_positioned/terminal_info/voltage/gsm_signal 等中间字段
|
||||
80. **parser.py 0x81** - 新增指令回复解析器
|
||||
81. **builder.py 0x1F** - 时间同步添加2字节 language 参数
|
||||
82. **builder.py 地址回复** - 重写 CN/EN 地址回复完整格式
|
||||
83. **builder.py 0x80/0x82** - cmd_len 正确包含 language(2)
|
||||
84. **constants.py** - 从 PROTOCOLS_REQUIRING_RESPONSE 移除 0x28
|
||||
|
||||
#### 批量 API + 索引
|
||||
85. **batch-latest** - `POST /api/locations/batch-latest` 批量获取多设备最新位置
|
||||
86. **all-latest-locations** - `GET /api/devices/all-latest-locations` 所有在线设备位置
|
||||
87. **数据库索引** - 新增5个索引 (alarm_type, acknowledged, beacon_mac, location_type, attendance_type)
|
||||
|
||||
#### 多 API Key + 权限控制
|
||||
88. **ApiKey 模型** - SHA-256 hash, permissions(read/write/admin), is_active
|
||||
89. **多 Key 认证** - master key (env) + DB keys, last_used_at 追踪
|
||||
90. **权限控制** - require_write/require_admin 依赖,写端点需 write 权限
|
||||
91. **Key 管理 API** - `/api/keys` CRUD (admin only),创建时返回明文一次
|
||||
92. **DeviceUpdate** - 移除 status 字段 (设备状态由系统管理)
|
||||
|
||||
#### WebSocket 实时推送
|
||||
93. **WebSocketManager** - 连接管理器,topic 订阅,最大100连接
|
||||
94. **WS 端点** - `/ws?api_key=xxx&topics=location,alarm` WebSocket 认证
|
||||
95. **TCP 广播集成** - 7个广播点 (location, alarm, device_status x2, attendance, bluetooth x2)
|
||||
|
||||
#### 数据清理 + 补充
|
||||
96. **自动数据清理** - 后台定时任务,DATA_RETENTION_DAYS=90, DATA_CLEANUP_INTERVAL_HOURS=24
|
||||
97. **手动清理 API** - `POST /api/system/cleanup` (admin only)
|
||||
98. **alarm_source 过滤** - alarms 列表新增 alarm_source 参数
|
||||
99. **beacon_mac 过滤** - bluetooth 列表新增 beacon_mac 参数
|
||||
100. **command_type 过滤** - commands 列表新增 command_type 参数
|
||||
101. **sort_order 参数** - alarms/bluetooth 列表支持 asc/desc 排序
|
||||
|
||||
#### 协议层统一
|
||||
102. **PacketBuilder 统一** - tcp_server.py 内嵌 PacketBuilder 改为委托 protocol/builder.py
|
||||
|
||||
### 审计修复 (2026-03-23)
|
||||
103. **require_admin 导入** - main.py 缺少 require_admin 导入,设置 API_KEY 后 cleanup 端点崩溃
|
||||
104. **0x28/0x2C CellID 3字节** - tcp_server.py 2G 基站 CellID 从2字节修正为3字节 (0x28 LBS, 0x2C WiFi, 邻区解析)
|
||||
105. **parser.py CellID 3字节** - parse_lbs_station 默认 cell_id_size=2→3,新增3字节分支; _parse_lbs_address_req CellID 2→3字节
|
||||
106. **alarm_source 字段长度** - models.py String(10)→String(20), schemas.py max_length=10→20 ("single_fence"=12字符)
|
||||
107. **AlarmRecord wifi_data/fence_data** - 0xA9 WiFi报警存储 wifi_data; 0xA4 多围栏报警提取并存储 fence_id
|
||||
108. **CommandLog.sent_at** - 指令发送成功后设置 sent_at 时间戳 (原来始终为 NULL)
|
||||
109. **geocoding IMEI 参数化** - 移除硬编码 IMEI,新增 GEOCODING_DEFAULT_IMEI 配置项,geocode_location 接受 imei 参数,TCP 层传递设备 IMEI
|
||||
110. **parser.py 循环长度检查** - _parse_lbs_multi 和 _parse_wifi 站点循环检查从 pos+5 改为 pos+6 (LAC=2+CellID=3+RSSI=1=6)
|
||||
111. **batch sent_at** - batch_send_command 批量指令路径也设置 cmd_log.sent_at (与单条路径一致)
|
||||
112. **GPS 经度符号反转** - course_status bit 11 含义为 0=东经/1=西经 (非 1=东经),`is_east` 改为 `is_west`,修复成都定位到北美洲的问题 (tcp_server.py + parser.py)
|
||||
|
||||
## 待完成功能
|
||||
|
||||
1. **⭐ 接入高德智能硬件定位** - 企业认证通过后,替换 Mylnikov,大幅提升 WiFi/基站定位精度
|
||||
2. ~~**地图瓦片**~~ - ✅ 已切换为高德瓦片 (GCJ-02),支持 MAP_PROVIDER 切换 ('gaode'|'tianditu')
|
||||
3. **心跳扩展模块解析** - 计步器、外部电压等模块未解析
|
||||
4. ~~**蓝牙信标调试**~~ - ✅ 已完成 (2026-03-18),0xB2打卡数据正常上报,信标匹配成功
|
||||
1. **心跳扩展模块解析** - 计步器、外部电压等模块未解析
|
||||
2. **前端 WebSocket 集成** - admin.html Dashboard 改用 WebSocket 替代 30s 轮询,报警页实时通知
|
||||
3. **协议层深度统一** - tcp_server.py 辅助方法 (_parse_gps, _parse_datetime 等) 逐步迁移到 protocol/parser.py
|
||||
|
||||
## 调试技巧
|
||||
|
||||
```bash
|
||||
# 查看实时日志
|
||||
tail -f /home/gpsystem/server.log | grep -aE "TCP|login|heartbeat|error|geocod|Tianditu" --line-buffered
|
||||
tail -f /home/gpsystem/server.log | grep -aE "TCP|login|heartbeat|error|geocod|Amap" --line-buffered
|
||||
|
||||
# 检查数据库
|
||||
python3 -c "
|
||||
|
||||
Reference in New Issue
Block a user