Skip to main content

产品功规范描述

1. 快速入门

1.1 设备

在现实中,常见的物理设备基本都包含了诸多功能,如:

Example 1.1

设备智米风扇智米霾表飞利浦灯泡智米空气净化器
功能1可开关可以查询空气质量可开关可开关
功能2可调节风速可充电可调节亮度可调节风速
功能3可充电可查询电量可调节颜色可查询滤芯生命值
功能4可查询电量可查询充电状态可调节色温可查询空气质量
功能5可查询充电状态

1.2 功能分组

不同的设备的某些功能可能是一样的,比如:

  • 智米风扇和智米霾表都有电池,都可以:

    • 充电

    • 查询电量

    • 查询充电状态

  • 智米霾表和智米空气净化器都可以:

    • 查询空气质量
  • 智米风扇和智米空气净化都可以:

    • 调节风速

为了方便,有必要对功能进行分组,比如:

  • 电池

  • 空气质量传感器

  • 风扇

我们将功能组替换具体功能,那么Example 1.1可以写得更简洁:

Example 1.2

设备智米电风扇智米霾表飞利浦灯泡智米空气净化器
功能组1风扇空气质量传感器灯泡风扇
功能组2电池电池空气质量传感器

1.3 功能组定义

将功能组细化:

Example 1.3

功能组风扇电池空气质量传感器灯泡
功能1可开关可充电可查询PM2.5值可开关
功能2可调节/查询风速可查询充电状态可调节/查询亮度
功能3可查询当前电量可调节/查询色温
功能4可调节/查询颜色

1.4 抽象设备描述

通过以上的功能分解,我们可以比较完整地描述一个设备具备的功能了:

  • 智米电风扇

    • 风扇

      • 可开关

      • 可调节/查询风速

    • 电池

      • 可充电

      • 可查询充电状态

      • 可查询当前电量

用JSON来表达就是这样:

Example 1.4.1

{
"名称": "智米电风扇",
"功能组": [
{
"名称": "风扇",
"功能列表": ["可开关", "可调节/查询风速"]
},
{
"名称": "电池",
"功能列表": ["可充电", "可调节充电状态", "可查询当前电量"]
}
]
}

还有些细节没有确定,比如说:

  • 风速的调节到底是按档位来,还是无极变速?

  • 电池的电量到底是用百分比表达,还是用毫安?

所以,如果我们把每个细节都确定下来,计算机就很方便处理了,Example 1.4.1可以改写得比较规范了:

Example 1.4.2

{
"type": "urn:xiot-spec:device:fan:0000A005:zhimi:sa:1",
"description": "Zhimi Fan",
"services": [
{
"iid": 1,
"type": "urn:xiot-spec:service:fan:00007808:zhimi:sa:1",
"description": "Fan",
"properties": [
{
"iid": 1,
"type": "urn:xiot-spec:property:on:00000006:zhimi:sa:1",
"description": "Switch Status",
"format": "bool",
"access": ["read", "write", "notify"]
},
{
"iid": 2,
"type": "urn:xiot-spec:property:fan-level:00000016:zhimi:sa:1",
"description": "Speed Level",
"format": "uint8",
"access": ["read", "write", "notify"],
"value-range": [1, 3, 1]
}
]
},
{
"iid": 2,
"type": "urn:xiot-spec:service:battery:00007805:zhimi:sa:1",
"description": "Battery",
"properties": [
{
"iid": 1,
"type": "urn:xiot-spec:property:battery-level:00000014:zhimi:sa:1",
"description": "Battery Level",
"format": "uint8",
"access": ["read", "notify"],
"value-range": [0, 100, 1],
"unit": "percentage"
},
{
"iid": 2,
"type": "urn:xiot-spec:property:charging-state:00000015:zhimi:sa:1",
"description": "Charging State",
"format": "uint8",
"access": ["read", "notify"],
"value-list": [
{
"value": 0,
"description": {
"en-US": "NOT_CHARGING",
"zh-CN": "没有充电"
}
},
{
"value": 1,
"description": {
"en-US": "CHARGING",
"zh-CN": "充电中"
}
},
{
"value": 2,
"description": {
"en-US": "NOT_CHARGEABLE",
"zh-CN": "不可充电"
}
}
]
}
]
}
]
}

2. 名词和概念

  • Specification

  • 规范,简写为spec

  • xiot-spec

  • 可扩展IoT规范

  • 产品规范

  • 所谓的产品规范,指的是对产品功能的基本定义。

  • 产品模板

  • 所谓的产品模板,指的是对某一类产品的概念定义。

  • 产品实例

  • 所谓的产品实例,指的是开发者最终的产品功能定义。

  • type

  • 全称为Specification Type,即规范定义类型.

  • device

  • 设备

  • service

  • 服务,也可以理解为功能组

  • property

  • 属性

  • action

  • 方法

  • event

  • 事件

  • instance

  • 实例

  • iid

  • 全称为instance id,实例id

  • template

  • 模板

  • lifecycle

  • 生命周期,产品规范定义、产品模板、产品实例都有可能携带这个字段,字段取值含义如下:

含义说明
development开发中可能随时会修改
preview预览中正在测试验证,修改的概率不高了
released上线已经测试完成,上线了,再也不会修改了。

另外,和汽车工业对比,物联网工业的产品规范、产品模板和产品实例有类似关系:

物联网工业汽车工业汽车工业的例子
产品规范零部件规格轮毂尺寸、发动机参数
产品模板抽象车型A级小轿车,B级SUV
产品实例具体车型宝马325,大众途观

3. 产品规范

3.1 简介

规范定义,分为:

  • 设备规范定义

  • 服务规范定义

  • 方法规范定义

  • 事件规范定义

  • 属性规范定义 注: 在规范里,我们称功能组为“服务” 我们需要有一个字段来表达不同的定义,这个字段称之为SpecificationType

3.2 SpecificationType

规范定义类型,简写为 type,必须是URN格式:

urn:xiot-spec:service:device-information:00007801
  • URN表达式

  • URN表达式遵循URN语法规范(RFC2141),6个字段,最后一个字段为可选:

<URN> ::= "urn:"<ns>":"<type>":"<name>":"<value>[":"<vendor>:"<model>":"<version>]
  • urn

  • 第一个字段必须为urn,否则视为非法urn。

  • ns

  • 名字空间,如果是苹果定义的规范为xiot-spec,蓝牙联盟定义的规范为bluetooth-spec。

  • type

  • SpecificationType (类型,简写为: type),只能是如下几个:

    • template

    • property

    • action

    • event

    • service

    • device

  • name

  • 有意义的单词或单词组合(小写字母),多个单词用"-"间隔,比如:

    • temperature

    • current-temperature

    • device-name

    • battery-level

  • value

  • 16进制字符串,使用UUID前8个字符,如:

    • 00002A06

    • 00002A00

  • 可以认为value和name是等价的,name字段表达语义,方便人和AI阅读,value使用2个字节,嵌入式设备可以使用value来替代name。

  • vendor

  • 厂家,有意义的单词或单词组合(小写字母),比如:

    • philips

    • aux-group

注:这个字段在产品规范中不出现,在产品模板和产品实例中出现。
  • model

  • 产品型号,有意义的单词或单词组合(小写字母),比如:

    • c200

    • a6

    • mx-5

注:这个字段在产品规范中不出现,在产品模板和产品实例中出现。
  • version

  • 版本号,只能是自然数,如:

    • 1

    • 2

    • 3

注:这个字段只有在产品实例定义里出现。

3.3 设备品类

同一类设备被定义为同一个设备品类,如灯、开关等,使用一个urn表达式来表达:

  • type(SpecificationType, 简写为type)
  • 设备类型,必须是URN表达式,如:
"type": "urn:xiot-spec:device:fan:0000A005"
  • description(描述)
  • 对此Device做一个简单的描述:
"description": "风扇"
  • 支持多语言:
"description": {
"en-US": "Fan",
"zh-CN": "风扇"
}

3.4 服务定义

服务是一个独立的有意义的功能组,描述一个服务,需要说清楚:

  • 是什么服务?

  • 有什么方法可以操作?

  • 有什么事件可能会发生?

  • 有哪些属性?

因此,服务规范定义需要包含如下字段:

  • type(SpecificationType, 简写为type)
  • 服务类型,必须是URN表达式,如:
urn:xiot-spec:service:fan:00007808
  • description(描述)
  • 对此Service做一个简单的描述,如:
Fan Service
  • 或支持多语言,如:
{
"en-US": "Fan Service",
"zh-CN": "风扇服务"
}
  • required-actions(必选方法列表)
  • 如:
"required-actions": [
"urn:xiot-spec:action:get-stream-configuration:00000001",
"urn:xiot-spec:action:start-stream:00000101",
"urn:xiot-spec:action:stop-stream:00000201"
]
  • optional-actions(可选方法列表)
  • 如:
"optional-actions": [
"urn:xiot-spec:action:identify:00002801"
]
  • required-events(必选事件列表)
  • 如:
"required-events": [
"urn:xiot-spec:event:alert1:00000007"
]
  • optional-events(可选事件列表)
  • 如:
"optional-events": [
"urn:xiot-spec:event:alert2:00000008"
]
  • required-properties(必选属性列表)
  • 如:
"required-properties": [
"urn:xiot-spec:property:on:00000006",
"urn:xiot-spec:property:fan-level:00000016"
]
  • optional-properties(可选属性列表)
  • 如:
"optional-properties": [
"urn:xiot-spec:property:horizontal-swing:00000017",
"urn:xiot-spec:property:vertical-swing:00000018",
"urn:xiot-spec:property:horizontal-angle:00000019",
"urn:xiot-spec:property:vertical-angle:0000001A",
"urn:xiot-spec:property:mode:00000008",
"urn:xiot-spec:property:status:00000007",
"urn:xiot-spec:property:fault:00000009"
]

Example 2.4.1

{
"type": "urn:xiot-spec:service:fan:00007808",
"description": {
"en-US": "Fan",
"zh-CN": "风扇",
"zh-TW": "風扇"
},
"required-properties": [
"urn:xiot-spec:property:on:00000006",
"urn:xiot-spec:property:fan-level:00000016"
],
"optional-properties": [
"urn:xiot-spec:property:horizontal-swing:00000017",
"urn:xiot-spec:property:vertical-swing:00000018",
"urn:xiot-spec:property:horizontal-angle:00000019",
"urn:xiot-spec:property:vertical-angle:0000001A",
"urn:xiot-spec:property:mode:00000008",
"urn:xiot-spec:property:status:00000007",
"urn:xiot-spec:property:fault:00000009"
]
}

解读如下:

  • 这是一个风扇服务

  • 作为一个风扇,必须有的功能:

    • 开关

    • 调整风速

  • 作为一个风扇,可选以下功能:

    • 名字

    • 旋转

    • 旋转角度

    • 禁用物理按键

当然,服务也可以稍微再复杂一点:

Example 2.4.2

{
"type": "urn:xiot-spec:service:camera:00000007",
"description": {
"en-US": "Camera",
"zh-CN": "摄像头",
"zh-TW": "攝像頭"
},
"required-properties": [
"urn:xiot-spec:property-v2:streaming-status:00000004",
"urn:xiot-spec:property-v2:support-video-stream-configuration:00000002",
"urn:xiot-spec:property-v2:support-audio-stream-configuration:00000002",
"urn:xiot-spec:property-v2:support-rtp-stream-configuration:00000003",
"urn:xiot-spec:property-v2:session-id:00000102",
"urn:xiot-spec:property-v2:controller-ip-version:00000103",
"urn:xiot-spec:property-v2:controller-ip-address:00000104",
"urn:xiot-spec:property-v2:controller-video-rtp-port:00000105",
"urn:xiot-spec:property-v2:controller-audio-rtp-port:00000106",
"urn:xiot-spec:property-v2:selected-video-parameters:00000107",
"urn:xiot-spec:property-v2:selected-audio-parameters:00000108",
"urn:xiot-spec:property-v2:device-status:00000109",
"urn:xiot-spec:property-v2:device-ip-version:00000110",
"urn:xiot-spec:property-v2:device-ip-address:00000111",
"urn:xiot-spec:property-v2:synchronization-source-for-video:00000112",
"urn:xiot-spec:property-v2:synchronization-source-for-audio:00000113",
"urn:xiot-spec:property-v2:session-control:00000119"
],
"required-actions": [
"urn:xiot-spec:action-v2:get-stream-configuration:00000001",
"urn:xiot-spec:action-v2:start-stream:00000101",
"urn:xiot-spec:action-v2:stop-stream:00000201"
],
"optional-actions": [
"urn:xiot-spec:action:set-stream-configuration:00000009"
],
"required-events": [
"urn:xiot-spec:event:alert:00000007"
],
"optional-events": [
"urn:xiot-spec:event:warrning:00000008"
]
}

注意,与Example 2.4.1相比,多了几个字段:

  • required-actions

  • optional-actions

  • required-events

  • optional-events

3.5 方法定义

有时候,一个有意义的操作需要对多个属性进行读写,可以用方法来实现,描述一个方法,需要说清楚:

  • 是什么方法?

  • 输入参数是什么?

  • 方法执行完有没有输出值,如果有,输出值什么?

因此,方法规范定义需要包含如下字段:

  • type (SpecificationType, 简写为type)
  • 方法类型,必须URN表达式,如:
urn:xiot-spec:action:play:0000280B
  • description(描述)
  • 对此Action做一个简短的描述:
Get Streaming Configuration Of Camera
  • in(输入参数列表)
  • 可以是0到N个,每个参数都由属性组成,参数为可变参数,可以重复多次,也可以不出现。
  • out(输出参数列表)
  • 可以是0到N个,每个参数都由属性组成,参数为可变参数,可以重复多次,也可以不出现。

Example 2.5.1 读取摄像头配置信息(需要一次读取多个属性)

{
"type": "urn:xiot-spec:action:get-stream-configuration:00000001",
"description": {
"en-US": "Get Streaming Configuration Of Camera",
"zh-CN": "从摄像头读取流配置信息",
"zh-TW": "從攝像頭讀取流配置信息"
},
"in": [],
"out": [
{
"type": "urn:xiot-spec:property:streaming-status:00000004",
"repeat": [1, 1]
},
{
"type": "urn:xiot-spec:property:support-video-stream-configuration:00000002",
"repeat": [1, 1]
},
{
"type": "urn:xiot-spec:property:support-audio-stream-configuration:00000002",
"repeat": [1, 1]
},
{
"type": "urn:xiot-spec:property:support-rtp-stream-configuration:00000003",
"repeat": [1, 1]
}
]
}

Example 2.5.2 开启摄像头视频流(需要设置SRTP相关的N个属性,返回SRTP相关的N个属性)

{
"type": "urn:xiot-spec:action:start-stream:00000101",
"description": {
"en-US": "Start Camera Streaming",
"zh-CN": "开启摄像头视频流",
"zh-TW": "開啟攝像頭視頻流"
},
"in": [
{
"type": "urn:xiot-spec:property:session-id:00000102",
"repeat": [1, 1]
},
{
"type": "urn:xiot-spec:property:controller-ip-version:00000103",
"repeat": [1, 1]
},
{
"type": "urn:xiot-spec:property:controller-ip-address:00000104",
"repeat": [1, 1]
},
{
"type": "urn:xiot-spec:property:controller-video-rtp-port:00000105",
"repeat": [1, 1]
},
{
"type": "urn:xiot-spec:property:controller-audio-rtp-port:00000106",
"repeat": [1, 1]
},
{
"type": "urn:xiot-spec:property:selected-video-parameters:00000107",
"repeat": [1, 1]
},
{
"type": "urn:xiot-spec:property:selected-audio-parameters:00000108",
"repeat": [1, 1]
}
],
"out": [
{
"type": "urn:xiot-spec:property:device-status:00000109",
"repeat": [1, 1]
},
{
"type": "urn:xiot-spec:property:device-ip-version:00000110",
"repeat": [1, 1]
},
{
"type": "urn:xiot-spec:property:device-ip-address:00000111",
"repeat": [1, 1]
},
{
"type": "urn:xiot-spec:property:synchronization-source-for-video:00000112",
"repeat": [1, 1]
},
{
"type": "urn:xiot-spec:property:synchronization-source-for-audio:00000113",
"repeat": [1, 1]
},
{
"type": "urn:xiot-spec:property:session-control:00000119",
"repeat": [1, 1]
}
]
}

哪些情况下使用Action?

对于同时需要对多个属性的读写才能完成一次有意义的操作,用Action,如上文的开启摄像头视频流。
如果对某些属性的写操作很耗时,则用Action,status返回1,待操作完成后再用事件通知。

方法所引用的属性

方法在两种情况下引用到了属性定义,一种是参数列表中的数据,另一种是返回结果列表的数据。
注意:方法只能引用同服务内部的其他属性。

3.6 事件定义

简单的事件,用属性的变化来通知用户。复杂的事件,需要用Event来表达:

  • 发生了什么事情?

  • 哪些属性发生了变化?

因此,事件规范定义需要包含如下字段:

  • type(SpecificationType, 简写为type)
  • 事件类型,必须是URN表达式,如:
urn:xiot-spec:event:alert:00000007
  • description(描述)
  • 纯文本字段,对此事件做一个简单的描述,如:
Get Streaming Configuration Of Camera
  • arguments(参数列表)
  • 可以是0到N个,每个参数都由属性组成,参数为可变参数,可以重复多次,也可以不出现。

Example 2.6

{
"type": "urn:xiot-spec:event:alert:00000007",
"description": {
"en-US": "alert alert alert!!!",
"zh-CN": "警告",
"zh-TW": "警告"
},
"arguments": [
{
"type": "urn:xiot-spec:property:name:00000002",
"repeat": [1, 1]
},
{
"type": "urn:xiot-spec:property:temperature:00000003",
"repeat": [0, 4]
}
]
}

3.7 属性定义

属性描述需要表达这几个意思:

  • 语义是什么?

  • 数据格式是什么?

  • 是否可读?是否可写?数据变化了是否有通知?

  • 值是否有约束?如果有,取值范围是离散值还是连续值?

  • 单位是否定义?如果有定义,单位是什么?

因此,属性规范定义需要包含如下字段:

  • type (SpecificationType, 简写为type)
  • 属性类型,必须是URN表达式,如:
urn:xiot-spec:property:color-temperature:0000000F
  • description(描述)
  • 纯文本字段,对此事件做一个简单的描述,支持多语言,如:
Name
Temperature
Current Temperature
Temperature Display Units
Battery Level
Air Quality
  • format(数据格式)
数据格式描述备注
bool布尔值: true/false 或 1/0
uint8无符号8位整型建议约束取值范围
uint16无符号16位整型同上
uint32无符号32位整型同上
int8有符号8位整型同上
int16有符号16位整型同上
int32有符号32位整型同上
int64有符号64位整型同上
float浮点数同上
string字符串建议约束最大长度
hex16进制,(使用字符串表示,如”FF0011”, “EE00”等)建议约束取值范围
combination组合格式,包含多个属性
  • access (访问方式)
描述
read
write
notify通知
  • value-range (对取值范围进行约束,可选字段)
  • 当format为整型、浮点数或hex时,可定义value-range,比如:
最小值最大值步长
16320.5

用JSON数组表示:

[16, 32, 0.5]
  • value-list (对取值范围进行约束,可选字段)
  • 当format为整型,可定义"value-list",每个元素都包含:

    • value

    • description

  • 用JSON数组表示,如:

[
{"value": 1, "description": "Monday"},
{"value": 2, "description": "Tuesday"},
{"value": 3, "description": "Wednesday"},
{"value": 4, "description": "Thursday"},
{"value": 5, "description": "Friday"},
{"value": 6, "description": "Saturday"},
{"value": 7, "description": "Sunday"}
]
  • 描述可以支持多语言,如:
[
{"value": 1, "description": {"en-US": "Monday", "zh-CN": "周一"}},
{"value": 2, "description": {"en-US": "Tuesday", "zh-CN": "周二"}},
{"value": 3, "description": {"en-US": "Wednesday", "zh-CN": "周三"}},
{"value": 4, "description": {"en-US": "Thursday", "zh-CN": "周四"}},
{"value": 5, "description": {"en-US": "Friday", "zh-CN": "周五"}},
{"value": 6, "description": {"en-US": "Saturday", "zh-CN": "周六"}},
{"value": 7, "description": {"en-US": "Sunday", "zh-CN": "周日"}}
]
  • unit (单位,可选字段)
  • 当format为整型或浮点型,可定义unit值:
描述
percentage百分比
celsius摄氏度
seconds
minutes
hours小时
days
kelvin开氏温标
pascal帕斯卡(大气压强单位)
arcdegrees弧度(角度单位)
rgbRGB(颜色)
watt瓦特(功率)
litre
ppmppm浓度
lux勒克斯(照度)
mg/m3毫克每立方米
  • max-length (字符串最大长度) 可选字段,仅当format为字符串时可选。

  • members(成员)

  • 可选字段,仅当format为combination时才出现,如:
{
"type": "urn:xiot-spec:property:hsv:00000040",
"description": "HSV",
"format": "combination",
"access": ["read", "write", "notify"],
"members": [
"urn:xiot-spec:property:hue:00000041",
"urn:xiot-spec:property:saturation:00000042",
"urn:xiot-spec:property:brightness:00000043"
]
}

Example 2.7.1 最简单的定义

{
"type": "urn:xiot-spec:property:device-name:00000001",
"description": "Device Name",
"format": "string",
"access": ["read"],
"max-length": 16
}

Example 2.7.2 使用value-range和unit

{
"type": "urn:xiot-spec:property:current-temperature:00000002",
"description": "Current temperature",
"format": "float",
"access": ["read", "write", "notify"],
"value-range": [16, 32, 0.5],
"unit": "celsius"
}

Example 2.7.3 使用value-list

{
"type": "urn:xiot-spec:property:day-of-the-week:00000003",
"description": "Day Of The Week",
"format": "uint8",
"access": ["read", "write", "notify"],
"value-list": [
{"value": 1, "description": "Monday"},
{"value": 2, "description": "Tuesday"},
{"value": 3, "description": "Wednesday"},
{"value": 4, "description": "Thursday"},
{"value": 5, "description": "Friday"},
{"value": 6, "description": "Saturday"},
{"value": 7, "description": "Sunday"}
]
}

4. 产品模板

产品模板,简称模板,在产品模板中,规定了哪些功能是必须的,哪些功能是可选的,同样:

  • 在模板的功能里,规定了哪些属性是可选的,哪些属性是必须的。

  • 在模板的功能里,规定了哪些方法是可选的,哪些方法是必须的。

  • 在模板的功能里,规定了哪些事件是可选的,哪些事件是必须的。

下面是一个具体模板的定义:

{
"type": "urn:xiot-spec:device:lightbulb:00000005:ks:b1:1",
"lifecycle": "preview",
"description": {
"en-US": "Ordinary bulb",
"zh-TW": "普通燈泡",
"zh-CN": "普通灯泡"
},
"services": [
{
"x-required": true,
"iid": 1,
"type": "urn:xiot-spec:service:accessory-information:0000003e:ks:b1:1",
"x-action-addable": false,
"x-event-addable": false,
"x-property-addable": false,
"description": {
"en-US": "Accessory Information",
"zh-TW": "配件信息",
"zh-CN": "配件信息"
},
"properties": [
{
"type": "urn:xiot-spec:property:firmware-revision:00000052:ks:b1:1",
"description": {
"en-US": "Firmware Revision",
"zh-TW": "固件版本",
"zh-CN": "固件版本"
},
"format": "string",
"access": ["read"],
"x-required": true,
"iid": 2
},
{
"type": "urn:xiot-spec:property:identify:00000014:ks:b1:1",
"description": {
"en-US": "Identify",
"zh-TW": "辨認",
"zh-CN": "辨认"
},
"format": "bool",
"access": ["write"],
"x-required": true,
"iid": 3
},
{
"type": "urn:xiot-spec:property:manufacturer:00000020:ks:b1:1",
"description": {
"en-US": "Manufacturer",
"zh-TW": "制造商",
"zh-CN": "制造商"
},
"format": "string",
"access": ["read"],
"x-required": true,
"iid": 4
},
{
"type": "urn:xiot-spec:property:model:00000021:ks:b1:1",
"description": {
"en-US": "Model",
"zh-TW": "型號",
"zh-CN": "型号"
},
"format": "string",
"access": ["read"],
"x-required": true,
"iid": 5
},
{
"type": "urn:xiot-spec:property:name:00000023:ks:b1:1",
"description": {
"en-US": "name",
"zh-TW": "名稱",
"zh-CN": "名称"
},
"format": "string",
"access": ["read"],
"x-required": true,
"iid": 6
},
{
"type": "urn:xiot-spec:property:serial-number:00000030:ks:b1:1",
"description": {
"en-US": "Serial Number",
"zh-TW": "序列號",
"zh-CN": "序列号"
},
"format": "string",
"access": ["read"],
"x-required": true,
"iid": 7
},
{
"type": "urn:xiot-spec:property:accessory-properties:000000a6:ks:b1:1",
"description": {
"en-US": "Accessory Flags",
"zh-TW": "配件屬性",
"zh-CN": "配件属性"
},
"format": "uint32",
"access": ["read", "notify"],
"value-range": [0, 65535,1],
"x-required": false,
"iid": 8
},
{
"type": "urn:xiot-spec:property:hardware-revision:00000053:ks:b1:1",
"description": {
"en-US": "Hardware Revision",
"zh-TW": "硬件版本",
"zh-CN": "硬件版本"
},
"format": "string",
"access": ["read"],
"x-required": false,
"iid": 9
}
]
},
{
"x-required": true,
"iid": 10,
"type": "urn:xiot-spec:service:lightbulb:00000043:ks:b1:1",
"x-action-addable": false,
"x-event-addable": false,
"x-property-addable": false,
"description": {
"en-US": "Light Bulb",
"zh-TW": "燈泡",
"zh-CN": "灯泡"
},
"properties": [
{
"type": "urn:xiot-spec:property:on:00000025:ks:b1:1",
"description": {
"en-US": "On",
"zh-TW": "開關",
"zh-CN": "开关"
},
"format": "bool",
"access": ["read","write","notify"],
"x-required": true,
"iid": 11
}
]
}
]
}

上面的模板中,新出现几个以"x-"字符串开头的字段,表达的是扩展字段:

字段名称含义出现的位置
x-action-addable是否可以添加方法service
x-event-addable是否可以添加事件service
x-property-addable是否可以添加属性service
x-required是否必须实现service, property, action, event

另外,还有几个字段:

字段名称含义出现的位置
iid实例ID,instance id,简称iidservice, property, action, event

注意,在产品规范中的服务定义中,已经有:必选属性和可选属性、必须方法和可选方法、必选事件和可选事件,产品模板完全覆盖产品规范的内容,更进一步定义了产品概念。

5. 产品实例

产品实例的创建方式:

  • 可以继承一个产品模板来创建一个产品实例。

  • 也可以直接从产品规范来创建一个产品实例。

5.1 实例ID(Instance ID,简称iid)

对于一个实际生产的物理设备,我们称之为产品实例(Device Instance),每个型号的设备具备的功能应该是一样的。也就是说:

  • Device包含哪些Service是确定的.

  • Service包含哪些Action/Event/Property也是确定的。

所以:在一个产品实例的定义中,可选的东西是不存在的。

在同一个设备中,有可能出现功能重复的定义,比如:

  • 插座中有N个插孔

  • 净水器有N个滤芯

也就是说:

  • 一个Property可能存在多个实例

  • 一个Action可能存在多个实例

  • 一个Service也可能存在多个实例。

为了区分不同的实例,需要引入一个概念:iid(实例ID)

iid用自然数表示,一个iid在同一级是唯一的,所谓的“iid在同一级唯一”的意思是:

  • 在一个Device中,Service的iid是唯一的。

  • 在一个Service的properties中,Property的iid是唯一的。

  • 在一个Service的actions中,Action的iid是唯一的。

  • 在一个Service的events中,Event的iid是唯一的。

注意:iid是自然数,不要求连续增长。

5.2 创建产品实例

在产品实例定义中使用规范定义(Property/Action/Event/Service/Device)时,往往需要修改规范定义。比如:

  • 风扇的档位由规范定义的5个档位,修改为10个档位。

  • 空调的温度由规范定义的16-32度,修改为15-33度。

因此需要引入一个概念: 继承。 在type字段加上后缀,表示此定义已经被继承,比如:

  • 规范定义的属性(speed-level,定义了5个档位)
{
"type": "urn:xiot-spec:property:speed-level:00000023",
"description": "Speed Level",
"format": "uint8",
"access": ["read", "write", "notify"],
"value-range": [1, 5, 1]
}
  • 智米做了一款风扇,继承了这个属性,修改风扇的档位为10档
{
"type": "urn:xiot-spec:property:speed-level:00000023:zhimi:aa:1",
"description": "Speed Level",
"format": "uint8",
"access": ["read", "write","notify"],
"value-range": [1, 10, 1]
}
  • 奥克斯也做了一款风扇,继承此属性后,修改了风扇的档位为3档:
{
"type": "urn:xiot-spec:property:speed-level:00000023:auxgroup:ff:1",
"description": "Speed Level",
"format": "uint8",
"access": ["read", "write", "notify"],
"value-range": [1, 3, 1]
}

厂家使用继承方式,可以自定义:

  • Device

  • Service

  • Action

  • Event

  • Property

5.2.1 Device

产品实例必须是继承方式,如:

urn:xiot-spec:device:light:0000A001:tuya02:ttt:1
urn:xiot-spec:device:air-conditioner:0000A004:aden:a:1
urn:xiot-spec:device:air-conditioner:0000A004:aux:b:1
urn:xiot-spec:device:outlet:0000A002:chuangmi:hmi:1
urn:xiot-spec:device:outlet:0000A002:chuangmi:m:1
urn:xiot-spec:device:outlet:0000A002:chuangmi:v:1
urn:xiot-spec:device:cooker:0000A00B:chunmi:mmm:1

厂家创建一个设备时,必须实现:

  • required-services

可以实现

  • optional-services

同时,厂家可以添加其他的service。

5.2.2 Service

在Service实例中,必须实现:

  • required-actions

  • required-events

  • required-properties

可以实现

  • optional-actions

  • optional-events

  • optional-properties

5.2.3 Action

在Action实例中,in和out参数可以被修改。

5.2.4 Event

在Event实例中,argument参数可以被修改。

如果参数被修改,则此Event实例属于继承方式,需要加上后缀字段。

5.2.5 Property

在Property实例中,以下字段都可以被修改:

  • format

  • access (不推荐修改)

  • unit (不推荐修改)

  • value-list

  • value-range

  • max-length

  • members

当然,一般情况下,我们只推荐修改值的约束范围。

特别注意:如果修改了format,则value-list/value-range/max-length等字段也需要跟着调整。

5.3 范例

用一个文件描述整个设备,由于是一个实例定义,所以Service和Property都有自己的"iid"。

  • 灯泡实例定义
{
"type": "urn:xiot-spec:device:light:0000A001:vw:cc:1",
"description": "Light",
"services": [
{
"iid": 1,
"type": "urn:xiot-spec:service:device-information:00007801:vw:cc:1",
"description": "Device Information",
"properties": [
{
"iid": 1,
"type": "urn:xiot-spec:property:manufacturer:00000001:vw:cc:1",
"description": "Device Manufacturer",
"format": "string",
"access": ["read"]
},
{
"iid": 2,
"type": "urn:xiot-spec:property:model:00000002:vw:cc:1",
"description": "Device Model",
"format": "string",
"access": ["read"]
},
{
"iid": 3,
"type": "urn:xiot-spec:property:serial-number:00000003:vw:cc:1",
"description": "Device Serial Number",
"format": "string",
"access": ["read"]
},
{
"iid": 4,
"type": "urn:xiot-spec:property:name:00000004:vw:cc:1",
"description": "Device Name",
"format": "string",
"access": ["read"]
},
{
"iid": 5,
"type": "urn:xiot-spec:property:firmware-revision:00000005:vw:cc:1",
"description": "Current Firmware Version",
"format": "string",
"access": ["read"]
}
]
},
{
"iid": 2,
"type": "urn:xiot-spec:service:light:00007802:vw:cc:1",
"description": "Light",
"properties": [
{
"iid": 1,
"type": "urn:xiot-spec:property:on:00000006:vw:cc:1",
"description": "Switch Status",
"format": "bool",
"access": ["read","write","notify"]
},
{
"iid": 2,
"type": "urn:xiot-spec:property:brightness:0000000D:vw:cc:1",
"description": "Brightness",
"format": "uint8",
"access": ["read","write","notify"],
"value-range": [1,100,1],
"unit": "percentage"
},
{
"iid": 3,
"type": "urn:xiot-spec:property:color:0000000E:vw:cc:1",
"description": "Color",
"format": "uint32",
"access": ["read","write","notify"],
"value-range": [0,16777215,1],
"unit": "rgb"
},
{
"iid": 4,
"type": "urn:xiot-spec:property:color-temperature:0000000F:vw:cc:1",
"description": "Color Temperature",
"format": "uint32",
"access": ["read","write","notify"],
"value-range": [1700,6500,1],
"unit": "kelvin"
}
]
}
]
}

6. 产品实例升级

物理设备的固件升级后,可能:

  1. 仅仅是修复内部bug。

  2. 增加了设备功能。

对于第1种情况,我们不关心。

对于第2种情况,我们需要规定好升级方式。

比如一款风扇升级过N个固件,更改了3次功能,这3次升级都修改了产品实例的type:

urn:xiot-spec:device:fan:0000A005:vw:cc:1
urn:xiot-spec:device:fan:0000A005:vw:cc:2
urn:xiot-spec:device:fan:0000A005:vw:cc:3

6.1 升级约定

  • 升级版本号,需要向下兼容,即:

    • 只能添加功能,不能删除和修改旧功能。
  • 如果更改了产品型号,则不需要考虑兼容。

  • 绝大多数情况下,不建议升级产品型号。

6.2 范例

  • 初始版本定义

  • 当一个产品刚被创建的时候,版本号是1,如:

{
"type": "urn:xiot-spec:device:fan:0000A005:vw:cc:1",
"description": "Zhimi Fan",
"services": [
{
"iid": 1,
"type": "urn:xiot-spec:service:fan:00007808:vw:cc:1",
"description": "Fan",
"properties": [
{
"iid": 1,
"type": "urn:xiot-spec:property:on:00000006:vw:cc:1",
"description": "Switch Status",
"format": "bool",
"access": ["read", "write", "notify"]
},
{
"iid": 2,
"type": "urn:xiot-spec:property:fan-level:00000016:vw:cc:1",
"description": "Speed Level",
"format": "uint8",
"access": ["read", "write", "notify"],
"value-range": [1, 3, 1]
}
]
}
]
}
  • 注意:

    • 产品实例中的type是
    urn:xiot-spec:device:fan:0000A005:vw:cc:1
    • 风速被厂家修改了取值范围,type是
    urn:xiot-spec:property:fan-level:00000016:vw:cc:1
    • 两个type的后缀保持一致,都是:
    vw:cc:1
  • 升级

  • 过了一段时间,厂家觉得3档太少,需要升级下固件,支持5个档位。产品实例被修改成:

{
"type": "urn:xiot-spec:device:fan:0000A005:vw:cc:2",
"description": "Zhimi Fan",
"services": [
{
"iid": 1,
"type": "urn:xiot-spec:service:fan:00007808:vw:cc:1",
"description": "Fan",
"properties": [
{
"iid": 1,
"type": "urn:xiot-spec:property:on:00000006:vw:cc:1",
"description": "Switch Status",
"format": "bool",
"access": ["read", "write", "notify"]
},
{
"iid": 2,
"type": "urn:xiot-spec:property:fan-level:00000016:vw:cc:1",
"description": "Speed Level",
"format": "uint8",
"access": ["read", "write", "notify"],
"value-range": [1, 3, 1]
},
{
"iid": 3,
"type": "urn:xiot-spec:property:fan-level:00000016:vw:cc:2",
"description": "Speed Level",
"format": "uint8",
"access": ["read", "write", "notify"],
"value-range": [1, 5, 1]
}
]
}
]
}
  • 注意:

    • 产品实例中的type是(版本号变成了2):
    urn:xiot-spec:device:fan:0000A005:vw:cc:2
    • 原来的风速属性依旧不变(这是一个在版本1时定义的风速),iid: 2:
    urn:xiot-spec:property:fan-level:00000016:vw:cc:1
    • 新增加了一个风速(iid: 3,版本号是2),档位被调整为5档,type是:
    urn:xiot-spec:property:fan-level:00000016:vw:cc:2
  • 也就说,在版本2的产品实例中,表达风速的2个属性,都同时存在,都可以进行读和写,向下兼容必须要实现:

    • iid: 2是版本1的产品实例中的风速属性。

    • iid: 3是版本2的产品实例中的风速属性。