南钢智慧管控平台 FastAPI 接口设计与数据结构说明
本文对应平台后端
v3.0.0,用于说明前后端分离后的 API 设计、数据结构和联调方式。示例地址统一写作<server>。出于生产安全考虑,现场设备 IP、账号、口令、厂商写入报文、道闸控制确认值等内容不在公开文档中展示。
一、设计目标
南钢智慧管控平台需要同时服务智慧大屏、车辆管控、人员预约、门岗设备和后续新增子系统。后端采用 FastAPI,将页面展示与设备协议解耦,并通过 PostgreSQL 保存业务数据、Redis 承担缓存和实时事件分发。
核心目标包括:
- 前端只依赖统一 REST API,不直接访问摄像机、门禁或停车软件。
- 不同厂家设备由适配器转换为统一的通道、车辆事件和控制能力模型。
- 大屏通过 SSE 接收实时变化,断线时可以回退到普通查询接口。
- 车辆进出、预约、白名单同步和人工控制都保留可追溯记录。
- PostgreSQL 与 Redis 只运行在后端内部网络,浏览器和现场设备只访问 FastAPI。
二、总体架构
Vue 3 大屏 / 管理页面
│ HTTPS / 同源 /api
▼
Nginx 网关
│
▼
FastAPI 平台服务(REST + SSE)
│ │ │
▼ ▼ ▼
PostgreSQL Redis 设备适配器
业务数据 缓存/事件 停车软件、门禁、摄像机、DI/Modbus
生产环境推荐由 Nginx 将同源 /api/ 转发到 FastAPI。这样前端无须写死内网地址,同一套页面可在不同授权网络中使用。
三、接口约定
3.1 基础地址
http(s)://<server>/api
健康检查位于根路径 /health/*。FastAPI 自带的交互式文档位于 /docs,生产部署可按网络边界限制访问。
3.2 数据格式
- 请求和响应默认使用
application/json; charset=utf-8。 - 日期时间统一使用
yyyy-MM-dd HH:mm:ss。 - 查询接口采用
items + total返回列表和总数。 - 方向字段统一为
in(进场)和out(出场)。 - 车牌在入库前自动去除空白并转换为大写。
- 图片接口直接返回
image/jpeg,不存在时返回404。
列表响应示例:
{
"items": [
{
"id": 1001,
"gate_no": "示例通道",
"direction": "in",
"captured_at": "2026-08-02 10:30:00"
}
],
"total": 1
}
错误响应沿用 FastAPI 的 detail 字段:
{
"detail": "请求内容不符合业务规则"
}
常用状态码:
| 状态码 | 含义 |
|---|---|
200 |
查询或操作成功 |
201 |
预约、车辆档案创建成功 |
204 |
删除成功,无响应正文 |
400 |
业务参数错误或缺少二次确认 |
401 |
兼容登录接口认证失败 |
404 |
通道、车辆、事件或图片不存在 |
409 |
数据冲突、设备状态不支持当前操作 |
422 |
字段类型、长度或枚举校验失败 |
502 |
下游停车软件、门禁或设备调用失败 |
503 |
服务依赖未就绪,或天气数据暂不可用 |
四、健康检查
GET /health/live
只判断 FastAPI 进程是否存活,适合容器存活探针。
{
"success": true,
"service": "nangang-platform-api"
}
GET /health/ready
检查 PostgreSQL、Redis、采集 Worker 和通道统计,适合 Nginx、大屏右上角服务器状态以及容器就绪探针。
{
"success": true,
"service": "nangang-platform-api",
"dependencies": {
"postgres": true,
"redis": true,
"worker": true
},
"online_gates": 8,
"total_gates": 10
}
任一关键依赖不可用时,接口返回 503,同时保留各依赖的布尔状态,前端可以显示明确的故障来源。
五、大屏公开查询接口
| 方法 | 路径 | 作用 | 主要参数 |
|---|---|---|---|
GET |
/api/public/weather |
查询南京实时天气 | 无 |
GET |
/api/public/stats |
查询指定时间段进出统计 | start、end |
GET |
/api/public/summary |
查询当前在场和容量概况 | 无 |
GET |
/api/public/events |
查询大屏安全字段事件 | limit=1..100 |
GET |
/api/public/records |
查询完整车辆进出记录 | 分页、车牌、通道、方向、时间 |
GET |
/api/public/sessions |
查询车辆在场会话 | session_status、limit |
GET |
/api/public/gates |
查询全部通道及能力 | 无 |
GET |
/api/public/gates/{gate_id}/barrier |
查询指定道闸状态 | 通道标识 |
GET |
/api/public/events/{event_id}/image |
获取事件抓拍图片 | 事件 ID |
GET |
/api/public/appointments |
查询最近预约 | limit=1..50 |
GET |
/api/public/appointments/options |
查询人员预约部门和设备选项 | 无 |
5.1 统计查询
curl "https://<server>/api/public/stats?start=2026-08-02%2000:00:00&end=2026-08-02%2023:59:59"
未传时间时,服务默认统计当天 00:00:00 至 23:59:59。概况接口则返回当前在场数量、剩余容量及相关汇总字段,适合大屏定时兜底刷新。
5.2 进出记录查询
curl "https://<server>/api/public/records?limit=50&offset=0&plate=%E8%8B%8FA12345&direction=in"
参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
limit |
integer | 每页数量,1..100,默认 50 |
offset |
integer | 偏移量,从 0 开始 |
plate |
string | 车牌模糊或精确筛选,由服务统一转为大写 |
gate_id |
string | 通道标识 |
direction |
enum | 空、in 或 out |
start |
datetime | 开始时间 |
end |
datetime | 结束时间 |
5.3 在场会话
车辆一次进场到对应出场形成一个停车会话。session_status 支持:
open:仍在场,默认值;closed:已出场;all:全部会话。
会话模型将进场事件、出场事件和停留时长关联起来,避免前端自行配对进出记录。
六、南京天气接口
GET /api/public/weather
服务固定使用南京坐标和 Asia/Shanghai 时区,从 Open-Meteo 获取天气。Redis 新鲜缓存为 10 分钟,最近一次成功结果可作为 24 小时降级缓存。
{
"city": "南京",
"condition": "多云",
"temperature_c": 30.2,
"weather_code": 3,
"observed_at": "2026-08-02 10:30:00",
"updated_at": "2026-08-02 10:31:12",
"source": "Open-Meteo",
"stale": false
}
stale=true 表示外部天气源暂时不可用,当前返回的是最近一次成功缓存。若没有可用缓存,则返回 503,前端应保留上一次显示结果并提示数据更新时间。
七、SSE 实时事件流
GET /api/public/realtime/stream
接口使用 Server-Sent Events(SSE)向浏览器推送实时变化,服务每 15 秒发送一次保活信息。事件类型包括设备状态、车辆进出、在场数量和天气更新。
浏览器示例:
const stream = new EventSource("/api/public/realtime/stream");
stream.addEventListener("vehicle_event", (event) => {
const data = JSON.parse(event.data);
console.log("车辆事件", data);
});
stream.addEventListener("presence_updated", (event) => {
const data = JSON.parse(event.data);
console.log("在场数量", data);
});
stream.onerror = () => {
// EventSource 会自动重连;页面同时保留定时查询作为降级方案。
};
SSE 只负责通知“数据已变化”,重要页面仍应在首次打开时调用 REST API 获取完整快照,重连后再次校准,避免网络中断期间漏掉变化。
八、预约接口
8.1 人员预约
POST /api/public/appointments/person
{
"name": "张三",
"phone": "13800000000",
"reason": "项目沟通",
"department_no": "DEPT001",
"device_nos": ["DEVICE001"],
"id_card": "",
"sex": 1,
"photo": "data:image/jpeg;base64,<base64-data>",
"valid_from": "2026-08-02 09:00:00",
"valid_until": "2026-08-02 18:00:00"
}
字段约束:姓名 1..50 字符,手机号 6..30 字符,事由 1..100 字符,设备最多 30 个;sex 取 0/1/2;照片为 Base64,服务限制有效长度;许可结束时间必须晚于开始时间。
8.2 车辆预约
POST /api/public/appointments/vehicle
{
"name": "李四",
"phone": "13800000000",
"plate": "苏A12345",
"plate_color": "blue",
"reason": "临时来访",
"valid_from": "2026-08-02 09:00:00",
"valid_until": "2026-08-02 18:00:00"
}
车牌颜色支持 auto、blue、yellow、green。预约成功后,平台先保存预约记录,再建立临时车辆档案并同步到停车系统;任一外部同步失败都会写入失败状态和审计记录,不会把“仅保存成功”误报为“设备已生效”。
九、车辆档案与白名单
车辆档案接口供车辆管控页面使用:
| 方法 | 路径 | 作用 |
|---|---|---|
GET |
/api/vehicles?query= |
查询车辆档案 |
POST |
/api/vehicles |
新增车辆并按启用状态同步 |
PUT |
/api/vehicles/{vehicle_id} |
修改车辆并更新停车系统 |
POST |
/api/vehicles/{vehicle_id}/sync |
重试单车同步 |
DELETE |
/api/vehicles/{vehicle_id} |
停用下游权限后删除车辆 |
POST |
/api/vehicles/import |
批量导入,单次最多 500 条 |
车辆输入模型:
{
"plate": "苏A12345",
"owner": "张三",
"department": "生产部",
"phone": "13800000000",
"vehicle_type": "内部车辆",
"plate_color": "blue",
"valid_from": "2026-08-02 00:00:00",
"valid_until": "2027-08-02 23:59:59",
"enabled": true,
"note": "长期车辆"
}
主要约束:车牌 3..16 字符;车主最多 40 字符;部门最多 80 字符;备注最多 200 字符;失效时间必须晚于生效时间。日期只传 yyyy-MM-dd 时,开始日期自动补 00:00:00,结束日期自动补 23:59:59。
9.1 批量导入
{
"duplicate_mode": "update",
"items": [
{
"plate": "苏A12345",
"owner": "张三",
"department": "生产部",
"enabled": true
},
{
"plate": "苏A67890",
"owner": "李四",
"department": "物流部",
"enabled": true
}
]
}
duplicate_mode 支持 skip 和 update。返回结果会分别统计 created、updated、skipped、failed,并为每一行返回状态和失败原因,便于前端生成导入报告。
{
"success": true,
"total": 2,
"created": 1,
"updated": 1,
"skipped": 0,
"failed": 0,
"items": [
{
"row": 1,
"plate": "苏A12345",
"status": "updated",
"message": "同步成功",
"vehicle_id": 10
}
]
}
十、核心数据结构
10.1 通道 Gate
| 字段 | 说明 |
|---|---|
id |
平台内部通道标识 |
gate_no |
展示名称或门号 |
direction |
in / out |
online |
最近一次采集是否在线 |
last_seen_at |
最近在线时间 |
capabilities |
设备支持的状态读取、事件采集、图片或控制能力 |
10.2 车辆事件 VehicleEvent
| 字段 | 说明 |
|---|---|
id |
平台事件 ID |
source_key |
来源侧唯一键,用于去重 |
gate_id / gate_no |
通道标识与显示名称 |
direction |
进场或出场 |
plate |
标准化车牌 |
plate_color |
车牌颜色 |
captured_at |
设备抓拍时间 |
received_at |
平台接收时间 |
image_path |
平台内部图片引用,不直接暴露文件系统路径 |
10.3 停车会话 ParkingSession
| 字段 | 说明 |
|---|---|
plate |
车牌 |
status |
open / closed |
entry_event_id |
进场事件 |
exit_event_id |
出场事件 |
entered_at / exited_at |
进出时间 |
duration_seconds |
停留时长 |
10.4 车辆档案 Vehicle
除车牌、车主、部门和有效期外,模型还保存 enabled、下游同步状态、同步结果编号、最近同步消息与更新时间。这样可以区分“平台已保存”“停车软件已接收”和“现场设备已具备放行条件”。
10.5 预约 Appointment
预约记录包含类型、预约人、手机号、事由、车牌或人员目标、许可时间、外部系统编号、处理状态和结果消息。平台先落库再调用外部系统,因此失败记录也能被追踪和重试。
10.6 审计 AuditLog
人工控制、车辆新增修改、批量导入、预约和同步重试都会记录操作类型、目标对象、来源地址、成功状态、时间及必要的错误摘要。审计记录不保存明文密码和设备口令。
十一、设备同步与控制边界
设备适配器统一输出四类能力:在线状态、车辆事件、抓拍图片和控制能力。查询端只读取统一模型,不关心设备来自 HTTP、XML、停车软件接口还是其他现场协议。
人工开闸属于生产控制操作,接口必须经过明确二次确认、网络访问控制和审计。本文不公开该接口路径、确认值、设备标识和底层报文;相关内容只应出现在受控的交付运维手册中。业务上也不应把“新增车牌”简单等同于“立即抬杆”:是否自动放行还取决于有效期、启用状态、下游同步结果以及停车系统当前策略。
十二、Nginx 同源转发
推荐配置思路如下,实际上游地址由部署环境提供:
location /api/ {
proxy_pass http://platform_api:19080/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /api/public/realtime/stream {
proxy_pass http://platform_api:19080/api/public/realtime/stream;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 1h;
}
SSE 路径需要关闭代理缓冲并延长读取超时,否则浏览器可能长时间收不到事件,或被网关误判为超时。
十三、联调建议
- 先调用
/health/ready,确认数据库、Redis 和采集 Worker 全部就绪。 - 再调用
/api/public/gates,检查通道总数、在线状态和能力集合。 - 使用
/api/public/records与/api/public/sessions核对进出记录和在场车辆。 - 打开 SSE 后制造一条测试事件,确认事件通知和 REST 快照一致。
- 新增或导入车辆后,以接口返回的同步状态为准,不以页面“保存成功”代替设备侧生效确认。
- 对外部系统失败、重复车牌、无效时间范围和网络超时分别做一次异常测试。
十四、安全说明
- 浏览器和现场终端只访问 FastAPI,不直接连接 PostgreSQL 或 Redis。
- 公开查询与业务写入应在网关层按部署网络进行访问控制。
- 控制类操作必须保留二次确认、来源地址和审计记录。
- 生产日志应脱敏,不记录明文口令、完整身份信息和设备认证参数。
- 抓拍图片使用事件 ID 访问,并校验文件路径,防止越权读取服务器文件。
- API 文档与实际服务版本保持一致,升级时同步维护字段、迁移和兼容说明。
十五、前后端代码仓库
前端仓库提供 Vue 3 大屏和 Nginx 同源转发配置。后端链接指向可公开交付的脱敏版本,用于展示 FastAPI 分层、数据结构和部署方式;其中不包含生产环境配置、账号密码、现场设备 IP、真实业务数据、图片备份和厂商控制参数。实际部署时应通过环境变量或受控配置文件补充现场参数,不要将生产密钥提交到 GitHub。
结语
这套 API 的重点不是把各厂家接口原样暴露给前端,而是建立稳定的平台契约:页面只面向统一业务模型,设备差异由后端适配器消化,实时性由 Redis 与 SSE 提供,业务一致性由 PostgreSQL 和审计记录保障。后续接入新的门禁、道闸或监控子系统时,只需新增适配器并复用现有事件和通道模型,无须重写大屏。