# V0.3 本地接口 服务默认 `http://127.0.0.1:8769`,只监听当前电脑。所有POST使用JSON与 `X-CSRF-Token`;先读取 `/api/state` 取得当前进程令牌,后端重启后重新读取。Host与Origin必须来自本机。此令牌是本地浏览器操作约束,不是产品网关/设备鉴权。 ## 工作台 | 方法与路径 | 字段 | 行为 | |---|---|---| | GET `/health` | — | 版本0.2,原型状态 | | GET `/api/state` | — | 标签、任务、事件、统计、CSRF令牌 | | GET `/api/export` | — | UTF-8 BOM CSV,记录每行的device_mode | | POST `/api/labels` | id,scenario,item_code,name,location,quantity,unit,min_quantity | 新增料位,默认模拟 | | POST `/api/tasks` | label_id,type,quantity,request_id可选UUID | 创建pick/replenish任务;同request_id相同内容只创建一次 | | POST `/api/tasks/{id}/complete` | {} | 业务确认,pick扣料/replenish加料;重复确认幂等 | | POST `/api/tasks/{id}/cancel` | {} | 取消并释放预留;不改总库存 | | POST `/api/labels/{id}/inventory` | quantity,reason可选 | 库存校正,不得低于已预留数量 | | POST `/api/labels/{id}/locate` | {} | 新命令含led_seconds=10 | | POST `/api/labels/{id}/button` | button,event_id,task_id可选 | 仅模拟标签;按键1多任务时必须指明task_id | | POST `/api/labels/{id}/mode` | device_mode:simulation或external | 切换模式,创建新显示版本,清除旧在线状态 | | POST `/api/labels/{id}/select-task` | task_id | 将该料位未完成pick显示到标签,新版本含该任务编号/数量 | | POST `/api/labels/{id}/retry-display` | {} | 用当前业务状态生成新命令/版本,清除当前失败提示 | 标签量和安全库存为0..1e9整数;任务数量为1..1e9。字符串按UTF-8字节限制:id31且仅ASCII字母数字下划线连字符;item_code63、name95、location63、unit15。任务编号最多63字节。控制字符、无效Unicode、布尔数量、未知字段均拒绝。 创建任务先预留库存,完成时再变更总量。补料同一料位只允许一个open任务。库存事务由SQLite BEGIN IMMEDIATE保护。完成/取消显示中的任务后自动选择最早的未完成pick。 ## 实机网关 以下接口仅在标签device_mode=external时允许。实机命令不会被模拟worker确认。 | 方法与路径 | 字段 | 行为 | |---|---|---| | GET `/api/device/{id}/command` | — | `{command: {...}}` 或 `{command:null}`;当前待刷新命令完整不可变快照 | | POST `/api/device/{id}/heartbeat` | {} | 网关在收到有效设备通信后上报;超过15秒没上报,标签离线 | | POST `/api/device/{id}/receipt` | event_id,command_id,display_version,display_ok布尔 | 驱动刷新终态,持久去重;不完成业务、不更新库存 | | POST `/api/device/{id}/button` | event_id,button,display_version,task_id可选 | 实机业务事件;按键1必须匹配曾成功上报的显示任务 | 命令字段:`command_id,label_id,display_version,item_code,name,location,quantity,unit,task_id,task_type,task_quantity,led_seconds`。没有active任务时task_id/task_type为空字符串、task_quantity=0。display_version为1..uint32最大值。quantity是库存总量,task_quantity是本次领料数量。 实机display_status:pending_device / device_reported / display_failed;display_report_version仅为实机驱动成功报告的版本。模拟display_status:pending_simulated_ack / simulated_ack;display_ack_version仅记录虚拟接收。device_online在模拟模式为null,实机模式依据device_last_seen计算。battery仍是历史演示字段,实机界面不展示它为测量电量。 新的命令取代此前pending命令,不修改旧快照。旧命令回执可作历史记录,不能改当前失败提示或压低最新成功版本。同命令只能有一个终态;刷新失败重试需创建新版本。任务接收/显示时间只绑定真正出现在快照中的任务。 ## USB NDJSON 115200,每行一条JSON。主机发送命令给板端;板端在刷新后发送显示事件、实体按键后发送业务事件。板端输入最大1535字节,溢出丢弃整帧并恢复到下一换行;网关帧上限4096字节。 ```json {"type":"hello","label_id":"EL-001","boot_id":"随机启动编号","needs_sync":true,"storage_fault":false,"queued_events":0} {"type":"command","command":{"command_id":"UUID","label_id":"EL-001","display_version":2,"item_code":"R10K","name":"10K电阻","location":"A01","quantity":100,"unit":"只","task_id":"UUID","task_type":"pick","task_quantity":3,"led_seconds":10}} {"type":"event","label_id":"EL-001","event":{"kind":"display","event_id":"UUID","command_id":"UUID","display_version":2,"display_ok":true}} {"type":"event","label_id":"EL-001","event":{"kind":"button","event_id":"UUID","button":1,"task_id":"UUID","display_version":2}} {"type":"ack","event_id":"UUID","result":"accepted"} ``` 新启动设备needs_sync时,网关创建新版本;同次启动只触发一次,直到成功显示。发出事件后不改变UUID;队列接收ACK且持久保存成功才删除。4xx永久拒绝会先写入data/device-rejections.ndjson并fsync,然后回ACK result=rejected;需要核对该日志。5xx、网络故障或CSRF失效不退队列。显示报告不是光学读屏验证。 该USB版本连接本地受控电脑。外部网络、多租户、设备证书、产品账号权限不在本地原型中实现;BLE无线加密和限时配对范围见V0.3扩展。 ## V0.3 扩展 创建任务可选reference(工单/领料单,最多63个UTF-8字节),写入任务和操作记录。request_id去重包含非空reference,重复ID改变单据会409。 工作台complete提交`{scanned_item,scanned_location,operator}`,三项必须一起提交;料号/货位与标签精确匹配后才更改库存,错码409 scan_mismatch,部分字段400。verification写入业务完成事件;操作员是录入标识,未做账号登录鉴权。保留旧complete空对象接口兼容和实体按钮路径,它们不产生扫码验证证据;现场规程若要求每次强制扫码,应使用工作台确认并另行限制实体直接确认。 heartbeat增加可选device_id(16位小写十六进制)、transport(usb/ble)、firmware(≤31 UTF-8字节)、storage_fault(bool)、queued_events(0–16)。外部通信诊断进入标签状态,新字段device_transport/device_firmware/device_storage_fault/device_queued_events。旧hello/heartbeat空体仍兼容。 BLE与USB使用相同NDJSON,BLE通知/写入可任意分包,不能直接按通知解析JSON。BLE使用认证加密NUS服务,帧开头/结尾换行,20字节带响应写入;ATT传输响应不代表显示或库存提交。业务ACK仍沿用event_id持久去重。USB控制`{"type":"pair"}`开启60秒配对入口,只在USB打印SDK动态PIN;具体真机协议验收详见固件说明。