Copyright © 2017-2025 World Wide Web Consortium. W3C® liability, trademark and permissive document license rules apply.
本文档描述了 Web of Things(WoT)物 描述(TD)2.0 版的一个正式信息模型和 通用表示。物描述描述了物的元数据和接口,其中物是对物理 或虚拟实体的一种抽象,这些实体向 Web of Things 提供交互 并参与其中。物描述提供了一组基于小型词汇表的交互, 使集成各种设备以及让各种 应用实现互操作成为可能。物描述默认 编码为一种 JSON 格式,该格式也允许 JSON-LD 处理。后者提供了一个强大的基础,用于以机器可理解的 方式表示关于物的知识。物描述实例可以由物自身托管,或在物存在 资源限制(例如,有限的内存空间)时,或在 Web of Things 兼容的旧式设备被改造为具有物 描述时,由外部托管。此外,本文档引入了物 模型,它允许作者仅描述物联网(IoT)实体的模型或类。 物模型可被视为物描述实例的模板, 但具有较少的约束,例如对特定 通信元数据没有要求或要求很少。
本规范延续了 [WOT-THING-DESCRIPTION11] 的工作,但不保证向后兼容。如果不 向后兼容,将为实现者提供具体指南,以迁移到 新版本。
本节描述本文档在 发布时的状态。当前 W3C 出版物以及 本技术报告最新修订版的列表,可在 W3C 标准和草案 索引中找到。
本文档由 Web of Things Working Group 作为第一份公开工作草案发布,并使用推荐标准 轨道。
作为第一份公开工作草案发布,并不意味着 得到 W3C 及其成员的认可。
这是一份草案文档,可能随时被更新、替换或 废弃。除作为进行中的工作外,不宜 引用本文档。
本文档由一个按照 W3C 专利政策运行的小组生成。 W3C 维护一份 与该小组可交付成果 相关的任何专利披露的公开列表;该页面还包含 披露专利的说明。实际知晓某项专利的个人, 若该个人认为该专利包含必要 权利要求,则必须按照 W3C 专利政策第 6 节 披露该信息。
本文档受2025 年 8 月 18 日 W3C 流程 文档管辖。
本节为非规范性内容。
WoT 物描述(TD)是 W3C Web of Things(WoT)中的核心构建块,并可被视为一个 物的入口点(非常 类似于一个 Web 站点的 index.html)。一个 TD 实例有五个主要 组成部分:关于物自身的文本元数据,一组交互可供性,用于 指示该物如何 被使用;用于实现机器可理解性的、与物交换的数据的 模式;用于提供必须为交互使用的安全 机制相关元数据的安全 定义;以及最后的 Web 链接, 用于表达与 Web 上其他物或文档的任何正式或非正式关系。
W3C WoT 的
交互模型
定义了三类交互
可供性:属性(PropertyAffordance
类)可用于感知和控制参数,
例如获取当前值或设置操作
状态。动作(ActionAffordance 类)
对物理(因此耗时的)
过程调用进行建模,但也可用于抽象现有平台中类似 RPC 的调用。
事件(EventAffordance 类)
用于通信的推送模型,其中
通知、离散事件或值流被
异步发送给接收者。详情请参见 [wot-architecture11]。
一般而言,TD 为不同的
协议绑定
提供元数据,这些绑定由 URI 方案 [RFC3986]
标识(例如 http、coap 等
[IANA-URI-SCHEMES]),
基于媒体类型 [RFC2046]
的内容类型(例如 application/json、
application/xml、application/cbor、
application/exi 等 [IANA-MEDIA-TYPES]),以及安全
机制(用于认证、授权、
保密性等)。TD 实例的序列化
基于 JSON [RFC8259],
其中 JSON 名称引用 TD 词汇表中的术语,如
本规范文档所定义。此外,TD 的 JSON
序列化遵循 JSON-LD 1.1
[JSON-LD11] 的语法,以
支持扩展和丰富的语义处理。
示例 1 展示了一个 TD 实例,并通过描述一个标题为 MyLampThing 的灯物, 用属性、动作和事件说明了交互 模型。
从这个 TD 示例中,我们知道存在一个标题为
status 的属性可供性。
此外,示例还提供了信息,以
表明该属性可通过 HTTP 协议的(安全
形式)使用 GET 方法在 URI
https://mylamp.example.com/status 处访问(在
forms 结构中通过
href 成员声明),并将返回一个基于字符串的
状态值。GET 方法的使用并未
显式声明,但它是本文档定义的
默认假设之一。
以类似方式,指定了一个动作
可供性,用于在
https://mylamp.example.com/toggle 资源上使用
POST 方法切换开关状态,
其中 POST 同样是调用
动作时的默认假设。
事件可供性
启用了一种机制,使消息能够由一个
物异步发送。
在此处,可以通过在
https://mylamp.example.com/oh 上使用 HTTP 及其长轮询子协议,
获得对灯可能发生过热事件的
通知订阅。
此示例还指定了 basic
安全方案,需要用户名和密码才能
访问。请注意,安全方案首先在
securityDefinitions 中命名,然后通过
在 security 节中指定该名称来激活。结合
HTTP 协议的使用,此示例
演示了 HTTP Basic Authentication 的使用。
在顶层指定至少一个安全方案是
强制性的,并为每个资源给出默认访问要求。
不过,也可以按 form 指定安全方案,
在 form 层级给出的配置会覆盖
在 Thing 层级给出的配置,从而允许
指定细粒度访问控制。也可以使用
特殊的 nosec 安全方案来表示
未使用任何访问控制机制。后文将提供
更多示例。
物描述提供了在某个命名空间中添加
上下文定义的可能性。该机制可用于向
物描述实例的内容集成附加语义,前提是
形式化知识,例如某个特定应用领域的
逻辑规则,可以在给定命名空间下找到。
上下文信息还可以帮助指定
forms 字段中声明的底层通信
协议的某些配置和行为。示例 2 通过在
@context 中引入第二个定义来声明前缀
saref 指向 SAREF,
即 Smart Appliance Reference Ontology [SMARTM2M],
从而扩展示例 1 中的 TD 样例。
这个 IoT 本体包含被解释为语义
标签的术语,这些术语可被设置为 @type
字段的值,用于赋予物及其交互
可供性以语义。在下面的示例中,物被标注为
saref:LightSwitch,status
属性被标注
为 saref:OnOffState,而
toggle 动作
被标注为 saref:ToggleCommand。
某些
@context 内部的声明机制由 JSON-LD 指定。TD 实例
符合该规范的 1.1 版
[json-ld11]。
因此,TD 实例也可以作为 RDF 文档进行处理
(有关语义处理的详情,请参阅
附录 D. JSON-LD 上下文
用法以及命名空间 IRI 下的文档,
例如 https://www.w3.org/2019/wot/td)。
物 描述的主要意图之一,是向消费者提供与物成功交互所 必需的全部细节。在某些 IoT 应用 场景中,一个包含完整细节的物描述, 例如带有通信元数据的描述,并非必要(例如,IoT 生态系统可能会隐式地单独处理通信), 或者可能尚不可用,因为新实体尚未 部署(例如,IP 地址尚未知晓)。有时,也 需要一种类定义,用于强制规定所有已创建 实例都应具备的能力定义(例如,新设备的大规模生产)。
为了解决上述场景或 其他场景,可以使用物 模型,它主要在物的 属性、动作和/或事件内提供数据模型 定义,并有可能被用作创建物描述 实例的模板。下面给出一个样例物模型, 它可被视为示例 1中物 描述实例的模型。
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"title": "Lamp Thing Model",
"properties": {
"status": {
"description": "current status of the lamp (on|off)",
"type": "string",
"readOnly": true
}
},
"actions": {
"toggle": {
"description": "Turn the lamp on or off"
}
},
"events": {
"overheating": {
"description": "Lamp reaches a critical temperature (overheating)",
"data": {"type": "string"}
}
}
}
物
模型定义由 "@type":
"tm:ThingModel" 标识。如示例所示,由于缺少
通信和安全元数据,它并不
提供关于单个物实例的细节。本规范
给出了一种机制,用于从此类物模型定义派生有效的物
描述实例。
此外,还指定了其他设计概念,包括
如何覆盖、扩展和复用现有物模型
定义。
除标记为非规范性的章节外,本规范中的所有编写 指南、图表、示例和注释均为非规范性内容。 本规范中的其他所有内容均为 规范性内容。
本文档中的关键词 MAY、MUST、MUST NOT、 RECOMMENDED、SHOULD 和 SHOULD NOT 在且仅在以此处所示的全大写形式出现时, 应按 BCP 14 [RFC2119] [RFC8174] 中的描述进行解释。
如果物描述实例遵循 5. TD 信息模型 和 6. TD 表示格式 中关于物 描述序列化的规范性陈述,则该实例符合 本规范。
附录 B. 用于 TD 实例验证的 JSON Schema 中提供了一个用于验证物描述实例的 JSON Schema [JSON-SCHEMA]。
本节为非规范性内容。
基本的 WoT 术语,例如 物、消费者、生产者、物 描述(TD)、部分 TD、 物 模型(TM)、交互模型、交互 可供性、IoT 平台、属性、动作、事件、数据 模式、内容类型、协议 绑定、服务体、词汇表、术语、词汇表 术语、WoT 接口,以及 WoT 运行时,定义于 WoT 架构规范 [wot-architecture11] 的第 3 节。
此外,本规范引入以下 定义:
@type
成员,以及通过使用带冒号
(:)的字符串前缀来实现。
Thing 类的实例关系约束的物描述。
为此,TD 处理器
可以计算填入物描述的形式,
其中所有可能的默认值均被
赋值。TD
处理器通常是WoT 运行时的一个子系统。
TD 处理器的实现可以是 TD 生产者(能够序列化
为 TD 文档),也可以是 TD 消费者(能够从
TD 文档反序列化),或二者兼具。
@context 等术语,是物层级;
forms 定义在可供性层级内;
type、maximum 定义在
数据模式层级内;而 href 定义在
Forms 层级内。即使未定义,也可以使用其他层级,
例如 Links 层级。
href
以 http:// 或
https:// 开头。
这些定义将在5.2 预备定义中进一步展开。
本规范5. TD 信息模型 中定义的TD 信息模型版本 由以下 IRI 标识:
https://www.w3.org/ns/wot-next/td
该 IRI [RFC3987], 同时也是一个 URI [RFC3986], 可被解引用以获取一个 JSON-LD 上下文文件 [json-ld11], 使TD 文档中的紧凑字符串能够展开为 基于完整 IRI 的词汇表 术语。不过,仅当把基于 JSON 的TD 文档转换为 RDF 时 才需要这种处理,而这是TD 处理器 实现的一项可选特性。
注意,该命名空间在规范达到推荐标准状态之前是临时的。 到那时,将分配一个永久命名空间。所有使用该 临时命名空间的文档都指向该规范 git 仓库的主分支,因此并不稳定。
在本规范中,词汇表术语总是 以其紧凑形式呈现。其展开形式可在它们所属 词汇表的命名空间 IRI 下访问。这些 命名空间遵循5.3 类 定义的结构。TD 信息模型中使用的每个 词汇表都有自己的命名空间 IRI,如下所示:
| 词汇表 | 命名空间 IRI |
|---|---|
| 核心 |
https://www.w3.org/ns/wot-next/td-ontology
|
| 数据模式 |
https://www.w3.org/ns/wot-next/json-schema-ontology
|
| 安全 |
https://www.w3.org/ns/wot-next/security-ontology
|
| 超媒体控件 |
https://www.w3.org/ns/wot-next/security-ontologyy
|
为物模型定义额外使用的所有词汇表 具有以下命名空间 IRI:
| 词汇表 | 命名空间 IRI |
|---|---|
| 物模型 |
https://www.w3.org/ns/wot-next/tm-ontology
|
词汇表彼此独立。
它们可以在其他 W3C
规范中复用和扩展。对某个
词汇表设计的每一次破坏性变更,都需要
分配一个新的基于年份的命名空间 URI。请注意,为了
维护TD
信息模型的一般一致性,
相关的 JSON-LD 上下文文件会进行版本化,使得每个
版本都有自己的 URI(v1、v1.1、
v2、……),以便同时标识非破坏性变更,
特别是新增术语。
因为某个命名空间 IRI 下的词汇表 只能发生非破坏性变更,所以其内容可以被 安全地缓存或嵌入到应用中。在命名空间 IRI 下 暴露相对静态内容的一个优点,是可以 优化受限设备之间交换消息的负载大小。 它还避免了设备从私有网络访问公开可用 词汇表所导致的任何隐私泄露(另见12. 隐私考量)。
本节介绍TD 信息模型。TD 信息模型 作为物描述及其序列化处理的概念基础; 序列化将在6. TD 表示 格式中单独描述。
这些词汇表中的每一个本质上都是一组 术语, 可用于构建数据结构,并被解释为传统 面向对象意义上的对象。对象是类的 实例,并具有属性。在 W3C WoT 的语境中,它们 表示物及其 交互 可供性。对象的形式化定义见 5.2 预备定义。随后在 5.3 类 定义中介绍TD 信息模型的主要元素。 当存在默认 值时,TD 中可以省略某些对象属性。 默认值列表见5.4 默认值定义。
下面显示的 UML 图给出了
TD
信息模型的概述。
它将所有类表示为表,并将从类
Thing 开始的类之间存在的关联表示为有向
箭头。为了可读性,该图被拆分为四个部分,
每个部分对应四个基础词汇表之一。
为了提供一个既能被基于树的文档上的简单规则 (即原始 JSON 处理)轻松处理,又能被丰富的 语义 Web 工具(即 JSON-LD 处理)轻松处理的模型,本文档定义以下形式化 预备内容,以相应地构造TD 信息模型。
本节中的所有定义都涉及集合, 直观地说,集合是元素的集合,这些元素本身也可以 是集合。所有任意复杂的数据结构 都可以用集合来定义。特别地, 对象是一种 递归定义如下的数据结构:
虽然该定义并不阻止对象包含多个 具有相同名称的名称-值对,但本规范通常不 考虑这种情况。元素只以数字作为名称的 对象称为数组。类似地,元素只 以术语(且这些术语不属于任何 词汇表)作为名称的 对象 称为映射。出现在某个 映射中名称-值对里的所有 名称,都被假定在该映射的作用域内是唯一的。
此外,对象 可以是某个类的实例。由 词汇表术语表示的类, 首先由一组称为 签名的词汇表术语定义。 签名为空的 类称为 简单类型。
类的签名允许构造两个
进一步定义类的函数:赋值函数和类型函数。
类的
赋值函数
接受该类的签名中的一个
词汇表术语作为输入,并返回
true 或 false 作为输出。
直观地说,赋值函数
指示在实例化该类时,签名中的某个元素是强制的还是
可选的。类的
类型函数也
接受该类的签名中的一个
词汇表术语作为输入,并返回
另一个类作为
输出。这些函数是部分函数:其定义域
限于所定义类的签名。
基于这两个函数,可以为由一个 对象和一个类组成的对定义 实例关系。 该关系被定义为需要满足的约束。也就是说, 如果同时满足以下两个约束,则一个对象是某个 类的实例:
true 的每一个术语,
该对象都包含一个以该
词汇表术语为名称的名称-值
对。
根据上述定义,一个对象将成为
每个简单
类型的实例,而不考虑其结构。因此,
为简单
类型引入了实例关系的另一个
定义:如果一个对象是具有给定词法形式的
术语
(例如,boolean 类型的
true、false,unsignedInt 类型的
1、2、
3、……,等等),则它是一个
简单类型的实例。
此外,还可以从通用的映射和数组结构派生出额外的 类,称为参数化 类。如果一个对象是某个 类的 映射, 即参数化为某个类的 映射类型的实例, 那么它就是一个映射,并且 它所包含的所有名称-值对中的值 都是该类的实例。对于 数组也是如此。
最后,如果前一个类的 每个实例也是后一个类的实例, 则前一个类是后一个类的 子类。
给定以上所有定义,TD 信息模型应被
理解为一组类定义,其中包括
类名称
(一个词汇表术语)、
签名(一组
词汇表术语)、
赋值函数,
以及类型
函数。这些类
定义以表格形式提供于5.3 类定义中。对于每个表,
赋值列中的值“mandatory”(相应地,“optional”)
表示赋值函数
针对对应的词汇表术语返回
true(相应地,false)。
按照约定,简单类型由
以小写字母开头的名称表示。TD 信息模型
引用了 XML Schema [XMLSCHEMA11-2-20120405]
中定义的以下
简单 类型:
string、anyURI、
dateTime、integer、
unsignedInt、double 和
boolean。它们的定义(即其
词法形式的规范)不属于TD
信息模型的范围。
此外,TD
信息模型定义了一个
作用于词汇表术语对的全局函数。
该函数接受一个类名称
和另一个词汇表术语作为输入,并返回一个
对象。
如果返回的对象
不同于 null,它表示输入
类的实例中输入
词汇表术语上某个赋值的
默认值。该函数允许
放宽上述关于赋值函数的约束:
如果一个对象
包含所有强制赋值,或者缺失的赋值存在
默认值,
则它是一个类的实例。
所有默认值都列于
5.4 默认值
定义的表中。在5.3 类定义的每个表中,如果
TD
信息
模型中对应的类和词汇表术语组合可用
默认值,则赋值
列包含值“with default”。
此处引入的形式化并不考虑作为抽象数据结构的 对象与物理世界对象(例如 物)之间可能存在的关系。然而,已注意到 可以将TD 信息模型中涉及的所有词汇表术语 重新解释为 RDF 资源,从而将它们集成到一个更大的 物理世界模型(本体)中。有关语义处理的详情, 请参阅 D. JSON-LD 上下文用法以及 命名空间 IRI 下的 文档,例如 https://www.w3.org/2019/wot/td。
一个 TD 处理器MUST 满足 类 实例化约束, 这些约束适用于类 中定义于 5.3.1 核心词汇 定义、5.3.2 数据模式 词汇定义、5.3.3 安全词汇 定义,以及 5.3.4 超媒体控件 词汇定义中的所有类。
尤其需要注意,所有词汇表术语和值 都区分大小写。信息模型的序列化 也是如此(第 6. TD 表示格式节)。
物理实体或虚拟实体的一种抽象,其 元数据和接口由 WoT 物 描述来描述;其中虚拟实体是 一个或多个物的组合。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
@context |
JSON-LD 关键字,用于定义称为术语的 简写名称,这些名称会在整个 TD 文档中使用。 | 强制 |
anyURI 或 数组
|
@type |
JSON-LD 关键字,用于用语义标签 (或类型)标记对象。 | 可选 |
string 或由 数组 组成的
string
|
id |
以 URI 形式给出的物标识符 [RFC3986] (例如稳定 URI、临时且可变的 URI、带有 本地 IP 地址的 URI、URN 等)。 | 可选 |
anyURI
|
title |
基于默认语言提供人类可读标题 (例如显示用于 UI 表示的文本)。 | 强制 |
string
|
titles |
提供多语言人类可读标题 (例如以不同语言显示用于 UI 表示的文本)。 另见 MultiLanguage。 | 可选 |
映射,其值为 MultiLanguage
|
description |
基于默认语言提供附加(人类可读) 信息。 | 可选 |
string
|
descriptions |
可用于支持不同语言中的(人类可读) 信息。另见 MultiLanguage。 | 可选 |
映射,其值为 MultiLanguage
|
version |
提供版本信息。 | 可选 |
VersionInfo
|
created |
提供 TD 实例创建时间的信息。 | 可选 |
dateTime
|
modified |
提供 TD 实例最后修改时间的信息。 | 可选 |
dateTime
|
support |
以 URI 方案形式提供关于 TD 维护者的信息
(例如 mailto
[RFC6068]、
tel [RFC3966]、
https [RFC9112])。
|
可选 |
anyURI
|
base |
定义基础 URI,用于整个 TD 文档中的所有
相对 URI 引用。在 TD 实例中,所有相对 URI
都使用 [RFC3986]
中定义的算法,相对于基础 URI 解析。base 不影响 @context 中使用的 URI,
也不影响在对 TD 实例应用语义处理时相关的
Linked Data [LINKED-DATA]
图中使用的 IRI。
|
可选 |
anyURI
|
properties |
物的所有基于属性的交互 可供性。 | 可选 |
映射,其值为 PropertyAffordance
|
actions |
物的所有基于动作的交互 可供性。 | 可选 |
映射,其值为 ActionAffordance
|
events |
物的所有基于事件的交互 可供性。 | 可选 |
映射,其值为 EventAffordance
|
links |
提供指向任意资源的 Web 链接,这些资源 与指定的物描述相关。 | 可选 |
数组,其元素为 Link
|
forms |
描述如何执行操作的一组 form 超媒体控件。 Forms 是协议绑定的序列化。物 层级 forms 用于描述一组交互可供性的端点。 | 可选 |
数组,其元素为 Form
|
security |
一组安全定义名称,从
securityDefinitions 中定义的名称中选取。
要访问资源,必须全部满足这些安全定义。
|
强制 |
string 或由 数组 组成的
string
|
securityDefinitions |
一组具名安全配置
(仅为定义)。除非名称被用于
security 名称-值对中,否则并不会实际应用。
|
强制 |
映射,其值为 SecurityScheme
|
profile |
指示此物描述及相应的 物实现所遵循的 WoT Profile 机制。 | 可选 |
anyURI 或由 数组 组成的
anyURI
|
schemaDefinitions |
一组具名数据模式。用于
AdditionalExpectedResponse
对象内的 schema 名称-值对。
|
可选 |
映射,其值为 DataSchema
|
uriVariables |
按照 [RFC6570] 定义 URI 模板变量,
其集合基于 DataSchema 声明。物
层级
uriVariables 可用于物
层级
forms 或交互可供性中。
各个变量的 DataSchema 不能是
ObjectSchema 或 ArraySchema,因为在执行操作时,
每个变量都需要在 href 内被序列化为字符串。
如果同一个变量同时在物层级
uriVariables 和交互
可供性层级中声明,则交互可供性
层级变量优先。
|
可选 |
映射,其值为 DataSchema
|
以下关于
@context URL 规则的列表项将经历重大
变更。
对于 @context,为
物描述
实例定义了以下规则:
@context 名称-值对 MUST 包含 anyURI
https://www.w3.org/2022/wot/td/v1.1,
以便将该文档标识为 TD 1.1,从而允许
消费者使用新
引入的术语。https://www.w3.org/2019/wot/td/v1
MUST 是第一项,而
https://www.w3.org/2022/wot/td/v1.1
MUST 是第二
项。@context 是一个数组时,anyURI
https://www.w3.org/2022/wot/td/v1.1
MAY 后面可以
以任意顺序跟随类型为
anyURI 或类型为映射的元素,同时
RECOMMENDED 只包含
一个映射,
其中包含 @context 数组中的所有名称-值对。@context 数组中时,MAY 包含名称-值
对,其中
值是类型为 anyURI 的命名空间标识符,
名称是术语或表示该
命名空间的前缀。@context 数组中的一个映射
SHOULD 包含一个名称-值对,
该名称-值对定义物描述的默认语言,
其中名称是术语 @language,
值是 [BCP47]
所定义的格式良好的语言标签
(例如 en、de-AT、
gsw-CH、zh-Hans、
zh-Hant-HK、
sl-nedis)。为了确定物描述 和物 模型实例中所有人类可读文本的基本方向, 本规范建议在没有内置机制可用于关联基本方向 元数据时,遵循 [STRING-META] 关于 字符串特定方向信息的指南。
TD 处理器在处理双向文本时应注意某些特殊情况。 TD 处理器 SHOULD 在向用户呈现字符串时注意使用 bidi 隔离, 尤其是在嵌入周围文本时(例如 Web 用户 界面)。混合方向文本可以出现在任何 语言中,即使该语言已被正确 标识。
TD 生产者 SHOULD 尝试以一种能被 朴素用户代理成功显示的方式提供混合方向 字符串。例如,如果一个 RTL 字符串 以 LTR 片段开头(例如数字或拉丁文字中的品牌或 商品名称),则在字符串开头包含一个 RLM 字符, 或者用 bidi 控制符包裹相反方向的片段, 可以帮助正确显示。
Strings on the Web: Language and Direction Metadata [string-meta] 提供了一些指导,并说明了使用双向文本时的 若干陷阱。
除了在 properties、
actions 和 events 映射中
显式提供的交互
可供性之外,一个物还可以
提供元交互,这些元交互由其可选
forms 数组中的
Form 实例表示。当一个物实例的
forms 数组包含
Form 实例时,它 MUST 包含 op 成员,
且赋给名称 op 的字符串值,
无论是直接给出还是在数组中给出,MUST 是以下
操作类型之一:readallproperties、
writeallproperties、
readmultipleproperties、
writemultipleproperties、
observeallproperties、
unobserveallproperties、
queryallactions、
subscribeallevents 或
unsubscribeallevents。(参见示例,
了解在物实例中使用 form 的情况。)
每个属性元交互的数据模式通过组合每个
PropertyAffordance 实例的数据模式来构造,
并放入单个 ObjectSchema 实例中;其中
ObjectSchema 实例的 properties
映射包含每个
PropertyAffordances 的数据模式,这些
数据模式由对应
PropertyAffordances 实例的名称标识。
如果未另行指定(例如通过
TD 上下文
扩展),
readmultipleproperties 操作的请求数据是一个
数组,其中包含
预期的 PropertyAffordances 实例
名称,并会被序列化为
Form 实例指定的内容类型。
物的元数据,向 消费者展示可能的选择,从而 提示消费者如何与 物交互。潜在可供性有许多类型, 但 W3C WoT 定义了三类交互可供性: 属性、动作和事件。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
@type |
JSON-LD 关键字,用于用语义标签 (或类型)标记对象。 | 可选 |
string 或由 数组 组成的
string
|
title |
基于默认语言提供人类可读标题 (例如显示用于 UI 表示的文本)。 | 可选 |
string
|
titles |
提供多语言人类可读标题 (例如以不同语言显示用于 UI 表示的文本)。 另见 MultiLanguage。 | 可选 |
映射,其值为 MultiLanguage
|
description |
基于默认语言提供附加(人类可读) 信息。 | 可选 |
string
|
descriptions |
可用于支持不同语言中的(人类可读) 信息。另见 MultiLanguage。 | 可选 |
映射,其值为 MultiLanguage
|
forms |
描述如何执行操作的一组 form 超媒体控件。 Forms 是协议绑定的序列化。该数组 不能为空。 | 强制 |
数组,其元素为 Form
|
uriVariables |
按照 [RFC6570] 定义 URI 模板变量,
其集合基于 DataSchema 声明。各个
变量的 DataSchema 不能是 ObjectSchema 或
ArraySchema,因为执行操作时,每个变量都需要
在 href 内被序列化为字符串。
如果同一变量同时在物层级
uriVariables和交互可供性层级中声明,
则交互可供性层级变量优先。
|
可选 |
映射,其值为 DataSchema
|
InteractionAffordance 类具有以下
子类:
一种暴露物状态的交互可供性。 该状态随后可以被检索(读取)和/或 更新(写入)。物也可以选择通过在发生 变化后推送新状态,使属性可被观察。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
observable |
一个提示,用于指示托管
物的服务体和中介是否应提供一个
支持该属性的 observeproperty 和
unobserveproperty 操作的
协议绑定。
|
有默认值 |
boolean
|
Property 实例也是
DataSchema 类的实例。因此,它可以包含
type、unit、
readOnly 和 writeOnly
成员,以及其他成员。
PropertyAffordance 是
InteractionAffordance 类和
DataSchema 类的子类。
当 Form
实例位于 PropertyAffordance
实例内部时,赋给 op 的值
MUST 是
readproperty、writeproperty、
observeproperty、
unobserveproperty 之一,或是包含这些术语组合的
数组。
良好实践是,每个
observeproperty 都有一个对应的
unobserveproperty,除非协议
支持隐式取消订阅机制(例如用于检测连接丢失的
heartbeat)。
一种交互可供性,允许调用物的 某个函数,该函数会操纵状态(例如打开或关闭灯) 或触发物上的一个过程(例如随时间调暗灯)。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
input |
用于定义动作的输入数据模式。 | 可选 |
DataSchema
|
output |
用于定义动作的输出数据模式。 | 可选 |
DataSchema
|
safe |
标示动作是否安全(=true)。 用于标示调用动作时没有内部状态 (参见资源状态)发生改变。在这种情况下, 响应可以被缓存,例如。 | 有默认值 |
boolean
|
idempotent |
指示动作是否幂等 (=true)。说明该动作在存在相同输入的情况下, 是否可以被重复调用并得到相同结果。 | 有默认值 |
boolean
|
synchronous |
指示该动作是否同步 (=true)。同步动作意味着动作的 响应包含关于动作结果的全部信息, 且不需要再查询动作状态。 缺少该关键字意味着不能对该动作的 同步性作出声明。 | 可选 |
boolean
|
ActionAffordance 是
InteractionAffordance 类的子类。
当 Form
实例位于 ActionAffordance
实例内部时,赋给 op 的值 MUST 是
invokeaction、
queryaction、cancelaction 之一,或是
包含这些术语组合的
数组。
一种交互可供性,用于描述一个事件 源,它会向 消费者异步推送事件数据(例如过热 警报)。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
subscription |
定义订阅时需要传递的数据, 例如用于设置 Webhooks 的过滤器或消息格式。 | 可选 |
DataSchema
|
data |
定义由物推送的事件实例 消息的数据模式。 | 可选 |
DataSchema
|
dataResponse |
定义消费者响应数据消息时发送的 事件响应消息的数据模式。 | 可选 |
DataSchema
|
cancellation |
定义取消订阅时需要传递的任何数据, 例如用于移除 Webhook 的特定消息。 | 可选 |
DataSchema
|
EventAffordance 是
InteractionAffordance 类的子类。
当 Form
实例位于 EventAffordance
实例内部时,赋给 op 的值
MUST 是
subscribeevent、
unsubscribeevent,或在一个
数组中同时包含这两个术语。
良好实践是,每个
subscribeevent 都有一个对应的
unsubscribeevent,除非协议
支持隐式取消订阅机制(例如用于检测连接丢失的
heartbeat)。
EventAffordances 与可观察的
PropertyAffordances 类似,因为物自身会
将状态变化告知感兴趣的消费者。
但是,EventAffordances 的一个主要区别是,
相关资源的每一次变化并不一定需要
触发发出事件消息,例如数值的临界
阈值。此外,
EventAffordances 允许通过定义
subscription、dataResponse 和
cancellation DataSchema 定义来实现更复杂的订阅和
取消订阅机制。不过,并非所有
协议都可能支持这些更高级的机制,
因此在某些场景中,事件可能与可观察的
PropertyAffordances 非常相似。在这些
情况下,应根据底层资源的语义来
在属性和事件之间选择用哪一个来建模
可供性;例如,如果该可供性的状态也预期
由消费者读取或写入,那么属性很可能是
合适的选择。
物的元数据,用于提供关于 TD 文档的版本信息。 如有需要,可通过 TD 上下文扩展机制扩展附加版本信息,例如固件和硬件版本 (TD 命名空间之外的术语定义)。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
instance |
提供此 TD 的版本指示符。 | 强制 |
string
|
model |
提供底层 TM 的版本指示符。 | 可选 |
string
|
建议
VersionInfo 类中的
instances 和 model 的值遵循语义化
版本模式,其中由点分隔的三个数字序列
分别表示主版本、次版本和补丁版本。
详情见
[SEMVER]。
一个映射, 提供一组以 [BCP47] 中描述的 语言标签标识的不同语言的人类可读文本。请参阅 6.3.2 人类可读 元数据,了解该容器在 物描述实例中的示例用法。
MultiLanguage 映射的每个名称
MUST 是
[BCP47] 中定义的语言标签。
MultiLanguage 映射的每个值
MUST 为
string 类型。
数据模式是一种用于表示数据格式中所含数据的 抽象记法。
数据模式词汇定义反映了 JSON Schema [JSON-SCHEMA] 所定义术语的一个非常常见的子集。 用于 JSON Schema draft 7 的 JSON Schema [JSON-SCHEMA] 处理器可以消费数据模式。需要注意的是, 物描述实例中的数据模式定义并不限于 这个已定义子集,并且可以通过 TD 上下文扩展 使用 JSON Schema 中发现的附加术语, 如 7. TD 上下文扩展所述;否则这些 术语会被TD 处理器 在语义上忽略(有关语义处理的详情,请参阅 D. JSON-LD 上下文用法 以及命名空间 IRI 下的 文档,例如 https://www.w3.org/2019/wot/td)。
在 TD 中,具体数据格式通过 Forms
(见 5.3.4.2 Form)
使用内容
类型来指定。当 Form 实例中的内容类型值为
application/json 时,数据模式
可以由 JSON Schema 处理器直接处理。
否则,Web of Things(WoT)绑定注册表
[WOT-BINDING-REGISTRY]
中的条目定义了从数据模式到其他
内容类型(如 XML [xml])的可用映射。
如果 Form 实例中的内容类型不是
application/json,且没有为该内容类型
定义映射,那么为该内容类型指定数据模式并
没有意义。
下表包含 MAY 使用数据模式来描述其负载 结构的内容类型。
| 格式 | 内容类型 |
|---|---|
| JSON/CBOR | application/jsonapplication/ld+jsonapplication/senml+jsonapplication/cborapplication/senml+cbor |
| XML/EXI | application/xmlapplication/senml+xmlapplication/exiapplication/senml-exi |
描述所用数据格式的元数据。它可用于 验证。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
@type |
JSON-LD 关键字,用于用语义标签 (或类型)标记对象 | 可选 |
string 或由 数组 组成的
string
|
title |
基于默认语言提供人类可读标题 (例如显示用于 UI 表示的文本)。 | 可选 |
string
|
titles |
提供多语言人类可读标题 (例如以不同语言显示用于 UI 表示的文本)。 另见 MultiLanguage。 | 可选 |
映射,其值为 MultiLanguage
|
description |
基于默认语言提供附加(人类可读) 信息。 | 可选 |
string
|
descriptions |
可用于支持不同语言中的(人类可读) 信息。另见 MultiLanguage。 | 可选 |
映射,其值为 MultiLanguage
|
const |
提供一个常量值。 | 可选 | 任意类型 |
default |
提供默认值。该值 SHOULD 通过其所在 数据 模式的验证。 | 可选 | 任意类型 |
unit |
提供单位信息,例如用于国际科学、 工程和商业。为保持唯一性,建议 unit 的值指向一个语义 定义(另见 语义 标注一节)。 | 可选 |
string
|
oneOf |
用于确保数据对数组中指定的 某一个模式有效。这可用于描述多个输入或输出 模式。 | 可选 |
数组,其元素为 DataSchema
|
enum |
以数组形式提供的一组受限 值。 | 可选 | 数组,其元素为任意类型 |
readOnly |
布尔值,用作提示,指示 属性交互/值是否为只读 (=true)或否(=false)。 | 有默认值 |
boolean
|
writeOnly |
布尔值,用作提示,指示 属性交互/值是否为只写 (=true)或否(=false)。 | 有默认值 |
boolean
|
format |
允许基于格式模式进行验证, 例如 "date-time"、"email"、"uri" 等。(另见 下文。) | 可选 |
string
|
type |
赋予与 JSON Schema 兼容的基于 JSON 的数据类型 (boolean、integer、number、 string、object、array 或 null 之一)。 | 可选 |
anyURI(以下之一:
object、array、
string、number、
integer、boolean 或
null)
|
DataSchema 类具有以下
子类:
format 字符串值来自一组
固定的值,以及 [JSON-SCHEMA]
中定义的相应格式规则
(尤其是第 7.3 节“已定义格式”)。服务体
MAY 使用
format 值
相应执行附加验证。
当赋给
format 的值不在已知值集合中时,
这样的验证 SHOULD 成功。
any type 的词汇表术语
(例如 const、default)遵循
与 JSON Schema 兼容的数据类型(boolean、integer、
number、string、object、array 或 null)。
format 术语并未被 JSON Schema 工具
广泛实现。此外,术语
format 正在 JSON
Schema 标准化社区中讨论,未来 JSON Schema
版本中可能会被另一种机制替代或移除。
描述类型为数组的数据的元数据。
此子类由
DataSchema 实例中赋给
type 的值 array 表示。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
items |
用于定义数组的特征。 | 可选 |
DataSchema
或由 数组 组成的 DataSchema
|
minItems |
定义数组中必须包含的最小 项数。 | 可选 |
unsignedInt
|
maxItems |
定义数组中必须包含的最大 项数。 | 可选 |
unsignedInt
|
描述类型为 boolean 的数据的元数据。
此子类由
DataSchema 实例中赋给 type 的值
boolean 表示。
描述类型为 number 的数据的元数据。
此子类由
DataSchema 实例中赋给 type 的值
number 表示。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
minimum |
指定一个最小数值,表示 包含式下限。仅适用于 相关的 number 或 integer 类型。 | 可选 |
double
|
exclusiveMinimum |
指定一个最小数值,表示 排除式下限。仅适用于 相关的 number 或 integer 类型。 | 可选 |
double
|
maximum |
指定一个最大数值,表示 包含式上限。仅适用于 相关的 number 或 integer 类型。 | 可选 |
double
|
exclusiveMaximum |
指定一个最大数值,表示 排除式上限。仅适用于 相关的 number 或 integer 类型。 | 可选 |
double
|
multipleOf |
指定 multipleOf 值数。 该值必须严格大于 0。仅适用于 相关的 number 或 integer 类型。 | 可选 |
double
|
描述类型为 integer 的数据的元数据。
此子类由
DataSchema 实例中赋给 type 的值
integer 表示。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
minimum |
指定一个最小数值,表示 包含式下限。仅适用于 相关的 number 或 integer 类型。 | 可选 |
integer
|
exclusiveMinimum |
指定一个最小数值,表示 排除式下限。仅适用于 相关的 number 或 integer 类型。 | 可选 |
integer
|
maximum |
指定一个最大数值,表示 包含式上限。仅适用于 相关的 number 或 integer 类型。 | 可选 |
integer
|
exclusiveMaximum |
指定一个最大数值,表示 排除式上限。仅适用于 相关的 number 或 integer 类型。 | 可选 |
integer
|
multipleOf |
指定 multipleOf 值数。 该值必须严格大于 0。仅适用于 相关的 number 或 integer 类型。 | 可选 |
integer
|
描述类型为对象的数据的元数据。
此子类由
DataSchema 实例中赋给
type 的值 object 表示。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
properties |
嵌套的数据模式定义。 | 可选 |
映射,其值为 DataSchema
|
required |
定义 object 类型的哪些成员是
强制的,即将要发送的负载中哪些成员是强制的
(例如
invokeaction 的输入、
writeproperty),以及正在接收的负载中
哪些成员将被确实交付(例如
invokeaction 的输出、
readproperty)
|
可选 |
数组,其元素为
string
|
描述类型为 string 的数据的元数据。
此子类由
DataSchema 实例中赋给 type 的值
string 表示。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
minLength |
指定字符串的最小长度。仅适用于 相关的 string 类型。 | 可选 |
unsignedInt
|
maxLength |
指定字符串的最大长度。仅适用于 相关的 string 类型。 | 可选 |
unsignedInt
|
pattern |
提供一个正则表达式,用于表示 字符串值的约束。该正则 表达式必须遵循 [ECMA-262] 方言。 | 可选 |
string
|
contentEncoding |
指定用于存储内容的编码, 如 [RFC2045] (第 6.1 节)和 [RFC4648] 所指定。 | 可选 |
string(例如 7bit、
8bit、binary、
quoted-printable、
base16、base32 或
base64)
|
contentMediaType |
指定字符串值内容的 MIME 类型, 如 [RFC2046] 所述。 | 可选 |
string(例如
image/png 或
audio/mpeg)
|
描述类型为 null 的数据的元数据。
该子类由 DataSchema
实例中赋给 type 的值 null
表示。该子类只描述一个可接受
值,即 null。需要注意的是,
null 并不表示没有
值。它类似于 JavaScript 中的 null、
Python 中的 None、
Java 中的 null 和 Ruby 编程语言中的
nil。它可作为
oneOf 声明的一部分使用,在其中用于
表示该数据也可以是
null。
本规范提供一组 成熟的安全机制,这些机制要么直接 内置于可作为 W3C WoT 协议 绑定的协议中,要么广泛用于 这些协议。当前的 HTTP 安全 方案集合部分基于 OpenAPI 3.0.1(另见 [OPENAPI])。 但是,虽然本规范给出的 HTTP 安全方案、 词汇表和语法 与 OpenAPI 有许多相似之处, 它们并不兼容。
一般而言,安全方案需要某种形式的安全 传输才能有效,例如 TLS 或 DTLS。 关于使用安全传输的要求见本文档 第 11. 安全 考量节,以及 [wot-architecture11] 的安全 考量一节。
描述安全机制配置的元数据。
赋给名称
scheme 的值
MUST 定义在
物描述中包含的
词汇表内,
可以是在
§ 5. TD
信息模型中定义的标准
词汇表,
也可以是在TD 上下文
扩展中。
对于所有安全方案,任何 密钥、密码或其他直接提供访问能力的敏感信息 MUST NOT 存储在 TD 中,而应通过其他机制 在带外共享和存储。TD 的目的 是在且仅在消费者已经获得授权时, 描述如何访问某个物,而并非用于 授予该授权。
TD 中使用的每个安全方案对象定义了一组 在授予访问前必须满足的要求。 当一个安全方案的所有要求都被满足时,我们称其 已满足。在某些情况下,必须先满足 多个安全方案的要求,才能授予访问。
安全方案通常可能需要附加的
认证参数,例如密码或密钥。
这些信息的位置由与名称 in 关联的值指示,
通常还会结合与
name 关联的值。与
in 关联的值可以取以下值之一:
header:name 的值提供。query:name 提供。body:name 提供。
当在
body 安全信息位置的上下文中使用时,
name 的值 MUST 采用 JSON 指针
[RFC6901]
的形式,并相对于其所用于的每个交互的输入
DataSchema 的根。由于该值不是片段
标识符,也不是相对于 TD 的根,而是相对于
安全方案所绑定的任何数据模式,因此该值不应以
# 开头;它是一个“纯”JSON 指针。
由于该值不是片段标识符,也不需要对特殊字符
进行 URL 编码。目标元素可能已经存在于
所引用对象或数组模式中的指定位置,也可能不存在
(因此该机制不适用于简单类型)。如果不存在,
将插入该元素。这避免了在每个交互的数据
模式中重复定义。当
body 定位器中指示的 JSON 指针所指示的数据模式元素
在所指示的模式中尚不存在时,MUST 能够
在指针所指示的位置插入该
元素。
body 定位器中使用的 JSON
指针 MAY 使用 "-"
字符来指示不存在的数组元素,当需要
在现有数组最后一个元素之后插入元素时。
body 安全信息位置所引用(或创建)的元素
MUST 是必需的,并且类型为
"string"。如果未给出
name,则假定整个 body 都将用作安全
参数。
cookie:name 的值标识的 cookie 中。
uri:name 的值定义的 URI
模板变量进行编码。这比
query 机制更通用,但也更复杂。
仅当 query 不适用时,
uri 值 SHOULD 被
指定为安全方案中名称 in 的值。
在使用 uri 作为 in
值的安全方案的交互中提供的 URI
MUST 是包含已定义变量的 URI 模板。
auto:SecurityScheme 的 in
字段设置为 auto 值,则
name 字段 SHOULD
NOT 被设置。在这种情况下,
SecurityScheme 的应用受给定协议的相应规范约束
(例如在使用 HTTP 的
BasicSecurityScheme 时为
[RFC8288])。
如果某个安全方案需要多个参数,
请为每个参数重复安全方案定义,并使用
combo 安全方案和 allOf 将其组合。
在某些情况下,参数实际上可能并非秘密,但用户可能
希望将其排除在 TD 之外以帮助保护隐私。
一个例子是,某些安全机制同时需要
客户端标识符和密钥。理论上,客户端
标识符是公开的;然而它可能难以更新并
带来跟踪风险。在这种情况下,可将其作为
附加安全参数提供,使其不出现在 TD 中。
SecurityScheme 中声明的 URI
变量名称 MUST 与 TD 中声明的所有其他
URI 变量不同。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
@type |
JSON-LD 关键字,用于用语义标签 (或类型)标记对象。 | 可选 |
string 或由 数组 组成的
string
|
description |
基于默认语言提供附加(人类可读) 信息。 | 可选 |
string
|
descriptions |
可用于支持不同语言中的(人类可读) 信息。另见 MultiLanguage。 | 可选 |
映射,其值为 MultiLanguage
|
proxy |
该安全配置为其提供访问的代理服务器 URI。 如果未给出,则相应的安全配置用于 端点。 | 可选 |
anyURI
|
scheme |
所配置安全机制的标识。 | 强制 |
string(例如
nosec、combo、
basic、digest、
bearer、psk、
oauth2、apikey 或
auto)
|
SecurityScheme 类具有以下
子类:
一种安全配置,对应于由
词汇表术语
nosec 标识(即 "scheme":
"nosec"),表示访问资源不需要认证或
其他机制。
一种由术语 auto 标识的自动认证安全配置
(即 "scheme": "auto")。该方案表示
安全参数将在运行时由底层协议协商,
并受该协议相应规范的约束(例如在使用 HTTP
时 Basic Authentication 的
[RFC8288])。
由词汇表术语
combo 标识的其他安全方案的组合
(即 "scheme":
"combo")。该方案的元素定义了
如何组合
securityDefinitions 中定义的其他具名方案(包括其他
ComboSecurityScheme
定义),以创建新的方案
定义。必须且只能包含
oneOf 或 allOf
词汇表术语之一。只有可以一起使用的安全方案定义
才能用 allOf 组合。例如,一般不可能
使用 allOf 将不同的 OAuth 2.0 流组合在一起,
除非一个适用于代理而另一个适用于端点。
注意,当多个具名安全方案定义列在
security 字段中时,其语义与
allOf 组合相同(并具有相同的
可允许组合限制)。oneOf 组合等价于
在其他方面相同的 forms 上使用不同的安全方案。
从这个意义上说,oneOf 方案并非必要特性,
但它可以避免此类情况下的冗余。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
oneOf |
由两个或更多字符串组成的数组,用于标识其他 具名安全方案定义;其中任意一个 被满足时即可允许访问。只能选择其中一个 使用。 | 强制 |
数组,其元素为
string
|
allOf |
由两个或更多字符串组成的数组,用于标识其他 具名安全方案定义;这些定义必须全部 被满足才能访问。 | 强制 |
数组,其元素为
string
|
Basic Authentication [RFC7617]
安全配置,由词汇表术语
basic 标识(即 "scheme":
"basic"),使用未加密的用户名和
密码。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
name |
查询、header、cookie 或 uri 参数的名称。 | 可选 |
string
|
in |
指定安全认证信息的位置。 | 有默认值 |
string(以下之一:
header、query、
body、cookie 或
auto)
|
Digest Access Authentication [RFC7616]
安全配置,由词汇表术语
digest 标识(即 "scheme":
"digest")。该方案类似于 basic
authentication,但增加了避免
中间人攻击的特性。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
name |
查询、header、cookie 或 uri 参数的名称。 | 可选 |
string
|
in |
指定安全认证信息的位置。 | 有默认值 |
string(以下之一:
header、query、
body、cookie 或
auto)
|
qop |
保护质量。 | 有默认值 |
string(以下之一:
auth 或 auth-int)
|
API key 认证安全配置,
由词汇表术语
apikey 标识(即 "scheme":
"apikey")。当访问令牌是不透明的时应使用该方案,
例如云服务提供商提供了某种未知或专有格式的
密钥。在这种情况下,该密钥可能并未使用
标准令牌格式。该方案表示服务提供商提供的密钥
需要使用 "in" 字段所指示的机制,
作为服务请求的一部分提供。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
name |
查询、header、cookie 或 uri 参数的名称。 | 可选 |
string
|
in |
指定安全认证信息的位置。 | 有默认值 |
string(以下之一:
header、query、
body、cookie、
uri 或 auto)
|
Bearer Token [RFC6750]
安全配置,由词汇表术语
bearer 标识(即 "scheme":
"bearer"),用于 bearer token
独立于 OAuth2 使用的情况。如果指定了
oauth2 方案,通常没有必要
同时指定该方案,因为它已被隐含。对于
format,值 jwt 表示
符合 [RFC7519],
jws 表示符合
[RFC7797],
cwt 表示符合
[RFC8392],而
jwe 表示符合
[RFC7516];alg 的值
按与这些标准一致的方式解释。
其他
bearer token 的格式和
算法 MAY
在词汇表扩展中指定。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
authorization |
授权服务器的 URI。 | 可选 |
anyURI
|
name |
查询、header、cookie 或 uri 参数的名称。 | 可选 |
string
|
in |
指定安全认证信息的位置。 | 有默认值 |
string(以下之一:
header、query、
body、cookie 或
auto)
|
alg |
编码、加密或摘要算法。 | 有默认值 |
string(例如
ES256 或 ES512-256)
|
format |
指定安全认证信息的格式。 | 有默认值 |
string(例如 jwt、
cwt、jwe 或
jws)
|
预共享密钥认证安全配置,
由词汇表术语
psk 标识(即 "scheme": "psk")。
这用于表明使用了预共享密钥标准,
例如 TLS-PSK [RFC4279],
并且用于密钥的密码套件将在协议协商期间
建立。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
identity |
提供可用于选择或确认的信息的 标识符。 | 可选 |
string
|
用于符合 [RFC6749]
和 [RFC8252]
的系统的 OAuth 2.0 认证安全配置,
由词汇表术语
oauth2 标识(即 "scheme":
"oauth2")。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
authorization |
授权服务器的 URI。 | 可选 |
anyURI
|
token |
令牌服务器的 URI。 | 可选 |
anyURI
|
refresh |
刷新服务器的 URI。 | 可选 |
anyURI
|
scopes |
以数组形式提供的一组授权范围标识符。
这些标识符在授权服务器返回的令牌中提供,
并与 forms 相关联,以标识客户端
可以访问哪些资源以及如何访问。与
form 关联的值 SHOULD 从
该 form 上激活的
OAuth2SecurityScheme 中定义的值中选择。
|
可选 |
string 或由 数组 组成的
string
|
flow |
授权流。 | 强制 |
string(例如 code
或 client)
|
对于 code
流,authorization 和
token 词汇表术语
都 MUST 被包含。
对于
client 流,token 词汇表术语
MUST 被包含。
对于
client 流,authorization
词汇表术语
MUST NOT 被包含。 每个
流的强制元素汇总在下表中:
| 元素 | code |
client |
|---|---|---|
authorization |
强制 | 省略 |
token |
强制 | 强制 |
refresh |
可选 | 可选 |
当前模型为由物暴露的(带类型的)
Web 链接和 Web forms 提供表示。Link
类定义反映了 Web Linking [RFC8288] 中定义术语的
一个非常常见的子集。定义的术语可用于
例如描述与另一个物的关系,例如一个
Lamp
Thing 由一个 Switch Thing 控制。
Form 类对应一种新引入的
超媒体控件形式,用于操纵
物
(以及其他 Web
资源)的状态。
链接可被视为如下形式的陈述: “链接上下文 在 链接目标 处有一个 关系 类型资源”, 其中可选的 目标属性 可以 进一步描述该资源。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
href |
链接的目标 IRI 或 form 的提交目标。 | 强制 |
anyURI
|
type |
目标属性,提供提示,指示 解引用该链接结果应当是什么媒体类型 [RFC2046]。 | 可选 |
string
|
rel |
链接关系类型标识链接的语义。 | 可选 |
string
|
anchor |
用给定 URI 或 IRI 覆盖链接上下文
(默认情况下为由其 id 标识的物自身)。 |
可选 |
anyURI
|
sizes |
目标属性,指定所引用图标的一个或多个 尺寸。仅适用于关系类型 "icon"。 其值模式遵循 {Height}x{Width} (例如 "16x16"、"16x16 32x32")。 | 可选 |
string
|
hreflang |
hreflang 属性指定链接文档的语言。 该值必须是有效语言标签 [BCP47]。 | 可选 |
string 或由 数组 组成的
string
|
hreflang 属性在本版本规范中
被允许为 string 或
array。
根据 [LINKSET-MEDIA-TYPES]
的结果,hrefLang 的值可能被限制为
只能是 array。
链接关系可用于描述各种关系, 例如与其他物的关系(如 Switch Thing 控制 Lamp Thing)、与特定类型物模型的关系(如物 描述是特定物模型的实例),或 与进一步文档信息的关系(如某个物的设备 手册)。建议复用已有且成熟的 IANA 链接 关系定义。
下面介绍一个最佳实践关系类型表, 建议在 WoT 物描述 或物 模型实例中使用。
| 值 | 出现次数 | 说明 | 值来源 |
|---|---|---|---|
icon |
0..* | 导入与物关联的图标 (例如用于 UI 目的)。 | IANA Link Relation |
service-doc |
0..* | 关联到提供(人类可读)文档或 描述的资源。 | IANA Link Relation |
alternate |
0..* | 指向该 物的替代表示(即 RDF-Turtle、人类可读 HTML 文档,……)。 | IANA Link Relation |
type |
0..1 | 指示该物是目标资源的实例, 例如某个物模型的实例。 | IANA Link Relation |
tm:extends |
0..1 | 扩展目标资源的现有定义,例如某个 物模型。 仅适用于物模型定义。 | W3C WoT Thing Model |
tm:submodel |
0..* | 用于组合一个或多个物模型。 仅适用于物模型定义。 | W3C WoT Thing Model |
manifest |
0..* | 指向 Web 应用清单,该 Web 应用提供例如一个用户界面,使用户可与物交互 (另见 [APPMANIFEST])。 | IANA Link Relation |
proxy-to |
0..* |
目标资源提供代理地址。
可以使用 SecurityScheme 中的
proxy 字段提供附加安全元数据。
|
W3C WoT Security and WoT Binding Template |
collection |
0..1 | 指向物集合。 | IANA Link Relation |
item |
0..* | 指向作为当前物集合成员的 物。 | IANA Link Relation |
predecessor-version |
0..1 | 指向先前的物 描述或物模型 版本。 | IANA Link Relation |
controlledBy |
0..* | 引用一个控制上下文物的 物。 | W3C Thing Description |
form 可被视为如下陈述:“要在 form 上下文上执行一个 操作类型操作,请向 提交目标发出一个 请求方法 请求”,其中可选的 form 字段 可以进一步描述所需的请求。在物描述中, form 上下文是周围的对象, 例如属性、动作和事件,或物自身(用于元交互)。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
href |
链接的目标 IRI 或 form 的提交目标。 | 强制 |
anyURI
|
contentType |
基于媒体类型
(例如 text/plain)以及该媒体类型的潜在
参数(例如 charset=utf-8)分配内容类型
[RFC2046]。
|
可选 |
string
|
contentCoding |
内容编码值表示已经或可以应用于 表示的编码转换。内容编码主要用于 允许表示被压缩或以其他有用方式转换, 同时不丢失其底层媒体类型的身份,也不 丢失信息。内容编码的示例包括 "gzip"、"deflate" 等。 | 可选 |
string
|
security |
一组安全定义名称,从
securityDefinitions 中定义的名称中选取。
要访问资源,必须全部满足这些定义。
|
可选 |
string 或由 数组 组成的
string
|
scopes |
以数组形式提供的一组授权范围标识符。
这些标识符在授权服务器返回的令牌中提供,
并与 forms 关联,以标识客户端
可以访问哪些资源以及如何访问。与
form 关联的值 SHOULD 从
该 form 上激活的
OAuth2SecurityScheme 中定义的值中选择。
|
可选 |
string 或由 数组 组成的
string
|
response |
如果例如输出通信元数据与输入 元数据不同(例如输出 contentType 不同于 输入 contentType),可以使用这个可选术语。 response 名称包含仅对主响应消息有效的 元数据。 | 可选 |
ExpectedResponse
|
additionalResponses |
如果可能存在附加的预期响应, 例如用于错误报告,可以使用该可选术语。 每个附加响应都需要以某种方式 与其他响应区分开来(例如指定协议特定的错误代码), 并且也可以拥有自己的数据模式。 | 可选 |
数组,其元素为 AdditionalExpectedResponse
|
subprotocol |
指示在给定协议有多个选项时,
交互将通过哪种确切机制完成。
例如,对于 HTTP 和事件,它指示应使用
若干可用机制中的哪一种来进行异步通知,
如长轮询
(longpoll)、WebSub [websub]
(websub)、Server-Sent Events
(sse) [html](也称为
EventSource)。请注意,对子协议选择没有
限制,其他机制也可以由该
subprotocol 术语声明。 |
可选 |
string(例如
longpoll、websub 或
sse)
|
op |
指示执行该 form 所描述操作的语义意图。 例如,属性交互允许 get 和 set 操作。协议绑定可能包含一个用于 get 操作的 form,以及另一个用于 set 操作的 form。op 属性指示哪个 form 对应哪个操作,并允许客户端为所需操作选择 正确的 form。op 可以被赋予一个或多个交互动词, 每个动词表示某个操作的语义意图。 | 有默认值 |
string 或由 数组 组成的
string(以下之一:
readproperty、
writeproperty、
observeproperty、
unobserveproperty、
invokeaction、
queryaction、
cancelaction、
subscribeevent、
unsubscribeevent、
readallproperties、
writeallproperties、
readmultipleproperties、
writemultipleproperties、
observeallproperties、
unobserveallproperties、
subscribeallevents、
unsubscribeallevents 或
queryallactions)
|
contentCoding
属性的可能值可以在例如
IANA HTTP 内容编码注册表中找到。
form 的可能操作类型列表是固定的。 截至本规范版本,该列表仅包含实现 [wot-architecture11] 中描述的 WoT 交互模型所必需的已知类型。 标准的未来版本可以扩展该列表,但 操作类型 MUST 限制为下表中的值。
| 操作类型 | 描述 |
|---|---|
| readproperty | 标识属性 可供性上的读取操作,用于检索相应 数据。 |
| writeproperty | 标识属性 可供性上的写入操作,用于更新相应 数据。 |
| observeproperty | 标识属性 可供性上的观察操作,用于在属性更新时收到新数据 通知。 |
| unobserveproperty | 标识属性可供性上的取消观察操作, 用于停止相应 通知。 |
| invokeaction | 标识动作 可供性上的调用操作,用于执行相应 动作。 |
| queryaction | 标识动作 可供性上的查询操作,用于获取 相应动作的状态。 |
| cancelaction | 标识动作 可供性上的取消操作,用于取消正在进行的相应 动作。 |
| subscribeevent | 标识事件 可供性上的订阅操作,用于在事件发生时由物发送 通知。 |
| unsubscribeevent | 标识事件 可供性上的取消订阅操作,用于停止相应 通知。 |
| readallproperties | 标识物上的 readallproperties 操作, 用于在单个交互中检索所有属性的 数据。 |
| writeallproperties | 标识物上的 writeallproperties 操作, 用于在单个交互中更新所有可写 属性的数据。 |
| readmultipleproperties | 标识物上的 readmultipleproperties 操作,用于在单个交互中检索 所选属性的数据。 |
| writemultipleproperties | 标识物上的 writemultipleproperties 操作,用于在单个交互中更新 所选可写属性的数据。 |
| observeallproperties | 标识属性上的 observeallproperties 操作, 用于在任一属性更新时收到新数据 通知。 |
| unobserveallproperties | 标识属性上的 unobserveallproperties 操作,用于在单个交互中停止来自所有属性的 通知。 |
| queryallactions | 标识物上的 queryallactions 操作, 用于在单个交互中获取所有动作的 状态。 |
| subscribeallevents | 标识事件上的 subscribeallevents 操作, 用于在单个交互中订阅来自所有 事件的通知。 |
| unsubscribeallevents | 标识事件上的 unsubscribeallevents 操作, 用于在单个交互中取消订阅来自所有 事件的通知。 |
WoT 生产者的 物描述 可能具有多个 forms 条目,例如具有不同协议和/或 内容类型声明,而消费者可能支持其中一些。 在这种情况下,消费者可以选择任何对其可用的 form 条目(例如协议和内容类型受支持)。一旦选择一个 form,就预期消费者会尽可能持续 将其用于与 WoT 生产者的每次新交互。
本节为非规范性内容。
可与 TD 一起使用的协议遵循
请求-响应或事件机制。可供性的数据
模式通常与 forms 中使用的
op 关键字相关。
下表以资料性方式总结了可用的
与数据模式相关的术语及其与 op
关键字的关系。
| 操作类型 | Consumer to Thing DataSchema 相关性 | Thing to Consumer DataSchema 相关性 |
|---|---|---|
| readproperty | 无相关性。 | Property Affordance 中所有不带
"writeOnly":true 的字段。
|
| writeproperty | Property Affordance 中所有不带
"readOnly":true 的字段。
|
无相关性。
additionalResponses 可在
form 层级使用。
|
| observeproperty | 无相关性。 | Property Affordance 中所有不带
"writeOnly":true 的字段。
|
| unobserveproperty | 无相关性。 | 无相关性。 |
| invokeaction | input 键的值。 |
output 键的值。 |
| queryaction | 无相关性。 | 无相关性。
additionalResponses 可在
form 层级使用。
|
| cancelaction | 无相关性。 | 无相关性。
additionalResponses 可在
form 层级使用。
|
| subscribeevent | subscription 键的值,
包含所有不带
"readOnly":true 的字段
|
subscription 键的值,
包含所有不带
"writeOnly":true 的字段
|
| unsubscribeevent | subscription 键的值,
包含所有不带
"readOnly":true 的字段
|
subscription 键的值,
包含所有不带
"writeOnly":true 的字段
|
写入属性并不 一定意味着新值会被发送给正在观察该属性的 消费者。这取决于 协议和实现。
关于如何将操作映射到数据模式的进一步规范,
以及如何映射诸如 readallproperties 这样的元
操作,可在
[WOT-BINDING-TEMPLATES]
的相应协议规范中找到。
可选的 response 名称-值对
可用于为预期的
响应消息提供元数据。在核心词汇中,它只能
包含内容类型信息,但也可以应用 TD 上下文
扩展。如果未提供
response 名称-值对,则
MUST 假定
响应的内容类型等于赋给 Form 实例的
内容类型。注意,
ExpectedResponse 类中的
contentType 没有
默认值。
在某些情况下可能存在附加响应。
一个例子是错误响应,但在某些情况下也可能
存在附加的成功响应。在这种情况下,
response 名称-值对仍用于主响应,
但也可以提供 additionalResponses,
其值为
AdditionalExpectedResponse 对象数组。
每个附加响应必须以某种方式与主响应区分开来,
可以通过 contentType,
或者通过协议特定设置(如错误代码 header 值)。
每个附加响应也可以具有一个数据模式,
该模式可不同于该交互的普通输出数据模式。
在某些用例中,输入和输出数据可能以
不同形式表示,例如某个动作
接受 JSON,但返回图像。在这种
情况下,可选的 response 键-值对
可以描述预期响应的内容类型。
由于没有定义默认值,以下
断言适用:
response 对象中没有定义
contentType 值,
消费者 MUST 预期
相应响应不包含任何
负载。response 对象中定义了内容类型,
消费者 MUST 预期响应包含
相应格式的负载,例如在
image/jpeg 的情况下为图像。类似考量也适用于附加 响应:
Form 实例 MUST 在与名称
additionalResponses 关联的数组中包含一个条目。contentType 值,消费者
MUST 预期相应响应不包含任何
负载。Form MUST
在与名称 additionalResponses 关联的数组中
包含一个条目,该条目包含名称 schema 的值。contentType 时,
附加预期响应对象的 schema
MUST NOT 被定义。上文解释了请求和响应变化的不同情况。 C. 物 描述中的 contentType 用法中的表以简洁 方式总结了这些情况。
描述主响应的预期 响应消息的通信元数据。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
contentType |
基于媒体类型
(例如 text/plain)以及该媒体类型的潜在
参数(例如 charset=utf-8)分配内容类型
[RFC2046]。
|
可选 |
string
|
描述附加响应的预期 响应消息的通信元数据。
| 词汇表术语 | 描述 | 赋值 | 类型 |
|---|---|---|---|
success |
标示附加响应是否不应被 视为错误。 | 有默认值 |
boolean
|
schema |
如果附加响应的输出数据模式不同于默认
输出数据模式,则用于定义该附加响应的
输出数据模式。必须使用
schemaDefinitions 映射中给出的
先前定义的名称,而不是
DataSchema 对象。
|
可选 |
string
|
contentType |
基于媒体类型
(例如 text/plain)以及该媒体类型的潜在
参数(例如 charset=utf-8)分配内容类型
[RFC2046]。
|
可选 |
string
|
当 TD 中的赋值 缺失时,TD 处理器MUST 遵循 默认 值赋值,这些赋值在默认值 定义表中表达。
| 类 | 词汇表术语 | 默认值 | 注释 |
|---|---|---|---|
PropertyAffordance |
readOnly |
false |
此词汇表术语的默认值仅适用于
PropertyAffordance 层级
定义。在其他上下文中,例如
DataSchema 定义,该词汇表
术语是可选的。
|
PropertyAffordance |
writeOnly |
false |
此词汇表术语的默认值仅适用于
PropertyAffordance 层级
定义。在其他上下文中,例如
DataSchema 定义,该词汇表
术语是可选的。
|
PropertyAffordance |
observable |
false |
|
ActionAffordance |
safe |
false |
|
ActionAffordance |
idempotent |
false |
|
AdditionalExpectedResponse |
success |
false |
|
Form |
contentType |
application/json |
|
Form |
op |
数组,其元素为
readOnly 和 writeOnly
设置为 false 时包含元素
readproperty 和
writeproperty 的
string,或当 readOnly
设置为 true 时包含元素
readproperty 的
数组
string,或当
writeOnly 设置为
true 时包含元素
writeproperty 的
数组
string。 |
如果定义在
PropertyAffordance 的实例中
|
Form |
op |
invokeaction |
如果定义在
ActionAffordance 的实例中
|
Form |
op |
数组,其元素为
subscribeevent 和
unsubscribeevent 的
string
|
如果定义在
EventAffordance 的实例中
|
BasicSecurityScheme |
in |
header |
|
DigestSecurityScheme |
in |
header |
|
DigestSecurityScheme |
qop |
auth |
|
APIKeySecurityScheme |
in |
query |
|
BearerSecurityScheme |
in |
header |
|
BearerSecurityScheme |
alg |
ES256 |
|
BearerSecurityScheme |
format |
jwt |
此外,以下考量适用于默认值的使用:
forms 条目
具有多个 op 值时,该 form MUST NOT 将消费者可发送的
消息限制为仅一个操作。例如,
具有 "op":["readproperty",
"writeproperty"] 的 form 不能包含
htv:methodName。通常,TD 处理器
会在内部将多个 op
值扩展为单独的 forms 条目,并
使用默认假定将每个操作与具体的协议
请求关联起来。地址信息(例如 href)
和其他元数据会被带入扩展后的版本。
请参阅 HTTP Binding 中的
示例。
@context 中定义的前缀的项时启用语义
处理,TD 处理器
SHOULD 根据
[WOT-BINDING-REGISTRY]
中定义的绑定,通过添加这些
前缀的定义来扩展
@context。
这要求 TD 处理器知晓
TD 中使用的前缀。当
TD 处理器被实现为支持
一组特定协议和数据格式时,通常就是
这种情况。另见示例 4。
注意,默认值和扩展机制可以按顺序
应用。例如,缺少
"readOnly" 和 "writeOnly" 意味着
默认值 false 会应用于二者,
如
表 31所示,这进而意味着
"op" 的默认值是
["readproperty", "writeproperty"]。使用协议绑定的
默认方法时,这意味着
"GET" 和 "PUT" 分别对应于
"readproperty" 和 "writeproperty"。
但是,遵循多个操作的扩展
机制,会在内部创建两个单独的 forms,
每个操作一个,并指示默认
方法。然后,应用默认上下文扩展
机制,将 htv 前缀的定义添加到
@context。下面的
示例显示初始 TD,以及在应用所有默认值和扩展
机制后的完全扩展 TD。
WoT 物描述表示物,并基于 5. TD
信息模型来建模和
构造。
本节为物定义一种基于 JSON
的表示格式,
即对
TD
信息模型所定义的
类
Thing 的实例进行序列化。
TD 处理器MUST 能够按照 6.1 到 JSON 类型的映射和 6.3 信息模型 序列化中指出的规则,将物 描述序列化为 JSON 格式 [RFC8259] 和/或从 该格式反序列化物描述。
TD 信息模型的 JSON 序列化与 JSON-LD 1.1 [json-ld11] 的语法保持一致,以简化 语义求值。因此,TD 表示格式既可以作为 原始 JSON 处理,也可以使用 JSON-LD 1.1 处理器 处理(有关语义处理的详情,请参阅 D. JSON-LD 上下文用法以及 命名空间 IRI 下的文档,例如 https://www.w3.org/2019/wot/td)。
为了支持可互操作的国际化, TD MUST 按照 RFC8259 [RFC8259] 第 8.1 节中为开放生态系统定义的要求进行序列化。 总结而言,这要求如下:
TD 信息模型经过构造,使模型对象与 JSON 类型之间存在 简单映射。每个 类 实例都映射到一个 JSON 对象,其中类实例的每个名称-值对都是该 JSON 对象的一个成员。
5.3
类定义中提及的每个简单
类型
(即 string、anyURI、
dateTime、integer、
unsignedInt、double 和
boolean)都按照下列规则映射到一个原始 JSON 类型
(string、number、boolean)。这些规则
适用于名称-值对中的值:
string 或 anyURI 的值 MUST 序列化为 JSON
字符串。dateTime 的值 MUST 按照
[RFC3339] 指定的 "date-time" 格式
序列化为 JSON 字符串。
示例包括 2019-05-24T13:12:45Z
和 2015-07-11T09:32:26+08:00。类型为
dateTime 的值 SHOULD 使用
表示 UTC 时区的字面量 Z,
而不是偏移量。integer 或 unsignedInt 的值 MUST 序列化为
不带小数部分或指数部分的 JSON 数字。double 的值 MUST
序列化为 JSON 数字。boolean 的值 MUST
序列化为 JSON 布尔值。TD 信息模型的每个复杂类型(即 数组、映射和 类 实例)都按照下列规则映射到 结构化 JSON 类型(array 和 object):
物描述序列化可以省略已定义 默认值的词汇表术语, 这些默认值列于 5.4 默认值定义给出的表中。
以下示例展示了来自示例 1的 TD 实例, 并带有一个复选框,用于同时包含带有默认值的成员 (= 复选框选中)。这些成员可以被省略(= 复选框 未选中),以简化 TD 序列化。注意, TD 处理器解释这些被省略的成员时,与 它们以给定默认值显式存在时相同。
请注意,根据所使用的协议 绑定,可能适用附加的协议特定词汇表术语。 它们也可能具有关联的默认值, 因此也可以按本小节所述被省略。 更多信息可在8.1.1 协议绑定中找到。
物描述是一种数据结构,其根为
对象
类型
Thing。相应地,物描述的 JSON
序列化是一个 JSON 对象,
它是由
TD
信息模型构造的语法树的根。
TD 序列化的根
元素
MUST 是一个 JSON 对象,
该对象包含一个名称为 @context 的成员,且其
值为字符串类型,或为等于或相应包含
https://www.w3.org/ns/wot-next/td
的数组类型。
通常,该 URI 用于标识本规范所定义的 TD
表示格式版本。对于 JSON-LD 处理 [json-ld11],该 URI
指定物描述上下文文件。类型为数组的
@context 表示 TD 上下文扩展
(详情见 7. TD 上下文
扩展)。
{
"@context": "https://www.w3.org/ns/wot-next/td",
// ...
}
Thing 实例中
名称属于 Thing 的
签名内
词汇表术语的所有名称-值对,
MUST 被
序列化为根对象的 JSON 成员。
下面给出一个序列化根对象的 TD 片段,其中包含所有 强制和可选成员:
{
"@context": "https://www.w3.org/ns/wot-next/td",
"@type": "Thing",
"id": "urn:uuid:1b37933b-3212-4dad-9c2c-74c6042c3e2b",
"title": "MyThing",
"titles": {/*...*/},
"description": "Human readable information.",
"descriptions": {/*...*/},
"support": "mailto:support@example.com",
"version": {/*...*/},
"created": "2018-11-14T19:10:23.824Z",
"modified": "2019-06-01T09:12:43.124Z",
"securityDefinitions": {/*...*/},
"security": /*...*/,
"base": "https://servient.example.com/",
"properties": {/*...*/},
"actions": {/*...*/},
"events": {/*...*/},
"links": [...],
"forms": [...]
}
Thing
类实例中赋给
version、
securityDefinitions、
descriptions、schemaDefinitions、
uriVariables、properties、
actions 和 events 的所有
值 MUST 被
序列化为 JSON 对象。
Thing
类实例中赋给
links 和
forms 的所有值
MUST 被序列化为 JSON 数组,
其中包含分别按 6.3.8
links 和 6.3.9
forms中定义的 JSON 对象。
Thing
类实例中赋给
security 的值
MUST 被序列化为
JSON 字符串,或被序列化为其元素为 JSON
字符串的 JSON 数组。
TD 文档中使用名为 title 和
description 的 JSON 成员来
提供人类可读元数据。它们可用作
检查 TD 文档的开发者注释,或用作
用户界面的显示文本。
如 5.3.1.1
Thing 中所定义,用于
显示人类可读元数据的基本文本方向,可以通过
首强规则等启发式方法估计,或从语言信息中
推断。在 TD 文档中,默认语言由
@context 中赋给
@language 的值定义,
并且该值连同必要时的文字系统子标签,可用于
确定基本文本方向。但是,
在解释人类可读文本时,每个人类可读
字符串值 MUST 被独立
处理。换言之,TD 处理器
不能将一个字符串中的方向变化延续到另一个字符串,
也不能根据 TD 中其他位置的另一个字符串推断
某个字符串的方向。
下面显示了一个使用 title 和
description 的 TD 片段。默认
语言通过 @context 数组中某个 JSON 对象内
@language 成员的定义
设置为 en。
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{ "@language": "en" }
],
"title": "MyThing",
"description": "Human readable information.",
// ...
"properties": {
"on": {
"title": "On/Off",
"type": "boolean",
"forms": [...]
},
"status": {
"title": "Status",
"type": "object",
// ...
"forms": [...]
}
},
// ...
}
Strings on the Web [STRING-META]
建议使用元数据来确定字符串值的基本
方向。鉴于
物描述格式基于 JSON-LD 1.1
[json-ld11],
@direction 及其字符串值
"ltr"、"rtl" 和 null 值
null MAY 在
@context 内使用,用于指示整个
TD 文档中人类可读字符串的默认文本方向。
当
@direction 等元数据不存在时,TD 消费者
SHOULD 使用
首强检测作为回退。
对于 MultiLanguage
映射,TD
消费者 MAY 根据各个
字符串的语言标签推断基本
方向。这些可概括为以下步骤,
TD 消费者可以根据 TD 中提供的信息实现这些步骤。
@context 中找到的
@direction 值。
@language 的值,然后猜测文本
方向。
dir=auto。请注意,在本规范当前版本中, 字符串特定方向元数据尚不可用。工作组正在制定一种 机制来使其成为可能。在此之后,它将成为 TD 消费者处理文本方向的首选方式。
此外,下面的示例说明了
@direction 和 @language
术语的使用。更多详细信息见 [json-ld11] 和 [string-meta]。
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"@language": "ar-EG",
"@direction": "rtl"
}
],
"title": "شيء يخصني يقيس درجة الحرارة",
"description": "شيء يقيس درجة الحرارة و يظهر حالته",
// ...
"properties": {
"temp": {
"title": "درجة الحرارة",
"type": "boolean",
"forms": [...]
},
"status": {
"title": "حالة",
"type": "object",
// ...
"forms": [...]
}
},
// ...
}
TD 文档中使用名为 titles 和
descriptions 的 JSON 成员,
以在单个 TD 文档内提供多种语言的人类可读元数据。
MultiLanguage
映射的所有名称-值
对 MUST 被序列化为 JSON
对象的成员,其中名称是由
[BCP47] 定义的有效语言标签(另见
W3C I18N Glossary),值是以该标签
指示语言书写的人类可读字符串。详情见
5.3.1.7
MultiLanguage。TD 文档中的所有
MultiLanguage 对象
SHOULD 包含相同的一组
语言成员。
下面给出一个在不同层级使用 titles 和
descriptions 的 TD 片段:
{
"@context": "https://www.w3.org/ns/wot-next/td",
"title": "MyThing",
"titles": {
"en": "MyThing",
"de": "MeinDing",
"ja": "私の物",
"zh-Hans": "我的东西",
"zh-Hant": "我的東西"
},
"descriptions": {
"en": "Human readable information.",
"de": "Menschenlesbare Informationen.",
"ja": "人間が読むことができる情報",
"zh-Hans": "人们可阅读的信息",
"zh-Hant": "人們可閱讀的資訊"
},
// ...
"properties": {
"on": {
"titles": {
"en": "On/Off",
"de": "An/Aus",
"ja": "オンオフ",
"zh-Hans": "开关",
"zh-Hant": "開關" },
"type": "boolean",
"forms": [...]
},
"status": {
"titles": {
"en": "Status",
"de": "Zustand",
"ja": "状態",
"zh-Hans": "状态",
"zh-Hant": "狀態" },
"type": "object",
// ...
"forms": [...]
}
},
// ...
}
TD 实例也可以将
title 和 description 与
titles 和 descriptions
结合使用。
当 title 和
titles,或 description 和
descriptions 出现在同一 JSON
对象中时,title 和
description 的值 MAY 被
视为默认文本。 当
title 和 titles,或
description 和 descriptions
出现在 TD 文档中时,每个 title 和
description 成员 SHOULD 分别具有对应的
titles 和 descriptions 成员。
默认文本的语言由默认语言指示,通常由
物描述实例的创建者设置。
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{ "@language": "de" }
],
"title": "MeinDing",
"titles": {
"en": "MyThing",
"de": "MeinDing",
"ja": "私の物",
"zh-Hans": "我的东西",
"zh-Hant": "我的東西"
},
"description": "Menschenlesbare Informationen.",
"descriptions": {
"en": "Human readable information.",
"de": "Menschenlesbare Informationen.",
"ja": "人間が読むことができる情報",
"zh-Hans": "人们可阅读的信息",
"zh-Hant": "人們可閱讀的資訊"
},
// ...
"properties": {
"on": {
"title": "An/Aus",
"titles": {
"en": "On/Off",
"de": "An/Aus",
"ja": "オンオフ",
"zh-Hans": "开关",
"zh-Hant": "開關" },
"type": "boolean",
"forms": [...]
},
"status": {
"title": "Zustand",
"titles": {
"en": "Status",
"de": "Zustand",
"ja": "状態",
"zh-Hans": "状态",
"zh-Hant": "狀態" },
"type": "object",
// ...
"forms": [...]
}
},
// ...
}
设置默认语言的另一种可能方式是
通过语言协商机制,例如 HTTP 的
Accept-Language header 字段。
在
默认语言已经协商确定的情况下,
@language 成员 MUST
存在,以指示协商结果以及所返回
内容的相应默认语言。 当
默认语言已经成功协商时,TD
文档 SHOULD 优先在
title 和 description 成员中包含
适当匹配的值,而不是在
titles 和 descriptions
成员中使用 MultiLanguage 对象。
不过请注意,物
MAY 选择不支持此类动态生成的 TD,
也可以选择不支持语言协商(例如由于资源
限制)。
不能保证 TD 中的字符串会在 HTML 渲染上下文中 显示。事实上,为了缓解 11.5 脚本 注入中描述的 XSS 安全风险,从 TD 获取的字符串中嵌入的 HTML 标签,在将这些字符串嵌入 网页或 Web 应用的应用程序中应当被清理 (因此不会被解释为 HTML)。因此,字符串中嵌入的 HTML 不是指定文本渲染 方向的适当机制。
VersionInfo
实例中的所有名称-值对,其中名称是包含在
VersionInfo 的
签名中的词汇表术语,
MUST 以该
词汇表术语作为名称,
序列化为 JSON 成员。
下面给出一个版本信息对象的 TD 片段:
{
// ...
"version": { "instance": "1.2.1" },
// ...
}
version 成员意在作为一个容器,
用于基于 TD 上下文扩展提供附加的
应用和/或设备特定版本
信息。详情见
7.1 语义
标注。
在 Thing 实例中,赋给
securityDefinitions 的值是
SecurityScheme 实例的映射。
SecurityScheme 实例映射的
所有名称-值对
MUST 序列化为由该映射序列化得到的
JSON 对象的成员;一个对的名称 MUST 序列化为 JSON 字符串,并且
该对的值,即
SecurityScheme 的实例,MUST
序列化为 JSON 对象。
SecurityScheme 的某个
子类实例中的所有名称-值对,
其中名称是包含在该子类的
签名中,或包含在
SecurityScheme 的
签名中的词汇表术语,
MUST
以该词汇表术语作为
名称,序列化为由该 SecurityScheme
子类实例序列化得到的 JSON 对象的成员。
下面的 TD 片段展示了一个简单安全
配置,它指定在 header 中使用 basic 用户名/密码
认证。为
in 给出的值实际上是默认值
(header),因此可以省略。在
securityDefinitions 映射中给出了一个具名
安全配置(basic_sc)。在此示例中,
该定义通过在
security 成员中包含其 JSON 名称来激活。
{
// ...
"securityDefinitions": {
"basic_sc": {
"scheme": "basic",
"in": "header"
}
},
"security": "basic_sc",
// ...
}
TD 中的安全配置是强制的。
至少一个安全定义
MUST 通过
物层级
(即 TD 根对象)中的 security 成员激活。
这种配置可被视为与物交互所需的默认安全机制。
安全定义 MAY 也可以通过在
form 对象中包含
security 成员,在
form 元素层级激活;这会覆盖(即完全
替换)在物
层级激活的所有定义。
在不需要任何安全机制的情况下,提供了
nosec 安全方案。物的最小安全
配置,是在物层级激活
nosec 安全方案,如下例所示:
{
"@context": "https://www.w3.org/ns/wot-next/td",
"id": "urn:uuid:e9ecb6ad-cd4c-481b-96ce-5b4c57ddb844",
"title": "MyThing",
"description": "Human readable information.",
"support": "https://servient.example.com/contact",
"securityDefinitions": { "nosec_sc": { "scheme": "nosec" }},
"security": "nosec_sc",
"properties": {/*...*/},
"actions": {/*...*/},
"events": {/*...*/},
"links": [/*...*/]
}
为了给出一个更复杂的示例,假设我们有一个
物,其中除一个之外的所有
交互
可供性都需要 basic 认证,而该例外项不需要认证。
对于
status 属性和 toggle
动作,要求 basic 认证,并在
物层级定义。对于
overheating 事件,则不需要
认证,因此安全配置在 form 层级被覆盖。
{
// ...
"securityDefinitions": {
"basic_sc": {"scheme": "basic"},
"nosec_sc": {"scheme": "nosec"}
},
"security": "basic_sc",
// ...
"properties": {
"status": {
// ...
"forms": [{
"href": "https://mylamp.example.com/status"
}]
}
},
"actions": {
"toggle": {
// ...
"forms": [{
"href": "https://mylamp.example.com/toggle"
}]
}
},
"events": {
"overheating": {
// ...
"forms": [{
"href": "https://mylamp.example.com/oh",
"security": "nosec_sc"
}]
}
}
}
TD 也可以指定安全方案的组合。
下面是一个 TD 片段,展示了在代理上使用 digest 认证,
同时在物上结合 bearer token
认证。
在 digest 方案中,in 的默认值
(即 header)被省略,但仍然适用。
注意,相应的私有安全配置,例如用户名/密码
和 token,需要在消费者中配置,
以便成功交互。当激活多个安全
定义时,security 成员会变成一个
数组。
{
// ...
"securityDefinitions": {
"proxy_sc": {
"scheme": "digest",
"proxy": "https://portal.example.com/"
},
"bearer_sc": {
"scheme": "bearer",
"in": "header",
"format": "jwt",
"alg": "ES256",
"authorization": "https://servient.example.com:8443/"
}
},
"security": ["proxy_sc", "bearer_sc"],
// ...
}
然而,现在不推荐
在 security 元素中使用包含多个元素的
数组来组合安全方案;
应改为使用 ComboSecurityScheme
SHOULD。以下示例与上面的示例
完全等价,并演示了这一点:
{
// ...
"securityDefinitions": {
"proxy_sc": {
"scheme": "digest",
"proxy": "https://portal.example.com/"
},
"bearer_sc": {
"scheme": "bearer",
"in": "header",
"format": "jwt",
"alg": "ES256",
"authorization": "https://servient.example.com:8443/"
},
"combo_sc": {
"scheme": "combo",
"allOf": ["proxy_sc", "bearer_sc"]
}
},
"security": "combo_sc",
// ...
}
也可以为同一个交互
可供性内的不同 forms 指定安全配置。
对于支持多个协议的设备,例如 HTTP 和 CoAP
[RFC7252],
这些协议支持不同安全机制时,这可能是必需的。
当允许替代认证机制时,这也很有用。下面的 TD
片段演示了激活一个属性可供性的三种
可能方式:通过带 basic 认证的
HTTPS、通过 digest 认证、以及通过 bearer token 认证。
换言之,在多个 forms 中使用不同安全配置,
提供了一种以“OR”方式组合安全
机制的方法。相反,将多个安全配置放入同一个
security 成员中会以“AND”方式组合它们,
因为在这种情况下必须全部满足这些配置,才能允许激活该
交互
可供性。注意,在物层级激活一个
(默认)配置仍然是强制的。
{
// ...
"securityDefinitions": {
"basic_sc": { "scheme": "basic" },
"digest_sc": { "scheme": "digest" },
"bearer_sc": { "scheme": "bearer" }
},
"security": "basic_sc",
// ...
"properties": {
"status": {
// ...
"forms": [{
"href": "https://mylamp.example.com/status"
}, {
"href": "https://mylamp.example.com/status",
"security": "digest_sc"
}, {
"href": "https://mylamp.example.com/status",
"security": "bearer_sc"
}]
}
},
// ...
}
为了在这种情况下避免冗余,例如重复
form 元素的细节,可以改用带有
oneOf 的 ComboSecurityScheme。
{
// ...
"securityDefinitions": {
"basic_sc": { "scheme": "basic" },
"digest_sc": { "scheme": "digest" },
"bearer_sc": { "scheme": "bearer" },
"combo_sc": {
"scheme": "combo",
"oneOf": [ "basic_sc", "digest_sc", "bearer_sc" ]
}
},
"security": "combo_sc",
// ...
"properties": {
"status": {
// ...
"forms": [{
"href": "https://mylamp.example.com/status"
}]
}
},
// ...
}
作为另一个更复杂的示例,OAuth 2.0 会使用
scopes。这些标识符可能出现在
tokens 中,并且必须与资源中的相应标识符匹配,
才允许访问该资源(或在
W3C WoT 的情况下访问交互
可供性)。例如,
在下面示例中,status 属性可以由
消费者使用包含 scope limited 的 bearer
tokens 读取,但
configure 动作只能使用包含
special scope 的 token 调用。Scopes
与角色并不相同,但通常与角色相关联;
例如,可能只有拥有管理员角色的人才被授权执行
“special”交互。Tokens 可以拥有多个 scope,
并由专门的 Web 服务签发给用户。在这个
示例中,可以向管理员签发同时带有
limited 和 special
scopes 的 tokens,而普通用户可以获得带有
limited scope 的 tokens。
{
// ...
"securityDefinitions": {
"oauth2_sc": {
"scheme": "oauth2",
"flow": "client",
"token": "https://example.com/token",
"scopes": ["limited", "special"]
}
},
"security": "oauth2_sc",
// ...
"properties": {
"status": {
// ...
"forms": [{
"href": "https://scopes.example.com/status",
"scopes": ["limited"]
}]
}
},
"actions": {
"configure": {
// ...
"forms": [{
"href": "https://scopes.example.com/configure",
"scopes": ["special"]
}]
}
},
// ...
}
一个物可以要求执行 onboarding 过程, 其结果是消费者需要 API key 才能与该 物交互。该 API key 可以按照 API key 方案的指定, 以不同方式包含在发往该 物的请求中。下面是一个示例,展示如何将其用作 URI 模板,其中 API key 应在消费者发送 HTTPS 请求时由消费者在 URI 中替换。
{
// ...
"securityDefinitions": {
"apikey_key": {
"scheme": "apikey",
"in": "uri",
"name": "adminKey"
}
},
"security": "apikey_key",
"properties": {
"status": {
// ...
"forms": [{
"href": "https://example.com/{adminKey}/status",
// ...
}]
}
},
// ...
}
为了在上面所示 URI 模板示例的用法之外,
再举一个使用 ComboSecurityScheme
的示例,假设存在一个安全方案,其中云服务
提供商提供的客户端 ID 和“secret”key 都必须
嵌入到 URL 中。从技术上说,只有 key
真正是秘密的,并且必须带外处理,而不是秘密的客户端 ID
可以嵌入到 TD 中。然而,如果客户端 ID
不能轻易轮换,我们可能希望避免将其嵌入到
TD 中,以增强隐私。在这种情况下,我们可以
组合两个 APIKeySecurityScheme 实例,
二者都将 uri 值用于
in 位置说明符,以声明两个 URI
变量。然后这些变量可以(事实上,必须)在安全方案
处于激活状态的 Form 的
href 中使用。示例如下:
{
// ...
"securityDefinitions": {
"apikey_key": {
"scheme": "apikey",
"in": "uri",
"name": "secKey"
},
"apikey_id": {
"scheme": "apikey",
"in": "uri",
"name": "secClientID"
},
"apikey_combo": {
"scheme": "combo",
"allOf": ["apikey_key","apikey_id"]
}
},
"security": "apikey_combo",
// ...
"properties": {
"status": {
// ...
"forms": [{
"href": "https://example.com/{secClientID}/status/{secKey}",
// ...
}]
}
},
// ...
}
虽然此示例中没有显示,但使用
uriVariables 声明附加 URI 模板变量,
并将它们包含在同一个
URI 模板中,是合法的;不过这些名称不能与
安全方案中声明的名称冲突。像上例那样,
为安全方案中声明的 URI 变量使用特定
前缀,可以更容易地避免名称
冲突。
Body 中的 API Key:在某些系统中,安全参数也可能
随负载一起包含。例如,假设一个系统要求每个
负载都是一个 JSON 对象,其中包含一个名为 auth
的成员,其值是一个对象,该对象包含一个名为
key 的成员,其中包含访问 key。可是,根据
交互不同,JSON 对象中的其他元素可能会变化。
这种情况可以通过使用 body 安全信息位置来处理。
注意,对于这个位置,name 参数实际上是一个
JSON 指针,它相对于其所绑定的每个交互的
DataSchema 根进行求值,这使其可以用于
其他方面会发生变化的负载。作为示例,下面是一盏灯,
它有一个用于设置亮度和颜色的属性,以及两个单独的
动作来打开和关闭它。虽然这些动作的
JSON 负载不同,但
/auth/key 元素出现在相同的
相对位置,因此可以使用单个 JSON 指针。
注意:如果安全 key 出现在不同且不一致的位置,
就有必要使用多个安全方案定义。
{
// ...
"securityDefinitions": {
"apikey_body": {
"scheme": "apikey",
"in": "body",
"name": "/auth/key"
}
},
"security": "apikey_body",
// ...
"properties": {
"color": {
// ...
"type": "object",
"properties": {
"brightness": {
"type": "number",
// ...
},
"rgb": {
"type": "array",
// ...
},
"auth": {
"type": "object",
"properties": {
"key": {
"type": "string"
}
},
"required": ["key"]
}
},
"required": ["brightness", "rgb", "auth"],
"forms": [{
"href": "https://example.com/color",
// ...
}]
}
},
"action": {
"on": {
// ...
"input": {
"auth": {
"type": "object",
"properties": {
"key": {
"type": "string"
}
},
"required": ["key"]
}
},
"required": ["auth"],
"forms": [{
"href": "https://example.com/on",
// ...
}]
},
"off": {
// ...
"input": {
"auth": {
"type": "object",
"properties": {
"key": {
"type": "string"
}
},
"required": ["key"]
}
},
"required": ["auth"],
"forms": [{
"href": "https://example.com/off",
// ...
}]
}
},
// ...
}
body 位置中的
JSON 指针所引用的位置不存在,它会被自动插入。
在这种情况下,上面的示例可以简化为下面这样。
注意,事实上会为
动作 on 和 off 有效地
创建 一个数据模式,仅用于容纳
安全信息。
{
// ...
"securityDefinitions": {
"apikey_body": {
"scheme": "apikey",
"in": "body",
"name": "/auth/key"
}
},
"security": "apikey_body",
// ...
"properties": {
"color": {
// ...
"type": "object",
"properties": {
"brightness": {
"type": "number",
// ...
},
"rgb": {
"type": "array",
// ...
}
},
"required": ["brightness", "rgb"],
"forms": [{
"href": "https://example.com/color",
// ...
}]
}
},
"action": {
"on": {
// ...
"required": ["auth"],
"forms": [{
"href": "https://example.com/on",
// ...
}]
},
"off": {
// ...
"forms": [{
"href": "https://example.com/off",
// ...
}]
}
},
// ...
}
在
Thing 实例中赋给 properties 的值,是
PropertyAffordance 实例的映射。
PropertyAffordance 实例映射的所有名称-值
对
MUST 序列化为由该映射序列化得到的
JSON 对象的成员;一个对的名称 MUST 序列化为 JSON 字符串,并且
该对的值,即
PropertyAffordance 的实例,MUST 序列化为 JSON
对象。
PropertyAffordance 实例中的所有名称-值对,其中名称是
包含在
PropertyAffordance、
InteractionAffordance 或
DataSchema 的(某个)
签名中的
词汇表术语,
MUST 以该
词汇表术语作为
名称,序列化为由该
PropertyAffordance 实例序列化得到的 JSON 对象的成员。 有关序列化
DataSchema
实例的详情,见 6.3.10 数据
模式。
PropertyAffordance 实例中赋给
forms 的值 MUST 序列化为 JSON 数组,
其中包含一个或多个 JSON 对象序列化,
如 6.3.9
forms 中所定义。
下面给出两个属性可供性的 片段:
在 Thing 实例中,赋给
actions 的值是
ActionAffordance 实例的映射。
ActionAffordance 实例映射的所有名称-值对
MUST 序列化为由该映射序列化得到的
JSON 对象的成员;一个对的名称 MUST 序列化为 JSON 字符串,并且
该对的值,即
ActionAffordance 的实例,MUST 序列化为 JSON
对象。
ActionAffordance 实例中的所有
名称-值对,其中名称是包含在
ActionAffordance 或
InteractionAffordance 的(某个)
签名中的词汇表术语,
MUST 以该
词汇表术语作为
名称,序列化为由该
ActionAffordance 实例序列化得到的 JSON
对象的成员。
ActionAffordance 实例中赋给
input 和 output 的值
MUST 序列化为 JSON
对象。
它们依赖于类
DataSchema,其序列化
在 6.3.10 数据
模式中定义。
ActionAffordance
实例中赋给 forms 的值 MUST 序列化为
JSON 数组,
其中包含一个或多个 JSON 对象序列化,
如 6.3.9
forms 中所定义。
下面给出一个动作可供性的 TD 片段:
在 Thing 实例中,赋给
events 的值是
EventAffordance 实例的映射。
EventAffordance 实例映射的所有名称-值对
MUST 序列化为由该映射序列化得到的
JSON 对象的成员;一个对的名称 MUST 序列化为 JSON 字符串,并且
该对的值,即
EventAffordance 的实例,MUST
序列化为 JSON 对象。
EventAffordance 实例中的所有
名称-值对,其中名称是包含在
EventAffordance 或
InteractionAffordance 的(某个)
签名中的词汇表术语,
MUST 以该
词汇表术语作为
名称,序列化为由该
EventAffordance 实例序列化得到的 JSON
对象的成员。
EventAffordance 实例中赋给
subscription、data 和
cancellation 的值 MUST
序列化为 JSON 对象。 它们依赖于
类 DataSchema,
其序列化在 6.3.10 数据
模式中定义。
EventAffordance 实例中赋给 forms 的
值 MUST
序列化为 JSON 数组,其中包含一个或多个 JSON
对象序列化,如 6.3.9
forms 中所定义。
下面给出一个事件对象的 TD 片段:
事件可供性以一种灵活的方式定义,
以便采用现有的(例如 WebSub
[websub])或
面向客户的事件机制(例如 Webhooks)。因此,
subscription 和
cancellation 可以按照所需机制定义。
更多详情请参见
[WOT-BINDING-TEMPLATES]。
示例 A.3 Webhook 事件
示例说明了事件如何使用
subscription 和 cancellation 来
描述 Webhooks。
Link 实例中的所有
名称-值对,其中名称是包含在
Link 的
签名中的词汇表术语,
MUST 以该
词汇表术语作为
名称,序列化为由该 Link 实例序列化得到的 JSON 对象的成员。
建议遵循 5.3.4.1
Link 一节中提供的链接关系值。
下面给出的示例演示了不同链接关系类型的使用。
可以提供一个引用,指向一个控制底层单元
(例如一盏灯)的物(例如控制器)。
对此可以使用
controlledBy:
要指向某个物的开发者文档,
可以使用
service-doc 值:
{
// ...
"links": [{
"rel": "service-doc",
"href": "https://example.com/howTo",
"type": "application/pdf",
"hreflang": "en"
}]
// ...
}
上级物可以收集一组物,并通过使用
item 值来引用它们:
{
"title": "Electric Drive",
// ...
"links": [{
"rel": "item",
"href": "coaps://motor1.example.com",
"type": " application/td+json"
},
{
"rel": "item",
"href": "coaps://motor2.example.com",
"type": " application/td+json"
}]
// ...
}
一个物可以使用
collection 值来引用收集它的组:
{
"title": "Electric Motor 1",
"base": "coaps://motor1.example.com",
// ...
"links": [{
"rel": "collection",
"href": "coaps://drive.example.com",
"type": " application/td+json"
}]
// ...
}
Form 实例中的所有
名称-值对,其中名称是包含在
Form 的
签名中的词汇表术语,
MUST 以该
词汇表术语作为
名称,序列化为由该 Form 实例序列化得到的 JSON 对象的成员。
如果需要,form 对象 MAY 使用 由前缀标识的、协议特定的词汇表术语进行补充。 另见 8.1.1 协议 绑定。
下面给出 forms
数组中 form 对象的 TD 片段:
href 也可以携带包含
动态变量的 URI,例如
http://example.org/weather/?lat=35&lon=139
中的 lat 和
lon。
在这种情况下,可以按照 [RFC6570] 中定义的方式,将 URI 定义为模板:
http://example.org/weather/{?lat,long}。
在这种情况下,URI 模板
变量 MUST 收集到
基于 JSON 对象的 uriVariables 成员中,
可以位于物层级,也可以位于
交互可供性层级,并将相关(唯一的)
变量名作为 JSON 名称。
Form 实例中赋给 uriVariables 的
映射里的每个值,其序列化
MUST 依赖于类 DataSchema,其
序列化在 6.3.10 数据
模式中定义。
下面给出一个 TD 片段,它在交互
可供性层级中使用 URI 模板来表示查询参数
和 uriVariables:
{
"@context": ["https://www.w3.org/ns/wot-next/td", {
"htv": "http://www.w3.org/2011/http#"
}],
// ...
"properties": {
"weather": {
// ...
"uriVariables": {
"lat": {
"type": "number",
"minimum": 0,
"maximum": 90,
"description": "Latitude for the desired location in the world" },
"long": {
"type": "number",
"minimum": -180,
"maximum": 180,
"description": "Longitude for the desired location in the world" }
},
"forms": [{
"href": "http://example.org/weather/{?lat,long}",
"htv:methodName": "GET"
}]
},
// ...
},
// ...
}
或者,如 [RFC6570] 中所定义,
uriVariables 可用于替换
href 结构。下面提供一个示例 TD,
其中获取哥伦比亚波哥大的天气预报的有效请求,
将是发送到
http://example.org/weather/bogota 的 HTTP GET 请求:
{
"@context": ["https://www.w3.org/ns/wot-next/td", {
"htv": "http://www.w3.org/2011/http#"
}],
// ...
"properties": {
"weather": {
// ...
"uriVariables": {
"city": {
"type": "string",
"description": "City name to find the weather information for"
}
},
"forms": [{
"href": "http://example.org/weather/{city}",
"htv:methodName": "GET"
}]
},
// ...
},
// ...
}
下面两个示例也可以组合,同时
使用同一个 uriVariables 特性。一个发送到
http://example.org/weather/bogota/?unit=Celsius
的 HTTP GET 请求可以描述如下:
{
"@context": ["https://www.w3.org/ns/wot-next/td", {
"htv": "http://www.w3.org/2011/http#"
}],
// ...
"properties": {
"weather": {
// ...
"uriVariables": {
"city": {
"type": "string",
"description": "City name to find the weather information for"
},
"unit": {
"type": "string",
"enum": ["fahrenheit_value","celsius_value"],
"description": "Desired unit for the temperature value"
}
},
"forms": [{
"href": "http://example.org/weather/{city}/{?unit}",
"htv:methodName": "GET"
}]
},
// ...
},
// ...
}
uriVariables 主要用于属性
和事件。在改造现有系统时,可能
有必要将 uriVariables 用于
动作。一般而言,在设计新的
基于 WoT 的系统时,建议尽量避免使用
uriVariables。
contentType 成员用于指定
媒体类型 [RFC2046],
包括由 ; 字符分隔的属性-值对形式的
媒体类型参数。示例:
{
// ...
"contentType": "text/plain; charset=utf-8",
// ...
}
在某些用例中,交互
可供性的 form 元数据不仅描述请求,
还为预期响应提供元数据。例如,
动作 takePhoto 定义了一个
input 模式,用于以 JSON 作为
请求负载(即 "contentType":
"application/json")来提交相机的参数设置
(光圈优先、定时器等)。该动作的输出
是拍摄的照片,例如以 JPEG 格式提供。
在这种情况下,response 成员
用于指示响应负载的表示格式(例如
"contentType":
"image/jpeg")。此处不需要 output
模式,因为内容类型已经完整指定了
表示格式。
下面基于上文描述的
takePhoto 动作,展示带有
response 成员的 form 片段:
{
// ...
"actions": {
"takePhoto": {
// ...
"forms": [{
"op": "invokeaction",
"href": "http://camera.example.com/api/snapshot",
"contentType": "application/json",
"response": {
"contentType": "image/jpeg"
}
}]
}
},
// ...
}
在预期响应不包含负载、因此也没有
contentType 的情况下,
可以使用空的 response 对象
来传达此信息。
{
// ...
"actions": {
"brewCoffee": {
"description": "Invoking this action does not return a payload.",
"input": {
"type": "object",
"properties": {
"coffeeType": {
"enum": [
"espresso",
"americano",
"cappuccino",
"latte"
]
},
"useOatMilk": {
"type": "boolean",
"default": false
}
},
"required": [
"coffeeType"
]
},
"forms": [{
"op": "invokeaction",
"href": "http://coffee-maker.example.com/brew-coffee",
"contentType": "application/json",
"response": {}
}]
}
},
// ...
}
在某些情况下,作为交互
可供性一部分从物接收的消息,可能会由于不同原因而有所不同。
这些原因可能是错误情况,或是对有效响应的
替代响应。在这些情况下,可以使用
additionalResponses 术语来
描述这种行为。
例如,用于启动汽车发动机的动作可供性, 在恶劣天气条件下或发动机需要维护时可能无法工作。 在这种情况下,物需要使用通常不会 使用的负载进行回复。
下面展示一个在动作
可供性中带有
additionalResponses 成员的
TD 片段。其第一个元素说明了
上述情况:错误响应可以使用不同于
output 中所描述内容的另一种负载发送。
值为 false 的 success
表明该负载对应错误情况,而 schema
允许链接到
schemaDefinitions 中使用的负载描述。
additionalResponses 中的第二个元素
也描述了错误响应,但这次响应没有
负载。
{
// ...
"schemaDefinitions": {
"actionErrorPayload": {
"type": "object",
"properties": {
"reason": {
"type": "string",
"enum": ["cold","hot","maintenance"]
},
"timeStamp": {
"description": "UNIX time in numbers indicating when the error happened",
"type": "number"
}
}
}
},
// ...
"actions": {
"startEngine": {
"output": {
"type": "string"
},
"forms": [{
"op": "invokeaction",
"href": "http://mycar.example.com/api/engine",
"contentType": "application/json",
"additionalResponses": [
{
"success": false,
"contentType": "application/json",
"schema": "actionErrorPayload"
},
{
"success": false
},
]
}]
}
},
// ...
}
additionalResponses 术语也可以用于
非错误情况。在这种情况下,
success 被设置为 true,
并且可以使用另一个 schema 来描述负载。
在某些情况下,二进制数据会嵌入到基于文本的
值中,例如,基于 JSON 字符串的值嵌入了一个 base64
编码图像。术语 contentMediaType
和 contentEncoding 可用于阐明
这类名称-值对的上下文和编码格式。
下面展示 contentMediaType 和
contentEncoding 的使用样例:
{
// ...
"properties": {
"image": {
"description": "Provides latest image",
"type": "string",
"contentMediaType": "image/png",
"contentEncoding": "base64",
"forms": [{
"op": "readproperty",
"href": "coaps://mylamp.example.com/lastPicture",
"cov:methodName": "GET",
"contentType": "application/json"
}]
}
},
// ...
}
当 forms 出现在顶层时,
它可用于描述由物提供的元交互。
例如,操作类型 readallproperties 和
writeallproperties 用于与物进行元交互,
通过这些交互,消费者可以一次性读取、写入
或观察所有属性。在下面的示例中,
forms 成员包含在 TD 根
对象中,消费者可以同时使用提交目标
https://mylamp.example.com/properties
来读取或写入该物的所有属性
(即 on、
brightness 和 timer),
并在单个协议事务中完成。
{
// ...
"properties": {
"on": {
"type": "boolean",
"forms": [...]
},
"brightness": {
"type": "number",
"forms": [...]
},
"timer": {
"type": "integer",
"forms": [...]
}
},
// ...
"forms": [{
"op": "readallproperties",
"href": "https://mylamp.example.com/properties",
"contentType": "application/json",
"htv:methodName": "GET"
},
{
"op": "writeallproperties",
"href": "https://mylamp.example.com/properties",
"contentType": "application/json",
"htv:methodName": "PUT"
}]
}
物层级的 uriVariables 可在此处用于
为操作提供更多变量,或为
readmultipleproperties 操作指定
属性可供性名称列表。在下面的示例中,
属性的单位可以通过这样的变量来设置,
并且可以设置期望的属性列表:
{
// ...
"properties": {
"temperature": {
"type": "number",
"forms": [...]
},
"brightness": {
"type": "number",
"forms": [...]
},
"humidity": {
"type": "integer",
"forms": [...]
}
},
"uriVariables": {
"propertyNames": {
"type": "string",
"description": "Comma separated list of property names to select."
},
"unitSystem": {
"type": "string",
"enum": ["metric","imperial","uscustomary"],
"description": "System of Measurement that will be used for the values"
}
},
"forms": [{
"op": "readallproperties",
"href": "https://mything.example.com/properties{?unitSystem}",
"contentType": "application/json",
"htv:methodName": "GET"
},
{
"op": "readmultipleproperties",
"href": "https://mylamp.example.com/properties{?propertyNames,unitSystem}",
"contentType": "application/json",
"htv:methodName": "GET"
}]
}
对于 readmultipleproperties 操作,
发送到 URI
https://mylamp.example.com/properties?propertyNames=humidity,temperature&unitSystem=metric
的一个示例 HTTP GET 请求,将返回
humidity 和
temperature 属性可供性的值,并使用
metric 度量系统。
对于操作类型
writeallproperties,预期
消费者提供所有
可写(非 readOnly)属性以及
(新的)赋值(例如在负载中)。类似地,
对于 writemultipleproperties 操作
类型,预期消费者提供可写
(非 readOnly)属性。在物侧,对于
readmultipleproperties 和
readallproperties 操作类型,预期物返回
可读(非 writeOnly)属性。
通过 DataSchema 类定义的
WoT 物描述数据模式,基于
JSON Schema 术语的一个子集 [JSON-SCHEMA]。
因此,TD 数据模式的序列化可以直接输入到
JSON Schema 验证器实现中,用于
验证与物交换的数据。
数据模式序列化适用于
PropertyAffordance 实例、赋给
ActionAffordance 实例中
input 和 output 的值、赋给
EventAffordance 实例中
subscription、data
和 cancellation 的值,以及
InteractionAffordance 的子类实例中
赋给 uriVariables 的值(当form 对象使用
URI
模板时)。
DataSchema 的某个子类实例中的所有
名称-值对,其中名称是包含在该子类的
签名中,或包含在
DataSchema 的
签名中的词汇表术语,
MUST 以该
词汇表术语作为
名称,序列化为由该 DataSchema
子类实例序列化得到的 JSON 对象的成员。
ObjectSchema 实例中赋给
properties 的值 MUST
序列化为 JSON 对象。
DataSchema 实例中赋给
enum、required 和
oneOf 的值 MUST
序列化为 JSON 数组。
ArraySchema 实例中赋给
items 的值 MUST
序列化为 JSON 对象,或包含 JSON
对象的 JSON 数组。
下面给出一个 TD 片段数据模式成员。注意,
周围对象可以是数据模式对象
(例如用于 input 和 output),也可以是
属性对象,后者会包含附加
成员。
术语 readOnly 和
writeOnly 可用于指示哪些数据
项在读取交互中交换(即读取
属性时),以及哪些在写入交互中交换(即
写入属性时)。当非常规物的属性在
读取和写入时表现出不同数据时,这可作为一种权宜方法;
这种情况可能出现在用物描述来增强
现有设备或服务时。
下面给出一个使用 readOnly 和
writeOnly 的 TD 片段:
{
// ...
"properties": {
"status": {
"description": "Read or write On/Off status.",
"type": "object",
"properties": {
"latestStatus": {
"type": "string",
"enum": ["on_value", "off_value"],
"readOnly": true
},
"newStatusValue": {
"type": "string",
"enum": ["on_value", "off_value"],
"writeOnly": true
}
},
"forms": [...]
}
}
// ...
}
当读取 status 属性时,
状态数据会使用负载中的 latestStatus
成员返回。要更新 status
属性,必须通过负载中的
newStatusValue 成员提供新值。
作为一项附加特性,物描述实例
允许在数据模式内使用 unit 成员。
这可用于将计量单位关联到
数据项。其字符串值可以自由选择。
然而,建议选择在知名词汇表中定义的单位。有关
示例,见 7. TD 上下文扩展。
物描述的基于 JSON 的序列化由
媒体类型 application/td+json
或 CoAP Content-Format ID 432 标识(见 13.
IANA 考量)。
在若干上下文中,对物描述的基于 JSON 的 序列化进行自动验证是有用的。形式上, 有效的 TD 满足本规范中的所有断言, 但并非所有断言都能仅根据 JSON 序列化进行验证,例如,列在 9. 行为断言下、 将 TD 与其所描述物的行为相关联的断言。扩展也 存在问题,因为即便给出了用于验证某个 扩展的形式化元数据,在部署中动态获取这些 元数据也可能带来隐私风险。因此,在本 节中,我们命名并定义适用于不同上下文的 各种验证级别。
这一验证级别包括本文档中规范性表格所隐含的 所有断言,以及那些仅查看 TD 本身即可 检查的断言。
最小验证适用于验证需要自包含的场景 (例如,隔离网络上的设备)。 它不会尝试验证上下文扩展和 词汇表。
实践中,可以使用 JSON Schema 结合少量抽查来验证这些断言, 例如检查安全模式名称是否具有匹配的 定义。
这一验证级别包括 6.5.1 最小 验证所涵盖的全部内容,以及对语义 定义的基本验证。
基本验证适用于网络访问可用且不会造成隐私 风险,并且计算需求相对不受限制的情况。 例如,它适用于网关,但不适用于端点, 因为需要语义处理。它可以对扩展进行基本验证, 具体来说,是验证所使用的词汇表已被定义。
在这种情况下,可以使用上下文定义文件和 SHACL 定义来验证附加断言,并检查 TD 的语义一致性。 此外,如果能够获取扩展词汇表的上下文定义和 SHACL 约束,那么这些也可用于 验证扩展。
完整验证确认本文档中的所有断言均已满足, 包括 9. 行为断言中给出的、 用于确认 TD 与其所描述的物一致的断言。
这一验证级别适用于开发期间、发布之前, 以及可能在安装之后。开发期间的验证必须 在测试物上进行。此类物的实例实际安装时, 需要使用适当的每实例标识符和 URL 更新 TD, 因此为了获得最大保证,现场验证必须在安装 之后进行。
本节是非规范性的。
除了 5. TD 信息模型中的标准 词汇表定义之外, WoT 物描述还提供了从附加命名空间添加上下文 知识的可能性。该机制可用于通过附加 (例如特定领域的)语义来丰富物描述实例。 它也可用于在将来导入附加的协议绑定或新的 安全方案。
对于此类TD 上下文
扩展,物描述使用 JSON-LD
[json-ld11] 中已知的
@context 机制。
使用TD 上下文
扩展时,
Thing
类的
@context 值是一个
数组,其中包含类型为 anyURI 的附加元素
用于标识 JSON-LD 上下文文件,或包含按
5.3.1.1 Thing中定义的命名空间 IRI 的
映射。
6.1 到 JSON
类型的映射中针对复杂类型的序列化规则定义了
扩展 @context 名称-值
对的序列化。下面给出一个带有TD 上下文扩展的片段:
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"eg": "http://example.org/iot#",
"cov": "http://www.example.org/coap-binding#"
},
"https://schema.org/"
],
// ...
}
TD
上下文扩展允许在
物描述实例中使用附加的
词汇表术语。
如果包含的命名空间基于
RDF Schema 或 OWL 所提供的那些类
定义,则可以通过将实例关联到
这样一个外部类
定义,来对物描述的任何类实例进行语义标注。
这是通过向
@type 名称-值对赋予一个类名称,或在其数组值中包含类名称以表示多个
关联/标注来完成的。按照
6.1 到 JSON
类型的映射中的序列化规则,@type 会被序列化为 JSON
字符串或 JSON 数组。@type 是 JSON-LD
关键字 [json-ld11],用于设置节点的类型。
TD 上下文扩展还允许在物 描述的任何类实例内包含附加的 名称-值对和明确定义的值。这些对和值 通过所包含的词汇表术语定义,并分别 序列化为相应 JSON 对象中的附加成员,或现有成员的值。 示例包括物的附加版本元数据,或数据 项的计量单位。
接下来的小节展示了物描述中不同 类型本体的一些使用样例。
下面的示例 TD 片段提供了来自
@context 中所给不同外部上下文文件的附加元数据
术语。版本信息容器通过添加所用软件的
附加版本信息(s:softwareVersion)得到扩展。schema.org 用于提供
序列号和组织信息,例如该物的公司名称。
SAREF
本体用于提供该物的语义上下文
(saref:TemperatureSensor),而对于
temperature 属性的单位
赋值,则使用
Ontology of Units of Measure (OM)。
请注意,这些词汇表和 本体用作示例。可以根据应用领域和用例 使用其他词汇表和本体。
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"saref": "https://w3id.org/saref#",
"om": "http://www.ontology-of-units-of-measure.org/resource/om-2/",
"schema": "https://schema.org"
}
],
"version": {
"instance": "1.2.1",
"schema:softwareVersion": "1.0.1"
},
"schema:serialNumber": "4CE0460D0G",
"schema:manufacturer": {"name": "CompanyName"},
// ...
"@type": "saref:TemperatureSensor",
"properties": {
"temperature": {
"description": "Temperature value of the weather station",
"type": "number",
"minimum": -32.5,
"maximum": 55.2,
"unit": "om:degreeCelsius",
"forms": [...]
},
// ...
},
// ...
}
在许多情况下,TD 上下文扩展可 用于标注数据模式的若干部分,以便能够 对物理世界对象的状态信息进行语义处理, 这些状态信息由交互期间交换的数据表示 (例如在响应负载中)。例如, 可以在TD 文档中嵌入 对该状态信息的 RDF 语义描述,并且 可以将数据模式的各个部分分别标注为引用 该 RDF 建模的物理世界对象状态的特定部分。
下面的 TD 片段使用 SAREF 来描述
一盏灯的状态。外部词汇表术语
ssn:forProperty 取自 SSN,即
Semantic
Sensor Network Ontology [VOCAB-SSN],
用于将
status 属性的数据模式与物理
世界对象的实际开/关状态相链接。
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"saref": "https://w3id.org/saref#",
"ssn": "http://www.w3.org/ns/ssn/"
}
],
"id": "urn:uuid:67c9122b-2680-4e1a-b41c-5af07edba1f4",
"@type": "saref:LightSwitch",
"saref:hasState": {
"@id": "urn:uuid:67c9122b-2680-4e1a-b41c-5af07edba1f4/state",
"@type": "saref:OnOffState"
},
// ...
"properties": {
"status": {
"ssn:forProperty": "urn:uuid:67c9122b-2680-4e1a-b41c-5af07edba1f4/state",
"type": "string",
"forms": [{"href": "https://mylamp.example.com/status"}]
},
"fullStatus": {
"ssn:forProperty": "urn:uuid:67c9122b-2680-4e1a-b41c-5af07edba1f4/state",
"type": "object",
"properties": {
"statusString": { "type": "string" },
"statusCode": { "type": "number" },
"statusDescription": { "type": "string" }
},
"forms": [{"href": "https://mylamp.example.com/status?full=true"}]
},
// ...
},
// ...
}
在 示例 2中,
物的状态由
status 可供性本身给出,而可能的状态
变化由 toggle 可供性给出。换言之,
物理世界对象的状态直接提供了该物的
交互
可供性。这种设计对于简单情况是令人满意的。
然而,在更复杂的情况下,同一物理状态可能有
多个可供性可用。在上面的示例中,
fullStatus 属性为该灯的状态提供了一个
替代的、更详细的表示。
对于建筑、农业或 智慧城市等许多用例,需要基于位置的数据。 这些信息可以在物描述中以 不同方式提供,并且可根据用途(例如室内、室外) 依赖不同类型的位置本体(例如 [w3c-basic-geo]、 schema.org)。另见 [sdw-bp]。
下面的 TD 片段使用
[w3c-basic-geo]
本体中的 lat 和
long,在物的顶层提供静态纬度和经度
元数据。
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"geo": "http://www.w3.org/2003/01/geo/wgs84_pos#"
}
],
"@type": "Thing",
"geo:lat": "26.58",
"geo:long": "297.83",
// ...
"properties": {
// ...
}
}
在某些用例中,基于位置的元数据必须
在交互层级提供,例如作为一个返回
基于 schema.org 的最新 longitude、latitude
和 elevation 值的
属性提供:
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"schema": "https://schema.org#"
}
],
// ...
"properties": {
"position": {
"type": "object",
"@type": "schema:GeoCoordinates",
"properties": {
"longitude": { "type": "number" },
"latitude": { "type": "number" },
"elevation": { "type": "number" }
},
"forms": [{"href": "https://robot.example.com/position"}]
},
// ...
},
// ...
}
如果数据模型中希望对例如
longitude、latitude 和
elevation 使用不同名称,
则可以使用
jsonld:context 将术语链接到某个本体中的
特定词汇表(另见
[JSON-SCHEMA-ONTOLOGY],
第 3.3 节“为数据
实例定义 JSON-LD 上下文”):
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"schema": "https://schema.org#"
}
],
// ...
"properties": {
"position": {
"jsonld:context": {
"schema": "https://schema.org/",
"long": "schema:longitude",
"lat": "schema:latitude",
"height": "schema:elevation"
},
"type": "object",
"properties": {
"long": { "type": "number" },
"lat": { "type": "number" },
"height": { "type": "number" }
}
}
},
// ...
}
借助物描述中的TD
上下文扩展,可以通过来自 WoT Binding Registry
[WOT-BINDING-REGISTRY] 的绑定
规范来补充通信元数据,
这些绑定规范通过附加词汇表术语添加,并被序列化
到表示 Form 实例的 JSON 对象中。
更多信息请见 8. 绑定。
最后,未包含在
5.3.3 安全
词汇表
定义中的新安全方案,可以使用TD 上下文扩展
机制导入。此示例使用一个虚构的 ACE 安全方案,
该方案基于 [RFC9200],
并且在此示例中由位于
http://www.example.org/ace-security# 的命名空间定义。
附加安全方案
MUST 是类 SecurityScheme 的子类。
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"cov": "http://www.example.org/coap-binding#",
"ace": "http://www.example.org/ace-security#"
}
],
// ...
"securityDefinitions": {
"ace_sc": {
"scheme": "ace:ACESecurityScheme",
// ...
"ace:as": "coaps://as.example.com/token",
"ace:audience": "coaps://rs.example.com",
"ace:scopes": ["limited", "special"],
"ace:cnonce": true
}
},
"security": ["ace_sc"],
"properties": {
"status": {
// ...
"forms": [{
"op": "readproperty",
"href": "coaps://rs.example.com/status",
"contentType": "application/cbor",
"cov:methodName": "GET",
"ace:scopes": ["limited"]
}]
}
},
"actions": {
"configure": {
// ...
"forms": [{
"op": "invokeaction",
"href": "coaps://rs.example.com/configure",
"contentType": "application/cbor",
"cov:methodName": "POST",
"ace:scopes": ["special"]
}]
}
},
// ...
}
请注意,5.3.3 安全词汇表 定义中定义的所有安全方案已经是 TD 上下文的一部分, 不需要通过TD 上下文扩展包含。
从消费者发送到物以及从物返回的每条消息,
尽管有 WoT 提供的属性–动作–事件抽象,
仍然需要通过网络协议传输。Forms 层级中的
操作需要绑定到消息在网络上应当呈现的形式。
因此,WoT 物描述中的每个 form 都需要有一个提交目标,
该目标由 href 成员给出,如 Form 中所示。例如,如果目标
以 http 或 https 开头,消费者可以推断该
物实现了
基于 HTTP 的协议绑定,
并且应当预期在此 form 的实例中出现 HTTP 特定术语。更多说明和示例见
8.1.1 协议绑定。
此外,由可供性层级中的数据模式描述的负载
需要被序列化为某种数据格式,并通过网络协议发送。
与操作绑定到协议消息的方式类似,
数据模式会绑定到由
contentType 或 Form 中提供的协议特定术语
指示的数据格式。根据这些术语,消费者
可以推断所需的序列化方法,并将应用层数据
转换为要在网络协议上传输的数据。类似地,
对于来自物的消息,消费者可以反序列化数据
并将其呈现给应用层。例如,一个用
Python 实现的消费者
可以读取 application/json 作为
contentType 的值,并将 Python dictionary 数据
结构序列化为 JSON 对象。更多说明和示例见
8.1.2 负载绑定。
上述机制在 Web of Things 中称为绑定,
一个具体示例在
图 5 中通过一个机器人手臂的 TD
摘录来说明,其中包含 HTTP 和 JSON 绑定。在这里,消费者
打算调用机器人手臂的一个动作
(goTo),以便将其移动到 x
等于 12 且 y 等于 100 的位置。为此,它会创建正确的
负载,对其进行序列化,并使用正确的协议
选项发送。物通过网络接收消息,并
以与其 TD 对应的消息进行响应。其他
协议、负载格式和/或它们的组合也是
可能的,并在 8.1 绑定
机制中解释。
总之,绑定使物描述能够以特定方式适配 某个特定协议、数据负载格式,或二者同时适配。 这是通过 URI 方案、附加描述性词汇表、物模型和示例来完成的, 其目标是同时指导物和消费者的实现者。 本节解释整体机制,并给出创建新绑定的基本指导。 [WOT-BINDING-REGISTRY] 包含现有绑定的注册表(列表),以及向该 注册表注册新条目所需遵循的要求。
在为某个特定 IoT 设备生成 TD 时, 可以使用相应的绑定来查找需要在物 描述中提供的通信元数据。 图 6 展示了绑定的使用方式。 基于协议或媒体类型,会创建一个 TD。 处理 TD 的消费者通过包含相应的协议栈和媒体类型编码器/解码器, 并根据 TD 中给出的信息(例如消息的序列化格式和 header 选项) 配置该栈(或其消息),来实现 TD 中存在的所需绑定。
本规范的编辑还建议阅读 [WOT-ARCHITECTURE] 中的相关章节, 例如 WoT Binding Templates 构建块、 超媒体控件、 协议绑定和媒体 类型。
[WOT-THING-DESCRIPTION]
定义了抽象操作,例如
readproperty、invokeaction 和
subscribeevent,这些操作描述了执行
物描述中 form
所描述操作的预期语义。为了在可供性上
执行这些操作,需要将操作绑定到协议。
换言之,form 需要包含消费者例如通过该 form 中的协议读取属性所需的
全部信息。
大多数协议都有一组相对较小的方法,
这些方法定义消息类型,即消息的语义意图。
REST 和 PubSub 架构模式会产生具有不同方法的
不同协议。每个目标协议都可能为类似操作指定不同的方法名称,
并且不同协议中类似方法名称之间可能存在语义差异。
此外,物
可能使用不同方法来执行某个特定 WoT
操作。例如,一个物可以使用 HTTP POST 请求
执行 writeproperty 操作,
而另一个物可以使用 HTTP PUT。由于这些原因,
物描述需要能够按操作指定要使用的方法。
REST 和 PubSub 协议中常见的方法包括
GET、PUT、POST、DELETE、PUBLISH 和 SUBSCRIBE。
绑定规范描述了这些现有方法及其相关词汇表如何在
物描述中使用,以
绑定到 WoT 操作。这是通过定义协议的
URI 方案,并将协议方法映射到诸如
readproperty、invokeaction 和
subscribeevent 等抽象 WoT 操作来完成的。
在某些情况下,还会提供附加说明,以解释
在不同协议使用场景下应如何使用词汇表术语。
下面的示例展示了 HTTP 和 Modbus
协议中 readproperty 操作的绑定实例。
请注意,这些只是示例;请始终参考相应的绑定规范,
以了解相关词汇表术语及其
值。
|
示例 53:将
readproperty 操作绑定到 HTTP 的绑定实例
|
示例 54:将
readproperty 操作绑定到 Modbus 的绑定实例
|
上面示例中的 form 元素传达了 以下陈述:
example.com 的端口
80 上的资源 props/temperature
执行 HTTP GET 请求,对主题属性可供性执行
readproperty
(根据 [RFC2616],假定使用端口 80)。
readCoil 函数,对 IP 地址为
127.0.0.1、unitID 为
1、端口为 60000
的设备中 coil
4 上的主题属性可供性执行
readproperty
这些绑定实例及其陈述也适用于其他操作和协议。
下面是 invokeaction 和
subscribeevent 的示例:
|
示例 55:将
invokeaction 操作绑定到 HTTP 的绑定实例
|
示例 56:将
subscribeevent 操作绑定到 MQTT 的绑定实例
|
上面示例中的 form 元素传达了 以下陈述:
192.168.1.32 的端口
8081 上的资源 example/levelaction
执行 HTTP POST 请求,对主题动作可供性执行
invokeaction。
iot.platform.com 的端口
8088 上的 MQTT
broker,然后订阅主题
thing1/events/overheating,
对主题事件可供性执行 subscribeevent。
在某些情况下,需要包含协议的 header 选项
或其他参数。鉴于这些内容高度依赖于协议,
请参考 Web of
Things (WoT) Binding Registry 中列出的绑定。此外,
协议可能已经定义了可用于某些交互类型的子协议。
例如,为了使用 HTTP 接收异步通知,
某些服务器可能支持 long polling(longpoll)、WebSub
[WebSub]
(websub)以及 Server-Sent Events
[eventsource]
(sse)。
如 [WOT-ARCHITECTURE] 中所定义,
子协议是协议的一种扩展机制。子协议可以要求
一系列协议消息,或要求消息负载具有特定结构,
这些负载在该子协议内部可以具有自己的语义。
子协议的使用通过
subprotocol 字段表示,如
[WOT-THING-DESCRIPTION]
中所定义。它可以用于 form 实例中,以指示
使用这些协议之一,例如具有特殊 HTTP 用法的
long polling:
{
"op": "subscribeevent",
"href": "https://mylamp.example.com/overheating",
"subprotocol": "longpoll"
}
subprotocol 术语可取的值
不受 [WOT-THING-DESCRIPTION]
约束,因为不同协议可以具有不同的
子协议。相应地,子协议与其所扩展的协议相关联,
并且应与 forms 的 href
(或 base)中指示的协议一起理解。
对于 WebSockets,可以使用 IANA 注册的 Websocket 子协议
[iana-web-socket-registry]。
对于 CoAP,可以使用
"subprotocol":"cov:observe" 来描述
[RFC6741]
所定义的异步观察操作。
子协议可以作为协议绑定
规范的一部分进行定义和解释。
协议绑定规范包含的词汇表会扩展 [WOT-THING-DESCRIPTION] 中的词汇表。这意味着 TD 被消费的方式,以及与物发生交互的方式, 会适配这些词汇表。下面的步骤解释了这一过程 通常是什么样的。
href 成员以及 base
(如果存在),并识别协议。
subprotocol 或协议绑定引入的其他词汇表术语。
与物交换的交互可供性数据 SHOULD 符合
TD 中存在的数据模式和
内容类型。
与操作对应的数据模式可在表 表 28 中找到。
因此,以下要求适用于物和消费者:
[WOT-THING-DESCRIPTION]
定义了两种机制,用于描述通过任何协议传输的消息负载
可以是什么样的。首先,媒体类型
[IANA-MEDIA-TYPES] 描述了通过协议发送和接收数据所使用的
序列化方式。它们在 TD 的 Forms 中通过
contentType 表示,该术语对每个交互可供性都是
强制的。其次,它定义了数据模式概念,用于描述
与媒体类型一起使用的消息结构。
二者的组合允许在 TD 中描述任何消息,
从而使物和消费者能够正确地序列化和
反序列化消息。
在本节余下的 8.1.2.1 内容 类型和 8.1.2.2 数据 模式中,可以看到负载绑定可能呈现形式的示例。
内容类型包括媒体类型以及媒体类型可能具有的参数, 并使序列化文档能够被正确处理。这样, 消息就可以以任意格式交换,并允许应用的上层 适配不同格式。在某些情况下,例如图像、视频或任何 非结构化数据,内容类型足以描述负载; 但在 JSON([RFC8259]) 等情况下,通常会提供数据模式,如 8.1.2.2 数据 模式中所解释。
例如,一个数字负载可以分别序列化为
JSON 或 XML,并在 forms 的
contentType 中分别以
application/json 或
application/xml 指示。还可以通过加号
(+)或分号(;)记法进行进一步
参数化。
在下面的示例中,可以看到带有 JSON 和 plain text
内容类型及附加参数的 form 元素。在此特定情况下,
这些 forms 描述了使用
http 或 coap 读取该属性会产生
不同内容类型。对于结构化媒体类型,通常会在可供性层级
提供数据模式,如
8.1.2.2 数据
模式和 5.3.2 数据模式
词汇表定义中所解释。然而,对于图像和视频等非结构化
数据,通常没有可用的数据模式。
{
"forms":[
{
"href": "http://example.com/properties/temperature",
"op": "readproperty",
"contentType": "application/json"
},
{
"href": "coap://example.com/properties/temperature",
"op": "readproperty",
"contentType": "text/plain;charset=utf-8"
}]
}
其他内容类型也可以在 TD 中表达。 在下面的列表中,可以找到不同内容类型变体的示例。 这些内容类型可以替换 示例 58中的内容类型。
image/jpeg:JPEG 图像video/mp4:MP4 视频application/octet-stream:通用
二进制流如 5.3.2 数据模式 词汇表定义中所解释,数据模式描述 与媒体类型一起使用的消息结构。 虽然它在很大程度上受到 JSON Schema [json-schema] 启发,但它也可用于描述其他负载类型,例如 [XML]、 字符串编码的图像、整数的位表示等。 除媒体类型之外,还 SHOULD 使用数据模式。
根据具体情况,消息结构可以是从简单数字到 数组,或具有多层嵌套的对象等任何形式。 现有 IoT 平台和标准具有某些负载格式, 并且数据结构方式有所变化。如 5.3.2 数据模式 词汇表定义中所解释,数据模式可以在 TD 的以下位置之一使用:
input 和
output 词汇表术语用于
在双向交换数据时提供两个不同的模式,
例如调用带输入参数的动作可供性并接收
状态信息的情况。
data、
dataResponse、subscription
和 cancellation 分别用于描述由暴露物传递事件数据时的
负载、事件传递时用于回复的负载、
订阅事件所需的负载,以及取消从暴露物
接收事件数据所需的负载。
uriVariables 可以描述
需要以字符串形式提供在请求 URI 内的数据。下面是一个简单 JSON 对象负载 及其相应数据模式的示例。来自各种 IoT 平台和标准的示例可在 E. 来自 IoT 平台和标准的负载与数据模式 示例中找到。
|
示例
59:简单 JSON 对象
负载
|
示例 60:简单 JSON
对象负载的 DataSchema
|
在 IoT 平台或 OPC-UA、BACnet 等标准中, 可以指定协议、媒体类型和数据结构。在这些情况下, 其绑定 规范可以依赖一组8.1.1 协议绑定和8.1.2 负载绑定,也可以 同时指定 协议、媒体类型和数据结构。
在 IoT 平台中,可能存在同时使用 HTTP 与特定 JSON 负载结构的要求。 因此,相应的绑定 规范会提供物模型和 TD 示例, 以允许对多个绑定进行语义分组。 这首先需要有一个用于 HTTP 和 JSON 的 绑定 规范。
在 OPC-UA 或 BACnet 等标准中,绑定 规范包含关于协议和 媒体类型的要求,也可能包含关于数据结构的要求。 因此,该 绑定 规范本身就足以指定 绑定实例 应当是什么样子。
Web of Things 还定义了一种配置文件机制, 允许降低实现工作量。配置文件构建在现有绑定之上, 通过约束 TD 的灵活性来实现。这类约束可以是绑定、 语义上下文、链接关系、安全方案和 发现机制。通过这些约束,它们在绑定之上提供了 附加的互操作性保证。
目前在 [WOT-PROFILES] 中规定的配置文件机制 并不完全遵循上述机制。不过, 对于配置文件机制的未来方向已有共识。 一旦配置文件机制得到更新,本节将相应更新。
例如,一个配置文件可以约束
readproperty 操作使用 HTTP GET
方法,并要求负载始终序列化为 JSON。
配置文件的使用由 TD 中的 profile 术语指示,
该术语是一个指向配置文件定义的 URI。
消费者如何使用配置文件,在
[WOT-PROFILES]
规范的配置文件
机制一节中解释。
以下断言涉及 WoT 系统组件的行为, 而不是 TD 的表示或信息模型。不过, 请注意 TD 是描述性的,尤其可以用于描述 已存在的网络接口。在这些情况下,不能作出 约束这类已存在接口行为的断言。 相反,这些断言应被解释为对 TD 准确表示 这类接口的约束。
为了实现安全互操作,安全配置 需要准确反映物的要求:
某些安全协议可能会动态请求认证 信息,包括所需的编码或加密方案。 上述要求的一个结果是,如果某个协议请求了物描述中未声明的 安全凭证形式,或请求了未声明的编码或加密方案, 则该物描述应被视为 无效。
TD 中提供的数据模式应准确表示所描述 物在 TD 中指定的交互中返回和接受的数据负载。 一般而言,消费者应严格遵循 数据模式,不生成 WoT 物描述中未给出的任何内容, 但应接受来自物的、 WoT 物描述中未显式给出的附加数据。一般而言, 物由 WoT 物描述进行描述, 但消费者在与物交互时 被约束为遵循 WoT 物描述。
ObjectSchema 和
ArraySchema(当 items 是
DataSchema 的数组时),其中返回的数据中可以有
附加属性或项。其行为如
[JSON-SCHEMA]
中定义的 "additionalProperties":true 或
"additionalItems":true。
ObjectSchema 和 ArraySchema
(当 items 是
DataSchema 的数组时),其中返回的数据中可以有附加
属性或项。其行为如
[JSON-SCHEMA]
中定义的 "additionalProperties":true 或
"additionalItems":true。
下图说明物模型和物 描述之间的关系。物模型主要描述 交互可供性,例如属性、动作和事件,以及公共元数据。 当一个物 描述依赖物模型被实例化时, 它 SHOULD 根据该 物模型是有效的。 这一范式可以与面向对象编程中 用于创建对象(~物描述)的抽象类或接口定义 (~物模型)相比较。
物 模型是对接口以及与物的属性、动作和事件进行 可能交互的逻辑描述, 然而它不包含 物实例特定 信息,例如具体的协议用法(例如 IP 地址),甚至序列号和 GPS 位置。不过, 物模型允许包含例如安全方案, 如果它们适用于模型所描述的整个实例类别。 它们可能有 URL(例如 token 服务器), 这些 URL 可能需要省略或参数化(使用 模板),不过在许多情况下也可能给出。
物
模型可以用与物描述相同的基于 JSON 的格式序列化,
该格式也允许 JSON-LD 处理。
注意,由于缺少某些强制术语,物
模型不能像物
描述实例那样进行验证。
这意味着任何未使用占位符类型的术语,
仍然使用TD 信息
模型中声明的类型。例如,
minimum 的值需要是
integer,除非使用了占位符。
可以使用该 JSON Schema来验证序列化为 JSON 的 TM 实例。
物
模型通过顶层 @type 被识别。
物模型定义
MUST 在顶层使用关键字
@type,其值为字符串类型,或
数组类型,且分别等于或包含
tm:ThingModel。 此外,
为了将其识别为 JSON-LD 文档,物模型定义
MUST 在顶层使用关键字
@context,规则与物描述相同。 前缀 tm 在
物描述的
上下文中定义,并指向物模型命名空间,如
4. 命名空间中所定义。意图是
tm 上下文中的词汇表只在
物
模型定义中使用,并在生成
物描述时被
移除或替换(另见 10.4
物描述
实例的派生)。
一个物模型 MAY 不包含实例特定的协议 绑定和安全信息,例如端点 地址。 因此,物模型定义即使没有 forms、base、securityDefinitions 和 security 等 JSON 成员,也 是有效的。物模型即使使用了这些 JSON 成员 (例如作为模板),也是有效的; 不过会省略嵌套的强制成员,例如 href。
在物模型定义的上下文中, 引入了可用于 物 建模的特定特性。
当物模型
定义
随时间发生变化时,这一点 SHOULD
反映在 version 容器中。 基于字符串的
术语 model 用在
version 容器内,用于提供这类版本
信息,例如 [SEMVER]。以下
片段展示了在物模型实例中使用 model。
{
// ...
"@type": "tm:ThingModel",
"title": "Lamp Thing Model",
"description": "Lamp Thing Description Model",
"version" : {"model": "1.0.0"},
// ...
}
由于
物模型的定义,
术语 instance MUST 在
version
容器中省略。
当物 模型被更新并具有新版本时,这可能 影响其他使用扩展和导入特性的物 模型(见 10.3.2 扩展和 导入一节)。在某些情况下,也有必要在文件名和/或 相应 URL 中反映新版本,以标识该版本。
物
模型可以通过在
links 定义中声明的
tm:extends 机制来扩展现有物模型:当一个物模型
扩展另一个物模型时,MUST 使用至少一个
links 条目,其中 "rel":
"tm:extends" 指向要被扩展的物模型。
该物
模型将继承被扩展
物
模型的所有定义。可以通过从现有 TD 信息模型
(5. TD 信息
模型)提供更多 JSON
名称-值对,或使用上下文扩展概念(7. TD
上下文扩展),
用更多元数据扩展现有定义。物模型也可以
覆盖现有定义,例如
title(s) 和 maximum 等。
对此存在两个限制:一个
物
模型 SHOULD NOT 覆盖被扩展物模型的
properties、actions 和/或 events
映射中定义的
JSON 名称。
定义 SHOULD
NOT 以使可能的实例值相对于原始
被扩展定义不再有效的方式被覆盖。 这些断言保留了
被扩展物模型中的语义。例如,
不允许将来自被扩展物
模型的 "minimum":2
覆盖为 "minimum":0。
同时,覆盖为 "minimum":5 是可行的,
因为所有实例值始终会满足被扩展
物模型的限制(更多说明另见
图 图
8)。
假设我们有如下示例中提供的基本模型描述:
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"title": "Basic On/Off Thing Model",
"properties": {
"onOff": {
"type": "boolean"
}
}
}
现在,设计一个名为 'Smart Lamp Control' 的新设备类模型,
它将用作创建 TD 实例的模板。
该模型将复用
'Basic On/Off Thing Model' 的现有定义,并用
dim 属性对其进行扩展:
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"title": "Smart Lamp Control with Dimming",
"links" : [{
"rel": "tm:extends",
"href": "http://example.com/BasicOnOffTM",
"type": "application/tm+json"
}],
"properties" : {
"dim" : {
"title": "Dimming level",
"type": "integer",
"minimum": 0,
"maximum": 100
}
}
}
请注意,title 被覆盖,
并将在创建 TD 实例时使用(另见下一小节
10.4 物描述
实例的派生)。
tm:extends 特性只允许继承
一个物模型的所有定义。然而,在许多
用例中,只希望导入一个或多个现有
物模型定义的片段。
为了
导入一个或多个现有物
模型定义的片段,引入了 tm:ref 术语,
它提供了应该被复用的现有(子)定义的位置。
tm:ref 值 MUST
遵循以作为 URI [RFC3986](第
4.1 节)的文件位置开始,随后是 # 字符,再随后是
JSON Pointer [RFC6901]
定义的模式。 注意,该 URI 也可以为空,
表示同文档引用 [RFC3986](第
4.4 节)。在这种情况下,tm:ref 应被解释为
相对引用。每次使用
tm:ref 时,所引用的预定义
及其依赖项(例如通过上下文扩展)
MUST 被假定为在新定义的
定义处存在。
tm:ref 值的一部分
可能包含非 ASCII 字符,使用前需要进行 URL
(“百分号”)编码。在对
tm:ref 值应用转义之前,实现应
检查该值是否尚未被编码。
以下示例展示了一个新的 TM 定义,
它将示例
62中属性
onOff 的现有定义导入到新的属性定义
switch 中。
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"title": "Smart Lamp Control",
"properties" : {
"switch" : {
"tm:ref": "http://example.com/BasicOnOffTM.tm.jsonld#/properties/onOff"
}
}
}
作为使用 tm:ref 的相对导入示例,
以下物模型复用并增强(见下文)一个
genericTemperature
属性,将其用于两个更具体的属性中,分别描述
内部和外部温度值。
{
"@context": "https://www.w3.org/ns/wot-next/td",
"@type": "tm:ThingModel",
"title": "Multi Sensor",
"properties": {
"genericTemperature": {
"type": "number",
"unit": "C"
},
"innerTemperature": {
"tm:ref": "#/properties/genericTemperature",
"title": "The inner temperature",
"minimum": 10
},
"outerTemperature": {
"tm:ref": "#/properties/genericTemperature",
"title": "The outer temperature",
"description": "The outer temperature is measured in Kelvin",
"unit": "K"
}
},
"tm:optional": [
"/properties/genericTemperature"
]
}
在定义 "tm:ref" 的位置,可以添加附加
名称-值对。也允许覆盖来自被引用定义的名称-值对。
如果意图是
覆盖来自
tm:ref 的现有 JSON 名称-值对定义,
则 MUST 在提供新
值的 tm:ref 声明的同一层级使用相同的
JSON 名称。 覆盖
过程
MUST 遵循 [RFC7396] 中定义的
JSON Merge Patch 算法,其中被引用定义的内容会
使用新提供的 JSON 名称-值对进行修补。
注意,这些值也可以基于 JSON
object 或 array,或只是一个
null 值。null 会导致
目标中现有的 JSON 名称-值对被移除。
与
tm:extends 类似,为了保持语义含义,
定义 SHOULD NOT 以使可能的实例值
相对于原始被引用定义不再有效的方式被覆盖。
以下示例展示了一个新的 TM 定义,
它覆盖(maximum)、增强
(unit)并移除(title)
来自示例
63的现有定义。
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"title": "Smart Lamp Control",
"properties" : {
"dimming" : {
"tm:ref": "http://example.com/SmartLampControlwithDimming.tm.jsonld#/properties/dim",
"title": null,
"maximum": 80,
"unit": "%"
}
}
}
基于 JSON Merge Patch 算法,
{"title": null,"maximum": 80,"unit": "%"}
将作为被引用原始内容
{"title": "Dimming level", "type": "integer",
"minimum": 0, "maximum": 100} 的补丁。
tm:extends 和基于
tm:ref 的导入机制也可以在同一个
TM 定义中同时使用。以下示例扩展了
示例 62中的 TM,并分别从
示例
3和示例
63导入
status 和 dim 定义。
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"title": "Smart Lamp Control",
"links" : [{
"rel": "extends",
"href": "http://example.com/BasicOnOffTM",
"type": "application/tm+json"
}],
"properties" : {
"status" : {
"tm:ref": "http://example.com/LampTM.tm.jsonld#/properties/status"
},
"dimming" : {
"tm:ref": "http://example.com/LampWithDimmingTM.tm.jsonld#/properties/dim"
}
}
}
tm:extends 和基于
tm:ref 的导入机制显式支持传递
扩展(扩展层次结构)。例如,
假设有 3 个 TM:"A" 定义了对 TM "B" 的
tm:extends,而 "B" 自身定义了
对 TM "C" 的 tm:extends。因此,
"A" TM 扩展了 "B" 和 "C" 的所有定义。
导致
无限循环的递归扩展 MUST NOT 被
定义。
下图总结了本节中介绍的扩展和导入 TM
功能允许的覆盖行为。三个物模型使用
tm:ref 或 tm:extends 特性来
复用 Smart Lamp Control 物模型的 TM 定义。第一个
物
模型在 dimmer
属性中导入并将 maximum
值覆盖为 120。然而,这会导致可能的实例值
(运行时)不在 Smart Lamp
Control 物模型的原始
dim 定义中 0 到
100 的范围内。因此,这样的物模型定义
不被允许。第二个模型将属性
type 值覆盖为 number。同样,这可能
导致数值型 dim 值不被 Smart
Lamp Control 物
模型中原始 dim 类型定义(integer)接受。
最后一个模型以正确方式定义。
dim 的新范围所产生的可能实例值
也会满足原始
dim 定义。
在某些应用中,复用现有
物
模型定义并将它们组合到新的 IoT
系统中是有益的。一个例子是设计一个新的 Smart Ventilator,
由两个子/子级物模型定义组成,
例如一个 Ventilation 物模型,它提供
on/off 和 adjustRpm
能力;以及一个 LED 物模型,它提供
dimmable 和 RGB
能力。
这种组合可以通过使用
links 容器来引入。如果希望
提供一个物模型由
一个或多个(子)物模型组成的信息,则
links 条目 MUST
使用指向这些(子)物
模型的 "rel": "tm:submodel"。 可选地,
MAY 提供一个
instanceName,以便为组合的
(子)物
模型关联单独名称。 当组合多个类似的
物
模型定义并需要区分它们时,这很有用。
可以遵循不同策略,从组合的
物描述
由物模型定义生成。
默认建议是从每个父级
和子/子级物模型生成一个
对应的物描述
(另见 10.4
物
描述实例的派生)。组合关系可以通过
collection 和
item 关系类型反映在
物描述的 links 容器中。
这里给出一个基于 Smart Ventilation 的示例:
也可以生成单个 TD,其中包含顶层/父级 物模型的交互定义,以及所有 子/子级物模型的全部交互定义。 因此,生成过程 MUST 避免可能的名称 冲突。 以下示例展示了从 Smart Ventilator 物模型潜在生成的(自包含) 物描述。
{
"@context": "https://www.w3.org/ns/wot-next/td",
"title": "Smart Ventilator",
"securityDefinitions": {
"basic_sc": {
"scheme": "basic",
"in": "header"
}
},
"security": "basic_sc",
"links": [
{
"rel": "type",
"href": "./SmartVentilator.tm.jsonld",
"type": "application/tm+json"
}
],
"properties": {
"status": {
"type": "string",
"enum": [
"on_value",
"off_value",
"error_value"
],
"forms": [
{
"href": "http://127.0.13.232:4563/status"
}
]
},
"switch": {
"type": "boolean",
"description": "True=On; False=Off",
"forms": [
{
"href": "http://127.0.13.212:4563/switch"
}
]
},
"adjustRpm": {
"type": "number",
"minimum": 200,
"maximum": 1200,
"forms": [
{
"href": "http://127.0.13.212:4563/adjustRpm"
}
]
},
"R": {
"type": "number",
"description": "Red color",
"forms": [
{
"href": "http://127.0.13.211:4563/R"
}
]
},
"G": {
"type": "number",
"description": "Green color",
"forms": [
{
"href": "http://127.0.13.211:4563/G"
}
]
},
"B": {
"type": "number",
"description": "Blue color",
"forms": [
{
"href": "http://127.0.13.211:4563/B"
}
]
}
},
"actions": {
"fadeIn": {
"title": "fadeIn",
"input": {
"type": "number",
"description": "fadeIn in ms"
},
"forms": [
{
"href": "http://127.0.13.211:4563/fadeIn"
}
]
},
"fadeOut": {
"title": "fadeOut",
"input": {
"type": "number",
"description": "fadeOut in ms"
},
"forms": [
{
"href": "http://127.0.13.211:4563/fadeOut"
}
]
}
}
}
在某些情况下,希望不强制哪些交互
可供性是强制性的,并且不一定需要在
物描述
实例中实现。如果交互模型不是
物描述
实例中必须实现的内容,
物
模型定义 MUST 使用
JSON 成员名称 tm:optional。
tm:optional MUST 是顶层的 JSON 数组。
tm:optional 的值 MUST
提供 JSON Pointer [RFC6901]
对所需交互模型定义的引用。
tm:optional 的 JSON
Pointers MUST
解析为整个交互可供性映射定义。
以下样例展示了对事件交互
overheating 使用
tm:optional。
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"title": "Lamp Thing Model",
"description": "Lamp Thing Model Description",
"tm:optional": [
"/events/overheating"
],
"properties": {
"status": {
"description": "current status of the lamp (on|off)",
"type": "string",
"readOnly": true
}
},
"actions": {
"toggle": {
"description": "Turn the lamp on or off"
}
},
"events": {
"overheating": {
"description": "Lamp reaches a critical temperature (overheating)",
"data": {"type": "string"}
}
}
}
由于事件
overheating 不是强制的,因此它可以不在
物描述
实例中可用。
请注意,如果一个物模型定义中的可选定义
通过使用 tm:ref 被另一个
物
模型扩展,则它可以被覆盖:
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"title": "Lamp Thing Model (All Mandatory)",
"description": "Lamp Thing Model description expects all interaction affordances (status, toggle, and overheating)",
"links": [
{
"rel": "tm:extends",
"href": "./lampThingModel.tm.jsonld",
"type": "application/tm+json"
}
],
"events": {
"overheating": {
"tm:ref": "./lampThingModel.tm.jsonld#/events/overheating"
}
}
}
物
模型可以指定 TD
实例中应使用哪些术语,但它们的值并不具体,
要到 TD 实例化期间才首次知道。在已预先知道
TD 实例术语但不知道其值的情况下,
可以在物模型中 MAY 使用占位符标记。
当从物模型创建
TD 实例时,占位符标记
MUST 被替换为
具体值(例如 JSON number、JSON string、JSON
object 等)。 基于字符串的
占位符模式
MUST 遵循基于正则表达式
{{2}[
-~]+}{2} 的有效模式(例如
{{PLACEHOLDER_IDENTIFIER}})。
{{ 和 }} 之间的字符
用作占位符的标识符名称。
该标识符名称可用于在替换过程中识别占位符。 占位符
MUST 应用于 JSON
名称-值对的值中。 如果 JSON 名称-值对的非
字符串值具有占位符,则该值 MUST
(临时)被类型化为字符串。 在替换占位符之后,
例如创建物描述实例时,
原始类型会与相应替换后的值一起应用。
以下物模型示例定义了不同的 占位符。占位符映射用于应用 替换并转换预期值类型。
物 模型可以用作模板,以根据 5. TD 信息 模型和 6. TD 表示 格式两节中定义的限制生成物 描述。在此过程中,必须补充缺失的数据,例如 通信和安全元数据,以创建有效的物描述 实例。一个物模型 MUST 以 不会产生不一致的方式定义,否则会导致物 描述无法满足 5. TD 信息 模型和 6. TD 表示 格式中所描述的要求。 用于从物模型 派生物 描述实例的 TM-to-TD 生成器,会使用以下步骤将其转换为 部分 TD:
"rel":"tm:extends" 的
links 元素条目,MUST 从当前
部分 TD中移除@type 中的
tm:ThingModel 值 MUST 在
部分
TD实例中移除。tm:optional 中)
MUST 被接收到
部分 TD
实例中。tm:optional 中)
MAY 被接收到
部分 TD
实例中。最后,TM-to-TD 生成器会取得生成的 部分 TD,并 通过最后一步将其转换为物描述
securityDefinitions 和
security 和/或 6.3.9 forms 在
物描述
实例中补全。建议物
模型的 id 值提供一个占位符,例如
"id":
"urn:example:{{RANDOM_ID_PATTERN}}",
以用于 TD 生成过程。请避免在
id 模式中包含元数据。
遵循物模型的
物描述
实例可以携带关于其派生自哪种类型
物模型的信息。
在此上下文中,可以使用带
"rel": "type" 的链接概念
(另见 5.3.4.1
Link 一节),如下例所示:
请注意,一个 TD 一次只能是一个 TM 的实例。
这意味着对于物描述:
links 数组中带有
"rel": "type" 的条目最多
MUST 使用
一次。 如果希望在物描述中反映与其他物的所有关系,
可以考虑 TM 中的组合机制(见 10.3.3
组合一节)。
以下物模型扩展了
示例
63所示模型,并覆盖
dim 属性的
maximum 值
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "tm:ThingModel",
"links" : [{
"rel": "tm:extends",
"href": "http://example.com/SmartControlLampTM",
"type": "application/tm+json"
}],
"properties" : {
"dim" : {
"maximum": 200
}
}
}
从该物模型派生出的预期 物描述将是(应用 HTTP 绑定和 basic 安全之后):
{
"@context": ["https://www.w3.org/ns/wot-next/td"],
"@type": "Thing",
"title": "Smart Lamp Control",
"securityDefinitions": {
"basic_sc": {"scheme": "basic", "in": "header"}
},
"security": "basic_sc",
"links" : [{
"rel": "type",
"href": "url/to/SmartLampControlModifiedDimTM",
"type": "application/tm+json"
}
],
"properties" : {
"onOff": {
"type": "boolean",
"forms": [{"href": "https://smartlamp.example.com/onoff"}]
},
"dim" : {
"type": "integer",
"minimum": 0,
"maximum": 200,
"forms": [{"href": "https://smartlamp.example.com/dim"}]
}
}
}
一般而言,用于保护 WoT 系统的安全措施将取决于该系统可能 面临的威胁和攻击者,以及需要保护的资产价值。 关于 Web of Things 的安全(和隐私)考量的详细讨论, 包括可适配各种情形的威胁模型,见资料性文档 [WOT-SECURITY-GUIDELINES]。 许多 WoT 物与 Web 服务相似,并使用相同技术。 除了下面的特定安全考量之外,还应评估 Web 服务指南中讨论的安全风险和缓解措施,例如 OWASP Top 10 [OWASP-Top-10], 并在适用时加以处理。本节仅讨论与 WoT 物描述直接 相关的安全风险和可能的缓解措施。
WoT 物描述既可以描述安全的网络接口,也可以描述 不安全的网络接口。当物描述被改配到现有网络接口上时, 不应期望该网络接口的安全状态发生变化。
使用 WoT 物描述会引入以下各节中给出的安全 风险。每个风险之后,我们都会建议一些可能的缓解措施。
拦截和篡改 TD 可用于发起中间人攻击, 例如通过重写 TD 中的 URL,将访问重定向到能够 捕获或操纵数据的恶意中介。
拦截和篡改上下文定义文件 可通过修改词汇表解释来促成攻击。上下文扩展(见 7. TD 上下文扩展) 如果从 Web 上通过非安全连接加载,例如 HTTP, 就存在被攻击者更改的风险,并可能以危及安全的方式 修改TD 信息模型。
如 12.1 上下文获取中所建议, 在受约束的实现上,上下文定义文件 应预先安装,并使用安全的软件更新过程进行管理, 上下文 URL 仅用于标识已知上下文,而不用于获取它们。 因此,本考量仅在动态获取上下文定义文件 在其他方面不可避免时适用,例如在支持通用语义处理的 目录服务中。
在某些场景中,可能希望限制某些用户对一组物的访问范围 和持续时间。例如,如果 A 正在拜访 B 的家,B 可能希望 向 A 提供对车库门开启器和汽车充电器的临时且受限访问, 以便 A 可以使用它们。不过,范围可以受到限制, 使 A 无法访问这些物的某些管理功能 (例如,更改车库门可以保持开启的时长,或更改充电 速率)。此外,该访问应在预计 A 已离开之后过期, 例如一周之后。
能够访问一组 TD 的攻击者,例如访问 WoT Discovery 返回的 TD, 可能能够使用这些信息识别易受攻击的设备,并计划对其发动攻击。
auto 安全方案
MAY 被使用。
TD 中给出的许多字符串,尤其是
title/titles 和
description/descriptions 中携带的值,
意图是人类可读的。应用可以取得这些字符串
并用它们生成用户界面,例如列出一组可用物及其标题
和描述的 Web 仪表板。如果此类界面是通过字符串替换
天真地生成的,例如将这些字符串的值插入 HTML 模板中
标记的位置以创建最终 HTML,则原始字符串中的任何 HTML
标记都会在显示仪表板的浏览器上下文中被解释。
攻击者可能以各种方式在 HTML 中嵌入脚本,并使这些脚本
在用户交互时甚至自动执行(例如,在页面加载时或发生错误时,
后者可以被有意触发)。由于该字符串将由 TD
生产者生成,而仪表板将由不同来源生成,
这是一种跨站脚本(XSS)攻击形式。
见 RFC 8259,
第 12 节:JSON 不应使用
eval() 作为 JavaScript 进行解析。WoT 物描述旨在
成为用于物元数据的纯数据交换格式,而不是用于保存
可执行内容。不过,一个(无效的)TD 可能包含
JavaScript 代码,该代码在执行时可能产生危及系统安全的副作用。
eval() 函数)进行解析。[WOT-DISCOVERY]
中讨论了其他代码注入风险。
TD 中的其他字符串,例如为
title 和 description 给出的值,
在用于 SQL、HTML 或其他可执行上下文的模板之前,
应进行清理。不过,本风险专门讨论解析 JSON 时的
Javascript 注入风险。
JSON-LD 处理通常包括将短术语替换为更长的 IRI [RFC3987]。 因此,WoT 物描述在使用 JSON-LD 1.1 处理器处理时 可能会显著扩展,并且在最坏情况下,生成的数据可能消耗 接收方的全部资源,或导致可被利用的缓冲区溢出。
隐私风险将取决于物与可识别人员的关联, 以及可从这种关联获得的直接信息和推断信息。 关于 Web of Things 的隐私(和安全)考量的详细讨论, 包括可适配各种情形的威胁模型,见资料性文档 [WOT-SECURITY-GUIDELINES]。 本节仅讨论与 WoT 物描述直接相关的隐私风险和可能的 缓解措施。
使用 WoT 物描述会引入以下各节中给出的隐私 风险。每个风险之后,我们都会建议一些可能的缓解措施。
WoT 物描述可以使用 JSON-LD 1.1 处理器 [json-ld11] 进行求值,该处理器通常会 自动跟随指向远程上下文的链接(即 TD 上下文扩展,见 7. TD 上下文扩展), 从而在消费者未对每一个文件显式请求的情况下 传输文件。如果远程上下文由第三方提供, 这可能允许它们收集使用模式或类似信息,从而导致 私有信息的泄露,或泄露可用于推断私有信息的信息。 在 WoT 的情况下,攻击者还可以观察此类获取产生的网络流量, 并使用获取的元数据(例如目标 IP 地址)推断有关设备的信息, 尤其是在使用特定领域词汇表时。即使连接被加密, 这也是一种风险,并且与 DNS 隐私泄露有关。 另见 11.2 上下文拦截 和篡改,这是一种相关的安全风险,也可以通过以下 缓解措施避免。
包含标识符(id)的物描述
可能描述一个与可识别人员相关联的物。这类标识符
会带来各种风险,包括跟踪。不过,如果该标识符也是
不可变的,则跟踪风险会被放大,因为设备可能被出售或赠予
另一个人,而已知 ID 可用于跟踪该人。
TD 中使用的所有标识符
SHOULD 都是可变的,并且尤其
SHOULD 有一种机制在必要时更新
物的 id。
具体而言,物的
id 不应固定在硬件中。不过,这确实
与 Linked Data 的理想相冲突,即标识符是固定的 URI。
然而,作为策略,强烈建议部署在配置发生重大变化或
重新初始化时更新标识符。配置重大变化的示例包括
将物移动到新的局域网、分配新的域名,或
将物从一个 hub 注销并注册到新的 hub。
通常,表明所有权可能发生变化的配置变化
应导致创建新的标识符。如果希望在设备的运行阶段
进行更频繁的更改,可以放置一种机制,以便在作出更改时
仅通知授权用户标识符的变化。不过请注意,某些类别的
设备,例如医疗设备,在某些司法管辖区可能依法要求
不可变 ID。理想情况下,任何必需的不可变标识符
都应仅通过可供性提供,例如通过一个属性,其值只有在
适当认证和授权之后才能获得,并与 TD 标识符分开管理。
如果有必要将不可变标识符用作 TD 标识符,则应特别注意
保护包含此类不可变标识符的文件(例如物描述)的访问安全。
如上所述,TD 中的 id 成员可能
带来隐私风险。不过,即使按所述更新 id 以缓解其
跟踪风险,仍可能通过指纹识别将 TD 与特定物理设备
关联起来,并由此关联到可识别人员。
即使无法通过指纹识别识别特定设备实例, 也可能从 TD 中的信息推断设备类型,例如交互集合, 并使用这种类型推断关于可识别人员的私有信息, 例如医疗状况。
id。
如果消费者在其用例中不需要某些交互,则可以省略它们。
如果消费者无权使用某些交互,它们也可以同样被省略。TD 的 id 字段值可能变得可供
无法访问完整 TD 的实体使用。如果 id 的值包含
嵌入式元数据,例如设备类型或所有者,则这可能被用于推断
个人信息。
id
值 SHOULD NOT 包含
描述物或来自 TD 本身的元数据。 为管理 TD
而生成的任何临时 ID,例如数据库或目录服务的 ID,
SHOULD NOT
包含描述物或来自 TD 本身的元数据。 按
12.5
全局
唯一标识符中的建议使用随机 UUID 也能缓解此风险。
如果需要集中式权威来创建和分发全局唯一标识符, 则它们会带来隐私风险,因为第三方会知道这些 标识符。
id 字段有意不要求
全局唯一。有多种加密机制(例如随机 UUID)可用于
以分布式方式生成合适的 ID,而不需要中央注册表。
这些机制通常生成重复标识符的概率很低,
并且系统设计需要考虑这一点;例如,通过检测重复
并在必要时重新生成 ID。ID 的范围也不需要是全局的:
使用只在某个上下文中区分物的标识符是可接受的,
例如在家中或工厂内。TD
标识符 SHOULD 使用分布式
机制(例如 UUID)生成,该机制提供高概率的
唯一性。 TD
标识符 SHOULD NOT 使用集中式
权威生成。在许多地区,为了保护用户隐私, 对个人可识别信息的处理有法律要求, 即可与特定个人相关联的信息。当然, 这类信息可以由 IoT 设备直接生成。然而, IoT 设备的存在和元数据(物描述中存储的数据类型) 也可能包含或被用于推断个人可识别信息。 这些信息可以简单到某人拥有某种类型设备这一事实, 而这可能导致关于该人的附加推断。
处理一致性内容和非一致性内容的规则 在本规范中定义。
请查看当前 IANA 注册;将来 .td.json 和 .td.jsonld 也可能被允许。
处理一致性内容和非一致性内容的规则 在本规范中定义。
IANA 在 Constrained RESTful Environments (CoRE) Parameters 注册表内的 CoAP Content-Formats 子注册表中为媒体 类型分配紧凑的 CoAP Content-Format ID [RFC7252]。 WoT Thing Description 的 Content-Format ID 是 432, WoT Thing Model 的 Content-Format ID 是 -(待定)。
本节是非规范性的。
以下 TD 示例使用 HTTP、CoAP 和 MQTT 协议
绑定。这些 TD 具有上下文扩展,其假定
存在类似于
[HTTP-in-RDF10] 的 CoAP-in-RDF 和 MQTT-in-RDF 词汇表,
它们可分别通过命名空间
http://www.example.org/coap-binding# 和
http://www.example.org/mqtt-binding#
访问。请注意,位于
"https://www.w3.org/2022/wot/td/v1.1" 的 TD 上下文已经
包含 [HTTP-in-RDF10],因此 HTTP
上下文扩展可以直接使用。请注意,每个
绑定规范
都包含最新的词汇表术语和示例。
我们在下面看到的上下文扩展对 TD 消费者具有以下 指示:
"htv:methodName" 成员指示
消费者必须应用哪个 HTTP 方法(例如,
使用 "GET" 检索资源,或使用
"POST" 向资源发送数据)。
"cov:method" 成员指示消费者
必须应用哪个 CoAP 方法(例如,"GET"
对应 CoAP Method Code 0.01,"POST" 对应
CoAP Method Code 0.02,或 iPATCH 对应 CoAP Method
Code 0.07)。"mqv:controlPacket" 成员指示
消费者必须应用哪个 MQTT 命令(例如,
使用 "subscribe" 订阅某个主题,使用
"unsubscribe" 取消订阅)。
首先展示使用单一协议的 TD。然后,引入具有 多个协议的 TD,其中每个交互 可供性都有一个带有一种协议的 form。
物的特性列表:
物的特性列表:
192.168.1.187:1883
后面的 MQTT broker 提供的主题 /illuminance。
另见
MQTT Binding
物的特性列表:
temperature,它使用 Webhook
机制周期性地将最新温度值推送给消费者,
在该机制中,物向消费者提供的
回调 URI 发送 POST 请求。为描述这一点,
subscription 成员定义了一个只写
参数 callbackURL,该参数必须通过
subscribeevent form 提交。
只读参数 subscriptionID 由订阅返回。
然后,TemperatureSensor 会周期性地向
该回调 URI POST 一个由
data 定义的负载。要取消订阅,消费者必须按照
cancellation 中的描述,使用
subscriptionID 提交
unsubscribeevent form。或者,也可以使用
uriVariables 方法,它告知
消费者将
subscriptionID 字符串包含在必须使用 delete 方法调用的
URI 中(见标签页“带
uriVariables”)。在这种设置中,
cancellation 容器可以省略。
一般而言,可以通过使用
TD
上下文扩展包含合适的语义
标注,进一步自动化此示例。
除了向该物发送周期性 POST 请求之外,
消费者可以提供响应
数据,其中包含该物应何时提供下一个 POST 请求的信息。
这是通过使用
dataResponse 字段描述的。
物的特性列表:
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"cov": "http://www.example.org/coap-binding#",
"mqv": "http://www.example.org/mqtt-binding#",
"htv": "http://www.w3.org/2011/http#"
}
],
"title": "LampThing",
"id": "urn:dev:ops:32473-WoTLamp-1234",
"securityDefinitions": {
"nosec_sc": {
"scheme": "nosec"
}
},
"security": ["nosec_sc"],
"properties": {
"switchState": {
"type": "boolean",
"readOnly": true,
"observable": false,
"forms": [
{
"href": "http://example.com/light/switchstate",
"op": "readproperty",
"contentType": "application/json",
"htv:methodName":"GET"
}
]
},
"brightness": {
"type": "number",
"readOnly": true,
"observable": false,
"forms": [
{
"href": "coap://example.com/light/brightness",
"op": "readproperty",
"contentType": "application/json",
"cov:method": "GET"
}
]
}
},
"actions": {
"switchLight": {
"input": {
"type": "boolean"
},
"forms": [
{
"href": "http://example.com/switch/state",
"op": "invokeaction",
"contentType": "application/json",
"htv:methodName":"POST"
}
]
},
"setBrightness": {
"input": {
"type": "number",
"maximum":255
},
"forms": [
{
"href": "coap://example.com/light/brightness",
"op": "invokeaction",
"contentType": "application/json",
"cov:method": "POST"
}
]
}
},
"events":{
"concentration": {
"title": "Gas Concentration Event Stream",
"data":{
"type": "integer",
"minimum": -1,
"maximum": 65535
},
"forms": [
{
"href": "mqtt://broker.com",
"contentType": "application/json",
"op": "subscribeevent",
"mqv:filter": "application/deviceid/sensor/concentration",
"mqv:controlPacket": "subscribe"
}
]
}
}
}
物的特性列表:
brightness 属性可通过 HTTP
和 CoAP 读取,并可通过 MQTT 观察;concentration
事件可通过 CoAP 和 MQTT 订阅。在这种情况下,
消费者会根据其内部实现选择它能够支持的 form,
例如它是否具有 CoAP 协议栈。另见
HTTP Binding、
CoAP Binding 和
MQTT Binding。
{
"@context": [
"https://www.w3.org/ns/wot-next/td",
{
"cov": "http://www.example.org/coap-binding#",
"mqv": "http://www.example.org/mqtt-binding#",
"htv": "http://www.w3.org/2011/http#"
}
],
"title": "Lamp",
"id": "urn:dev:ops:32473-WoTLamp-5678",
"securityDefinitions": {
"nosec_sc": {
"scheme": "nosec"
}
},
"security": ["nosec_sc"],
"properties": {
"switchState": {
"type": "boolean",
"readOnly": true,
"observable": false,
"forms": [
{
"href": "http://example.com/light/switchstate",
"op": "readproperty",
"contentType": "application/json",
"htv:methodName":"GET"
},
{
"href": "coap://example.com/light/switchstate",
"op": "readproperty",
"contentType": "application/json",
"cov:method": "GET"
}
]
},
"brightness": {
"type": "number",
"readOnly": true,
"observable": true,
"forms": [
{
"href": "http://example.com/light/switchstate",
"op": "readproperty",
"contentType": "application/json",
"htv:methodName":"GET"
},
{
"href": "coap://example.com/light/switchstate",
"op": "readproperty",
"contentType": "application/json",
"cov:method": "GET"
},
{
"href": "mqtt://broker.com",
"mqv:filter": "application/deviceid/sensor/brightness",
"op": "observeproperty",
"mqv:controlPacket": "subscribe"
}
]
}
},
"actions": {
"switchLight": {
"input": {
"type": "boolean"
},
"forms": [
{
"href": "http://example.com/switch/state",
"op": "invokeaction",
"contentType": "application/json",
"htv:methodName":"POST"
}
]
},
"setBrightness": {
"input": {
"type": "number",
"maximum":255
},
"forms": [
{
"href": "coap://example.com/light/brightness",
"op": "invokeaction",
"contentType": "application/json",
"cov:method": "POST"
}
]
}
},
"events":{
"concentration": {
"title": "Gas Concentration Event Stream",
"data":{
"type": "integer",
"minimum": -1,
"maximum": 65535
},
"forms": [
{
"href": "mqtt://broker.com",
"contentType": "application/json",
"op": "subscribeevent",
"mqv:filter": "application/deviceid/sensor/concentration",
"mqv:controlPacket": "subscribe"
},
{
"cov:method": "GET",
"href": "coap://example.com/sensor/gasconcentration",
"contentType": "application/json",
"op": "subscribeevent",
"subprotocol": "cov:observe"
}
]
}
}
}
本节是非规范性的。
用于对以基于 JSON 的格式序列化的物描述 实例进行语法验证的 JSON Schema [JSON-SCHEMA] 文档可在 https://www.w3.org/ns/wot-next/td-schema 获得。 该 JSON Schema 不要求带有默认值的术语 必须出现。因此,带有默认值的术语是可选的。 (另见 5.4 默认值 定义)
本文档定义的物描述
允许通过使用 JSON-LD
[json-ld11] 中已知的
@context 机制添加外部词汇表,
并且这些外部词汇表中的术语可以与
5. TD 信息模型中定义的术语
一起使用。出于这个原因,
下面的 JSON schema 在这方面有意保持非严格。
如果不使用外部词汇表,则可以在不同
作用域/层级中将
additionalProperties schema 属性的值
true 替换为 false,
以执行更严格的验证。
本节是非规范性的。
请求和响应变化的不同情况在
5.3.4.2.2
响应相关
术语用法中说明。下面的表格以简洁方式总结这些情况。
表格从较简单的情况开始,例如
单个 contentType,然后进入较复杂的情况,
例如多个 contentType。在所有表格中,
消息都从物的视角来看,其中 input
表示从消费者发送到物的消息(例如,请求),
output 表示从物发送到消费者的消息
(例如,响应)。
这些情况已编号,可用于将它们与表格后的 示例关联起来。
| 情况 | 所需术语 | 说明 | 消费者行为 | 物行为 |
|---|---|---|---|---|
| 情况 1A:存在 input,不存在 output | form 内的 contentType |
contentType 仅指
input |
|
|
| 情况 1B:不存在 input,存在 output。 | form 内的 contentType。 |
contentType 仅指
output。 |
|
|
情况 1C:存在 input 和 output,消息使用相同
contentType。
|
form 内的 contentType。 |
contentType 同时指 input 和
output。 |
|
|
下表考虑了更多变化,这些变化与操作 input
可以接受不同 contentType,或 output 可以返回
不同 contentType 的情况相关。
可能存在一个交互可供性具有多个 forms 的情况。
具有多个 forms 的此类情况应被视为上表和下表中
情况的组合。
| 情况 | 所需术语 | 说明 | 消费者行为 | 物行为 |
|---|---|---|---|---|
情况 2A:存在单个 input 和单个 output,
消息使用不同的 contentType。 |
form 内的 contentType 和 response。
response 具有
不同值的 contentType。
|
form 层级中的 contentType 指
input,而 response 中的
contentType(response 层级)指
output
|
|
|
情况 2B:存在 input 和多个可能的 output,
消息使用相同的 contentType |
form 内的 contentType 和
additionalResponses。
可能需要
additionalResponses 数组项中的
schema。
|
form 层级中的 contentType 指
input 和普通 output。
additionalResponses 不需要
contentType,因为默认值规则
适用。这与存在实际单个 contentType 的情况
(情况 1C)相同。不过,
output 中可能传递不同的数据模式,需要 form 中的
additionalResponses
和 schema 术语。
|
见情况 1C | 见情况 1C |
情况 2C:存在 input 和多个可能的 output,
output
消息使用不同的 contentType |
form 内的 contentType、
additionalResponses 以及可能的
response。
additionalResponses 对具有
不同 contentType 的 output 消息需要
contentType。
|
这是最复杂的情况,可以在 TD 中以
不同方式描述。
form 层级中的 contentType 指 input,
以及在 output 具有相同 contentType 时
指预期 output(如情况 1C)。
response 内的
contentType 在 output 具有
不同 contentType 时指预期 output
(如情况 2A)。
additionalResponses 内的
contentType 指其他可能的
outputs。
|
|
|
本节是非规范性的。
本规范将 TD
信息模型引入为一组
对不同词汇表的约束,即
词汇表
术语的集合。本节
简要说明如何利用 TD 文档强制要求的
@context,将这些约束的机器可读定义集成到
客户端应用中。
从 TD 文档访问 TD 信息模型分两步完成。 首先,客户端必须检索从 JSON 字符串到 IRI 的映射。该映射定义为 JSON-LD 上下文, 如后文所述。其次,客户端可以通过解引用这些 IRI, 访问在这些 IRI 上定义的约束。 约束以 RDF 格式中的逻辑公理定义, 可由客户端程序直接解释。
词汇表
术语在 5.
TD 信息
模型中引用时,会在 TD
文档中序列化为(紧凑的)JSON 字符串。
然而,根据第一个 Linked Data
原则 [LINKED-DATA],这些术语中的每一个都由完整 IRI
明确标识。从 JSON 键到 IRI 的
映射就是 TD 的 @context 值所指向的内容。例如,
位于
https://www.w3.org/ns/wot-next/td
的文件包含以下映射(以及其他映射):
properties |
→ |
https://www.w3.org/2019/wot/td#hasPropertyAffordance
|
object |
→ |
https://www.w3.org/2019/wot/json-schema#ObjectSchema
|
basic |
→ |
https://www.w3.org/2019/wot/security#BasicSecurityScheme
|
href |
→ |
https://www.w3.org/2019/wot/hypermedia#hasTarget
|
| ... | ||
该 JSON 文件遵循 JSON-LD 1.1 语法
[JSON-LD11]。
许多 JSON-LD 库可以自动处理 TD 的
@context,并扩展其中包含的所有 JSON 字符串。
一旦 TD 的每个词汇表 术语都被扩展为 IRI,第二步就是 解引用该 IRI,以获取TD 信息模型中引用 该词汇表 术语的片段。例如,解引用 IRI
https://www.w3.org/2019/wot/json-schema#ObjectSchema
会得到一个 RDF 文档,该文档声明术语
ObjectSchema 是一个类,更准确地说,是
DataSchema 的子类。此类逻辑公理使用不同复杂度的形式化方法
在 RDF 中表示:
这里,子类关系表示为 RDF Schema 公理
[RDF-SCHEMA]。此外,这些公理
可以以各种格式序列化。这里,它们以 Turtle 格式
[TURTLE] 序列化:
<https://www.w3.org/2019/wot/json-schema#ObjectSchema>
a rdfs:Class .
<https://www.w3.org/2019/wot/json-schema#ObjectSchema>
rdfs:subClassOf <https://www.w3.org/2019/wot/json-schema#DataSchema> .
默认情况下,如果用户代理不执行任何内容
协商,则会返回人类可读的 HTML 文档,
而不是 RDF 文档。要协商内容,客户端必须在
请求中包含 HTTP header Accept: text/turtle。
本节是非规范性的。
作为 8.1.2.2
数据模式的扩展,
本节收集了不同负载及其对应
DataSchema 的示例。这些示例来自
知名 IoT 平台和标准,旨在说明
负载可能呈现出的各种形式,以及如何用 Data Schema
描述它。
SenML [RFC8428] 可能会 使用以下结构:
|
示例
82:
SenML 负载示例
|
示例
83:SenML 负载示例的 Data
Schema
|
根据 OCF[OCF],Batch Collection 可以按如下方式 结构化:
|
示例
84:OCF
Batch 示例
|
示例 85:OCF Batch
负载
示例的 Data Schema
|
而 LWM2M [LWM2M] 上的 IPSO Smart Object 可能如下所示:
|
示例
86:
IPSO/LWM2M 负载示例
|
示例 87:IPSO/LWM2M
负载示例的 Data Schema
|
contentType 在没有
默认值的情况下成为可选。编辑特别感谢 Cristiano Aguzzi、 Thomas Jäckle、Jan Romann、Elodie Thiéblin、Michael Koster、 Michael Lagally、Kazuyuki Ashimura、Daniel Peintner、Toru Kawaguchi、María Poveda、Dave Raggett、Kunihiko Toumura、 Takeshi Yamada、Ben Francis、Manu Sporny、Klaus Hartke、Addison Phillips、Jose M. Cantera、Tomoaki Mizushima、Soumya Kanti Datta 和 Benjamin Klotz 提供贡献、指导 和专业知识。
此外,非常感谢 W3C 员工以及 W3C Web of Things Interest Group (WoT IG) 和 Working Group (WoT WG) 的所有其他 当前和以往活跃参与者,感谢他们的支持、 技术投入和建议,这些都推动了 本文档的改进。
最后,特别感谢 Joerg Heuer 从 WoT IG 创立之初起领导其 2 年,并指导该小组提出 WoT 构建块的概念,包括 Thing Description。
关于未列出 参考文献的临时 ReSpec 修复:[RFC6068]、[RFC3966]、 [html]、 [RFC6750]、 [RFC7519]、[RFC7797]、 [RFC8392]、[RFC7516]、 [LDML]、 [SEMVER]、 [RFC7617]、 [RFC7616]
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: