设备(业务)

设备模块讲三件事:资产台账(设备/采集服务器/型号/厂商的 CRUD 与异步导入)、设备文件通道(v1/general 的设备号文件视图与上传)、零售个人空间与设备分享(投影三态)。设备的实时指令(固件触发、上传命令、PTT 投递)不走本模块 REST,走 MQTT 命令,见各节内点名。

本页是 data-service device 模块接口的业务说明,非业务说明不在本页复述:

  • OpenAPI JSON(可直接导入 Postman 等工具):https://zxs.netbodycamera.com/main-service/v3/api-docs/device
  • 在线 Swagger 视图:data-service · 设备
  • 端点全量清单(含权限点与中文说明):清单层 · device

参数、请求/响应字段、错误码等契约事实一律见上述 Swagger 与清单层;本页只讲业务语义与动线。

dashboard 仪表盘

设备与在线状态的 KPI 聚合只读端点。已知状态:Web 仪表盘当前消费 /v2/mock/dashboard/* 静态样本(机构手册「mock 与静态资源」缺口具名在案,正式接口未在 Web 现役)——对接前先以清单层与 Swagger 核对实际形态。契约见清单层 · dashboard

data-acquisition-box 采集箱

采集箱台账 CRUD(无独立业务子流程);场景领域页:设备与资产域 · data-acquisition-box。契约见清单层 · data-acquisition-box

data-acquisition-box-fingerprint-scanner 采集箱指纹扫描仪

采集箱指纹扫描仪台账 CRUD;契约见清单层

data-acquisition-box-model 采集箱型号

采集箱型号字典 CRUD;契约见清单层

data-acquisition-device 采集设备

采集设备(执法记录仪等)主档,设备域的业务重心。

asset-and-import 资产主档与异步导入

  • importList:异步导入——data=true 只表示合法项已提交 JMS,监听器随后逐项 upsert、解析机构/型号/服务器并重建机构树;没有关联响应、进度或逐行最终结果,调用方只能稍后重新查询。
  • listCache:缓存列表,供选择器与直播/回放/远控页消费。读取语义:详情/列表会组合绑定服务器、在线状态和最近直播点击时间——这些是读取时动态值,不是持久化写入的回显。
  • page/list/count/getById/removeById* 为常规 CRUD(资源表受当前认证租户与数据权限约束,请求中的 tenantId 不能替代空间切换)。

device-sharing 设备分享生命周期

零售侧把个人空间内一台自有设备分享给另一名用户,状态机横跨发起方与受赠方两个租户:

  • share(发起):在目标用户的个人空间租户创建 To be confirm share 设备分享投影,并在发起方租户写入分享记录(device_share);受赠方确认前设备不出现在其可用列表语义中。
  • confirmShare(受赠方接受):按 deviceId(受赠方自己租户内的分享投影 ID)把投影与发起方记录一并置 confirm share(写 confirmTime)。源码不校验投影当前 state——重复确认会再次写成功并刷新 confirmTime(幂等写覆盖时间戳);对未确认(To be confirm share)投影调用 liftShare 同样生效(未确认就退出)。
  • 退场双出口:cancelShare(发起方撤销,按 deviceShareId;置 cancel share 软删并同步删除目标租户投影——待确认与已确认都可撤销);liftShare(受赠方解除,按 deviceId;投影置 lift share 软删、发起方记录同步置位)。对分享来的设备不得调用 unbind(解绑退场的是整条拥有周期)。
  • 记录面在 device-share;投影三态概念见账号与个人空间

personal-space 个人空间绑定

  • bind:把设备绑定到当前用户个人空间,生成设备直接拥有投影state=bind)。携带设备号与绑定授权码;绑定为投影复制而非设备搬运——库存侧投影不因此转移。授权码双版本:服务端优先按 V2 识别(以 V2 开头、以设备号结尾、总长恰 32 位——只依赖设备号,与绑定者无关),不满足 V2 判定的一律按 V1 严格比较(依赖当前用户名——同一台设备对不同用户算出的 V1 授权码不同);任一不满足报非法授权码。该值的生成算法属于内部实现,不在文档披露范围,具体生成方式请与开发人员沟通确认。当前租户为设备库存租户 pcm 时绑定/解绑均被直接拒绝;force=true 或授权码变化触发归属转移(先退场旧投影与活跃分享再建新投影,退场对账失败则整体失败)。
  • unbind:解绑自有设备、终止直接拥有周期;由它派生到其他用户的分享投影与分享记录一并退场。
  • listForPersonalSpace:个人空间设备列表(第一代读取端点),返回两类来源投影(直接拥有 + 分享来的),每台附当前采集服务器绑定与三路连接状态;分享来的还带设备管理标记。state 过滤的合法取值只有 bind/To be confirm share/confirm share 三种(终态行已软删,传其它值只得空集)。写路径(绑定/解绑/分享生命周期)只存在于第一代,第二代读取视图见 v1-retail

场景页:设备与资产域 · data-acquisition-device(含异步导入、缓存读取两个子流程小节)、发起设备分享确认设备分享撤销设备分享解除设备分享绑定设备到个人空间解绑个人空间设备查询个人空间设备列表。契约见清单层 · data-acquisition-device

data-acquisition-device-model 采集设备型号

采集设备型号字典 CRUD;契约见清单层

data-acquisition-server 采集服务器

采集服务器主档:importList/listCachedata-acquisition-device 同款异步导入与缓存读取语义;其余为 CRUD。服务器在线/信息同步的运行时面见运行时关联。契约见清单层 · data-acquisition-server

data-acquisition-server-data-acquisition-device 采集服务器与采集设备关联

采集服务器与采集设备的绑定关联表(设备详情里「绑定服务器」组合项的来源),CRUD;契约见清单层

data-acquisition-server-file-storage-server 采集服务器与文件存储服务器关联

采集服务器与文件存储服务器的绑定关联表,CRUD;契约见清单层

data-acquisition-server-model 采集服务器型号

采集服务器型号字典 CRUD;契约见清单层

device 设备

设备库存主档 CRUD;场景页未直接引用(设备域业务入口集中在 data-acquisition-device 与 v1 视图,设备实时面走 MQTT/设备服务)。契约见清单层 · device

device-model 设备型号

设备型号字典 CRUD(Web 型号选择器消费 list);契约见清单层

device-share 设备分享

分享记录面(驻留发起方租户):

  • shareList:查询当前租户发出的分享记录,每条带完整时间线(邀请/确认/解除/撤销时间)与状态——「我分享给了谁、是否已确认」。注意视角:收到的分享(受赠方视角)不经本端点,而是设备列表里 state=To be confirm share/confirm share 的分享投影。无分页参数(仅 sqlQueryLimit 上限钳制,缺省 100、钳 1..100000),是契约设计现状非缺口。
  • changeManage:修改分享记录的 deviceManage 标记——表示分享者用户名、用于展示与通知归属的非权威标记,不参与所有权或操作权限判定;是分享发出后的唯一可改字段端点。更新恒写该列:请求省略 deviceManage 字段会把标记清空为 NULL(「省略即清空」,只想保留原值必须回传原值);记录不存在(含他人租户的 ID)体现为 data=false 不报错,只更新 device_manage 一列、不影响 state 与时间线。

场景页:查询设备分享记录列表修改设备分享管理标记。契约见清单层 · device-share

device-type 设备类型

设备类型字典 CRUD(listTree 提供类型树);写操作(save/updateById/removeById*)成功后会发布设备类型树重建消息,HTTP 成功不提供树重建完成信号,使用方应重新读取树。listTree 的组装语义:服务端先按 sqlQueryLimit 截断取平面列表再按 parentDeviceTypeId 归组——父引用缺失(父节点被过滤/超出 limit)时该子树按根节点处理、排序不保证、limit 截断会使深层节点丢失父引用。场景领域页:设备与资产域 · device-type。契约见清单层

file-storage-server 文件存储服务器

文件存储服务器登记 CRUD;契约见清单层

file-storage-server-model 文件存储服务器型号

文件存储服务器型号字典 CRUD;契约见清单层

fingerprint-scanner 指纹扫描仪

指纹扫描仪台账 CRUD(场景页未覆盖;员工持指纹的关联在 basedata employee-fingerprint);契约见清单层

fingerprint-scanner-model 指纹扫描仪型号

指纹扫描仪型号字典 CRUD;契约见清单层

firmware-package 固件包

固件包管理面(上传/维护/查询)。业务动线:固件升级不是「推送」,而是 Web 发 MQTT retrieve 命令(device/{deviceNo}/iot/retrieve/v1items:["firmware"])让设备来取最新固件包信息——中心消费应答发往设备 topic,Web 看不到;每次触发还会顺带刷新该设备在线状态。文件本体经 /firmware-package{filePath} 静态路径直连下载(机构缺口页有该直连记录);从节点固件文件对账同步见运行时关联。写规则:同一 deviceModelId + version 重复时业务拒绝;仅 .bin/.img 的已完成 Tus 文件会被迁移,filePath 查不到已完成 Tus 信息时 Controller 不拒绝而继续保存原路径——调用方必须只提交上传成功回调给出的 URL;原始固件 md5 由浏览器在保存前计算,服务端不复算。

场景页:触发设备固件与文件上报(retrieve)。契约见清单层 · firmware-package

janus-server Janus 流媒体服务器

Janus 流媒体服务器登记 CRUD + listCache 缓存列表——直播/对讲媒体路由的基础设施表(信令转发与 会话路由在 device-service 侧,见其 business/runtime 页)。

目标节点解析级联(janus 信令下发时中心把 routeId 解析为物理出口 server/{janusNo}/to):routeId → 物理出口由中心解析(解析策略属中心内部实现,结果分钟级缓存;解析为空即静默丢弃)。本表是级联第一级的事实来源。契约见清单层 · janus-server

manufacturer 厂商

设备厂商字典 CRUD;契约见清单层

nfc-card NFC 卡

NFC 卡台账 CRUD(场景页未覆盖;员工持卡关联在 basedata employee-nfc-card,使用历史在 history/snapshot 模块);契约见清单层

nfc-card-model NFC 卡型号

NFC 卡型号字典 CRUD;契约见清单层

spirit-cam-firmware 随身摄像机固件

随身摄像机(SpiritCam)固件条目维护(save/updateById 两个写端点在册):写入最终生成普通固件包记录(读取走 firmware-package 端点),deviceModelId/version/md5/fileSize/binaryHeader 由服务端从固件二进制头派生,元数据固定写 scm 租户;已知实现风险——替换文件时 binaryHeader 保留旧值。场景领域页:设备与资产域 · spirit-cam-firmware。契约见清单层

talk-server 对讲服务器

对讲服务器登记 CRUD(对讲业务主体在 basedata talk-group,见基础数据(业务));契约见清单层

talk-server-data-acquisition-device 对讲服务器与采集设备关联

对讲服务器与采集设备的绑定关联表,CRUD;契约见清单层

talk-server-model 对讲服务器型号

对讲服务器型号字典 CRUD;契约见清单层

v1-general 通用接口(v1)

设备文件通道:面向中心文件存储区(服务器本地文件系统)的设备号视图,不是数据库查询:

  • listDeviceNos:枚举 files/device/ 下已有的设备号目录。与设备资产库无外键关系——只反映文件系统现有目录,无目录的设备不会出现;数据范围是文件系统全量目录,不受租户拦截器约束(跨租户可见性取决于目录写入侧)。结果有服务端 3 秒缓存(stringListCache),刚产生的目录最长 3 秒内不可见。
  • listFilesByDeviceNoAndType:按设备号 + 类型列出文件清单;[] 是成功空态(目录不存在或为空);直查文件系统无缓存窗口;路径段按「纯字母数字」白名单校验,非法段抛 Illegal path segment
  • uploadByDeviceNo:按设备号向存储区上传文件(设备文件备份链路的一环)。
  • getDeviceData/getServerTime:设备数据与服务器时间辅助读取。
  • 「让设备上传文件」不是本通道——那是 MQTT retrieve 命令(items:["upload/<category>"]),与固件触发同一命令族,见固件包节内点名。

场景页:枚举文件存储设备号按设备与类型列出设备文件。契约见清单层 · v1-general

v1-retail 零售接口(v1)

/v1/retail 门面的设备读取第二代视图(与第一代共享同一数据源,响应裁剪面向新客户端):

  • list:个人空间设备列表第二代读取端点(与第一代 listForPersonalSpace 共享同一 service 实现);读走 v1、写仍走第一代(绑定/解绑/分享生命周期端点无 v1 对应物)。
  • {dataAcquisitionDeviceId} 详情:列表页的同构详情端点(同一响应 DTO、同一套 options 懒装配),从列表点进单设备详情页时按需拉取。
  • share:V1 视图的分享发起增强入口——联系人三选一(用户名/邮箱/手机号自动识别)、分享数量上限校验,并返回解析后的目标用户名(extraData.targetUsername);受赠方确认/撤销/解除仍走第一代端点。识别规则:只对 targetUsername 做形态识别(含 @ → 邮箱;纯数字且 ≥7 位 → 手机号;其余 → 用户名),随后按用户名 → 邮箱 → 手机号顺序反查。分享上限(配置 device.share.limit,默认 10)只统计已确认分享——待确认不占名额、撤销/解除腾出的名额立即可复用;超限时 extraData 携带数值上限与未插值模板({{deviceShareLimit}} 占位符保留,供 App 本地化);上限校验在重复分享/投影守卫之前执行。完整错误清单(10 项,源码归纳 @ controller + 转调 service,按触发顺序;业务失败均为业务拒绝族,Bean Validation 走请求校验出口,判定口径见场景树错误响应差异):Incorrect email(邮箱反查无绑定)、Incorrect phone number(手机号反查无绑定)、At least one of targetUsername, targetEmail, and targetPhoneNumber is not empty(三字段全空)、Unable to share with oneself(目标即发起方自己)、The user corresponding to the shared username does not exist(用户名无对应用户)、Sharing users have no personal space(目标用户无 personal-space 租户)、Device share limit reached, maximum N shares allowed(已确认分享数达上限)、Device sharing already exists(同设备同目标已有活跃分享)、The data collection device does not existdeviceId 在发起方租户无有效投影)、The data collection device shared with the user already exists(目标租户已有该设备有效投影,重复投影守卫)。
  • options 懒装配语义list/详情共用):dataAcquisitionServer(全部设备,缓存读)、deviceShare(仅分享来的设备,一对一记录,缓存读)、deviceShareList(仅自有设备,一对多分享列表 + 联系人三字段)、firmwarePackage(仅型号非空设备,最新固件,缓存读)四块按 options 子串匹配开关;三路连接状态不在 options 之列、恒附加。cache 参数仅作用于 deviceShareList(真走缓存、假直查;无法识别的值一律按假),其余三块恒走缓存。V1 视图相对第一代裁剪:orgNo/orgName/treeOrgName/deviceModelCode/deviceModelName/deviceManage(扁平)/lastClickedDeviceLiveTime/dataAcquisitionServerId/dataAcquisitionServerNo 不在响应中,分享者信息改从 deviceShare.deviceManage 取。

场景页:查询个人空间设备列表(V1 视图)查询单设备详情(V1 视图)发起设备分享(V1 视图)。契约见清单层 · v1-retail

本模块相关的定时任务 / 消费者 / 缓存(全量表见 data-service 定时任务缓存device-service 消费者,此处只点名不复述):

  • 缓存 deviceIdCache(10 秒,采集设备信息短缓存防穿透)与 mqttClientIdCache(30 天远端,MQTT 客户端在线状态——listCache 组合的「在线状态」来源之一)。
  • 定时任务 FirmwareFileSyncService#syncFirmwareFiles(PT15M):从节点对固件文件周期对账同步——固件包的多节点一致性依赖此链。
  • device-service 消费者 DataAcquisitionServerIpSyncConsumer(采集服务器信息同步:按服务器遍历关联设备、比对在线状态并按需推送 DMS 载荷)与 NotifyToRefreshTheDeviceListConsumer(设备变更通知:经 MQTT 向相关用户推送设备列表刷新)。
  • 设备在线状态的每日对账(DeviceOnlineStatusSyncScheduling,device-service 任务,从 EMQX REST API 拉取在线客户端)收录在 data-service 定时任务表的 device-service 节,与本模块 dashboard/listCache 的在线口径相关。