Skip to content

设备 Device

设备是现场一台具体设备在平台里的镜像——一台 PLC、一个温控器、一块电表,在 DC3 里就对应一个 Device 。它绑定一个模板 Profile 决定"有哪些能力",绑定一个驱动 Driver 决定"怎么通信" ,运行时它的在线/离线由心跳租约维护。

设备回答的是"现场到底有哪一台机器"。它不是数据本身,也不是设备的类型定义:某型号温控器"应该有温度、湿度两个位号" 是模板说的事;车间里编号 TC-001 的那一台、此刻在线、刚上报温度 25.3℃,才是一个 Device

可以这样类比:模板像类(class),设备像它的实例(instance)。一个模板可被许多设备复用——100 台同型号温控器共用一个 Profile;但一个设备只能归属一个 Profile(多对多绑定已在模板改造中收敛为单归属)。设备能采哪些位号 、能下哪些指令、会报哪些事件,全部由它绑定的那个 Profile 决定。

设备的另一条绑定是驱动:Profile 说"这台设备有温度位号",但"用 Modbus 去哪个寄存器读这个温度"是驱动的事。 profileId 决定能力模型,driverId 决定通信通道,两者缺一不可。

关键字段

设备业务对象 DeviceBO(表 dc3_device),字段名与类型取自源码:

字段类型含义
deviceNameString设备名称(展示用,如"1号车间温控器")
deviceCodeString设备标识符
profileIdLong归属的模板 Profile,决定能力模型
driverIdLong归属的驱动 Driver,决定通信方式
deviceExtDeviceExtJSON 扩展,存放协议无关的自定义配置
enableFlagEnableFlagEnum启停标记,见下
tenantIdLong归属租户,多租户隔离

继承自 BaseBO 的通用字段:idremark(描述)、creatorId/creatorNameoperatorId/operatorNamecreateTime/ operateTime

profileId 是单值,不是集合

早期一个设备可绑定多个 Profile(Set<Long> profileIds)。模板改造后收敛为 Long profileId 单值:一个 Profile 可被多设备复用,但一个设备只归属一个 Profile。

启停标记

enableFlag0 enable 启用1 disable 停用

enableFlag 是配置态开关(这台设备是否纳入采集),与下文的运行态在线/离线是两回事:停用的设备不参与采集,启用的设备才会被驱动轮询并维护心跳租约。

与其它概念的关系

profileId · 一模板多设备1NdriverId · 一驱动多设备1Ndevice_id + point_id · 1:NdeviceId · 1:N运行态租约 1:1 · 不在 dc3_device模板 PROFILE · dc3_profileidPKprofileNameprofileCodeUKversion · enableFlagtenantIdFK驱动 DRIVER · dc3_driveridPKdriverName · driverCodeserviceName · serviceHostdriverTypeFlag · enableFlagtenantIdFK设备 DEVICE · dc3_deviceidPKdeviceName · deviceCodeprofileIdFKdriverIdFKdeviceExt (JSON)enableFlagtenantIdFK位号值 POINT_VALUE · dc3_point_valuedeviceIdFKpointIdFKrawValue · calValue · numValuecreateTime (时间戳)append-only 历史流水事件流水 EVENT_HISTORYrecordId (UUID)PKdeviceIdFKeventIdFKeventCode · paramValuesoccurTime实体状态 ENTITY_STATEentity_idFKentity_type_flag = 6 (设备)state 0 online · 1 offlineexpire_time (租约)lease_versionPKPK 主键FKFK 外键1:N 一对多1:1 租约(虚线)配置元数据运行态数据
  • 设备通过 profileId 取得自己的位号指令事件定义。
  • 设备运行时产生位号值device_id + point_id)和事件实例。
  • 设备通过 driverId 找到驱动完成实际读写。

在线状态与心跳租约

设备的"在线/离线"不是 dc3_device 上的字段,而是一份独立的运行态状态租约,由设备/驱动的超时管理机制维护,状态事实源是 dc3_entity_state 表(entity_type_flag = 6 表示设备)。机制是"心跳续租 + 超时维护":

接入前[驱动心跳 DeviceStateDTO] expire_time = now + timeout · lease_version ++[扫描器 tick] expire_time ≤ now → 批量判离线[驱动上报 maintain][维护结束 · 恢复心跳][健康检查失败][故障恢复 · 心跳续租][租约到期]1 offline无租约 / 已过期2 maintain维护中 · 暂不采集0 online心跳租约有效3 fault健康检查失败状态事实源: dc3_entity_stateentity_type_flag = 6 (设备)enableFlag 是配置态开关 ≠ 在线态心跳不写 dc3_device · 不污染元数据EntityStateStatus 状态码0 · online 在线1 · offline 离线2 · maintain 维护3 · fault 故障续租: 驱动按周期上报设备健康 → expire_time 顺延 · 超时由扫描器批量判定,不同设备的超时长短体现在各自 expire_time,而非扫描周期初始在线族维护故障离线心跳续租(实线)超时 / 恢复(虚线)
  • 续租:驱动按配置周期对设备做健康检查,上报 DeviceStateDTO,数据中心把 expire_time 顺延(now + timeout), lease_version 递增。
  • 超时:扫描器每隔固定 tick 唤醒,把 expire_time <= now() 仍处在线族的设备批量判为离线。不同设备的超时长短体现在各自的 expire_time 上,而非扫描周期上。

状态共四种(沿用设计稿 EntityStateStatus 契约):0 online、1 offline、2 maintain、3 fault。

在线状态查的是 dc3_entity_state,不是 dc3_device

dc3_device 是设备的配置元数据(名称、归属、扩展),不存高频心跳;当前在线/离线请查 dc3_entity_state。把心跳写进 dc3_device 会污染元数据表,这正是超时方案要避免的。

示例

车间里一台 Modbus 温控器接入 DC3:先选一个描述"温控器"这类设备的模板(含 temperaturehumidity 两个位号),再选一个 Modbus 驱动,创建一个设备 DeviceBO{ deviceName: "1号车间温控器", deviceCode: "TC-001", profileId: 1024, driverId: 2048, enableFlag: enable } 。启用后,Modbus 驱动按 Profile 的位号配置去读寄存器,产出位号值;同时每 15 秒上报一次设备健康,数据中心据此把 dc3_entity_state 里这台设备的 expire_time 续租 45 秒(租约时长);某次驱动连不上、心跳断了,扫描器在 expire_time 过期后把它判为 offline

延伸阅读

基于 AGPL-3.0 协议发布