领域模型
DeviceChain 使用少量可组合的概念来建模物理世界。其关键设计是使用带类型的关系图表达设备的上下文,而不是固定的分配记录。这使模型能够逐步接纳新的实体类型。
核心实体
- 设备(Device):建立连接并上报数据的对象。每台设备都是某种设备类型的实例。
- 设备类型(Device Type):分类与身份层。它保存一类设备的名称、外观(图标和颜色),以及用于分组和筛选的分类信息。一个设备类型最多引用一个设备配置文件。
- 设备配置文件(Device Profile):能力契约。它是独立且支持版本管理的资源(草稿 → 发布 → 回滚),拥有一类设备的指标、命令和检测规则定义。多个设备类型可以共享同一个配置文件,因此能力配置只需定义一次,即可复用。设备通过
device → type → profile查找其能力。没有配置文件的设备类型仍然有效:它对设备进行分类并控制显示,但不提供带类型的能力契约。 - 资产(Asset):设备监测的现实对象,按租户定义的资产类型分类。资产类型可以发布支持版本管理的属性模式,并据此验证资产属性。资产构成父子层级,每个资产最多有一个父级,不允许循环。
- 区域(Area):有名称的空间或组织位置,按区域类型分类。空间边界单独建模为地理围栏,而不是区域上的字段。
- 客户(Customer):组织所有者,按客户类型分类。
- 分组(Groups):统一的实体组收集同一类别的成员(设备、资产、区域或客户),类别在创建分组时选定。成员关系可以是静态的显式成员列表,也可以是动态的、针对成员属性保存的选择器,在读取时求值(参见分类维度与动态分组)。
设备、资产、区域、客户和分组采用相同的寻址方式:实体类型加上租户内稳定的令牌。统一地址让关系、分组和事件索引能够通用于这些实体。设备类型和设备配置文件不属于这种可寻址实体;它们是设备通过引用查找的配置。
关系
DeviceChain 不将设备绑定到唯一固定的 (customer, area, asset) 分配记录,而是用带类型、有方向的关系连接实体:
- 关系具有源、目标和关系类型。
- 关系类型携带
Tracked标志。
Tracked 标志至关重要。设备上报事件时,平台会将设备的每条被跟踪关系记录为该事件的锚点。锚点是事件锚点集合中的 (anchor_type, anchor_token) 条目:目标实体的类型及其在租户内的稳定令牌。
一台设备可以同时持有多条被跟踪关系,例如客户和区域和资产。读数随后可以按其中任何一个维度查询:“7 号楼的所有温度读数”和“Acme 客户的所有温度读数”都能找到它。锚点在写入时捕获,因此之后重新分配设备不会改变历史数据的归属。
分配用于组织,而非准入控制。 已有凭据但尚未分配的设备仍然可以上报遥测数据。其事件会解析为空锚点集合,而不是被丢弃。之后分配设备时,后续事件会获得客户、区域或资产锚点。参见管理设备分配。
属性与事件
DeviceChain 将当前状态与历史记录分开:
- 事件是设备上报的所有内容的只追加时序记录:测量、位置、警报、命令调用与响应,以及状态变更。它们保存在 TimescaleDB 超表中。
- 属性是实体当前的键值状态,分为三个作用域:
CLIENT:由设备上报。SERVER:仅供平台使用的元数据,设备不可见。SHARED:由平台设置,设备可以读取。这是远程配置和 OTA 目标的传递通道。
分类维度与动态分组
属性还可以作为分类维度,用于浏览和筛选实体。每个租户的分类维度注册表声明某个实体类别的哪些属性键作为分类维度,为控制台浏览界面提供筛选维度和值的输入提示。注册表只声明哪些键是分类维度;值仍作为属性保存在实体本身上。
动态分组将分类筛选条件转化为保存后自动更新的成员关系。其选择器是基于成员属性的布尔表达式,例如 attr["climate"] == "arid" && attr["country"] == "US"。它使用 CEL 编写,与检测引擎使用的表达式语言相同。
保存分组时,平台会验证选择器并限制其计算成本。随后在读取时,将表达式转换为使用索引的数据库查询来确定成员,绝不扫描每个实体。因此,动态分组始终反映当前属性状态,无需维护同步的物化缓存。静态分组则保存显式成员列表。
控制台中的**浏览(Browse)**页面根据分类维度组合选择器,实时预览匹配数量,并将其保存为动态分组。**分类维度(Facets)**页面管理注册表。
命令
设备配置文件声明设备接受的命令。发出的命令会持久化并跟踪完整生命周期,而不是发出后就不再关注。命令介绍了这两部分。
身份与凭据
设备具有稳定的身份,供其他对象引用;身份与用于认证的凭据分开保存。凭据可插拔,支持访问令牌和 MQTT-basic(用户名 + 密码)。因此,设备可以轮换凭据或同时持有多个凭据,而无需改变身份。
凭据中的密钥是只写的:注册凭据时提交,读取时绝不返回。这只适用于 MQTT-basic 密码。对于访问令牌,凭据 ID 本身就是持有凭据的证明,因此读取设备凭据需要 device:write 权限,而不是 device:read。参见设备凭据。
设备还可以带有可选的 externalId:客户自己的业务标识,例如 VIN、序列号、GS1 编码或资产标签。它既不同于内部身份,也不同于凭据。它具有以下特点:
- 不透明,没有格式限制;
- 存在时在租户内唯一;
- 绝不用于寻址或认证。
它用于查找与集成:将 DeviceChain 设备与其他系统用于同一物理对象的现有标识匹配起来。
事件
每个事件记录:
- 上报设备;
- 事件类型;
- 设备上报时间戳与平台接收时间戳;
- 用于幂等接入的可选外部关联 ID(
altId); - 上述已解析关系锚点的集合,即零条或多条
(anchor_type, anchor_token)记录。设备未分配时,集合为空。
事件类别包括测量、位置、警报、命令调用与响应,以及状态变更。
测量是自描述的。如果读数匹配设备配置文件上定义的指标,平台会将该指标的单位和数据类型直接写入持久化读数及实时最新已知状态投影。读取测量的消费者无需再次查询配置文件,即可获取其语义(22.4 °C,类型为 DOUBLE)。