Appearance
LWM2M 设备 API 参考
先决条件
我们假设您已经完成了一般的入门指南以熟悉 蟹立方物联网平台。
LwM2M 基础知识
LwM2M 是一种设备管理协议,专为受限设备和机器对机器 (M2M) 环境的需求而设计。您可以在此处找到有关 LwM2M 的更多信息。LwM2M 协议的主要优势是丰富的数据结构库,称为 LwM2M 对象和资源注册表。此 Github 存储库中提供了可用对象的最新列表。
注册表允许对遥测进行高效的序列化/反序列化。LwM2M 协议定义了设备注册、配置、管理和固件/软件更新的过程。
蟹立方物联网平台 实现了 LwM2M 服务器和引导服务器,支持普通 UDP 和 DTLS(通过 UDP 的安全传输)。蟹立方物联网平台 允许您预置自己的 LwM2M 模型(对象和资源),并将这些对象映射到 蟹立方物联网平台 遥测和属性。T
步骤 1.上传 LwM2M 模型
系统管理员可以使用“系统设置”菜单中的“资源库”UI 上传 LwM2M 模型。一个人可以一次上传多个文件。我们建议您从官方 github repo 下载可用模型列表并导入所有模型。
登录您的 蟹立方物联网平台 实例并转到系统设置 - >资源库,然后单击“+”按钮
上传资源模型文件
确保您可以在列表中看到新文件
租户管理员可以使用系统管理员定义的 LwM2M 模型,也可以为特定租户覆盖这些模型。
租户无法删除由系统管理员上传的文件
租户可以上传和覆盖系统管理员为同一资源上传的资源模型文件
租户可以删除自己上传的文件
当 Tenant 删除他的文件时,系统管理员上传的文件仍然存在
步骤 2.定义 LwM2M 设备配置文件
上传 LwM2M 模型后,您就可以使用它们来定义设备配置文件了。有关设备配置文件的更多信息,请参阅常规设备配置文件文档。重要的步骤是在 “Transport configuration” 步骤中选择 LwM2M Transport type。Transport Configuration 允许我们定义您的设备支持的 LwM2M 对象列表。
转到 设备配置文件,单击“+”,键入配置文件名称,然后选择或创建将处理消息的规则链
从下拉菜单中选择 “LwM2M” 传输类型
已成功创建新配置文件
让我们定义一个支持设备对象 (id: 3)、连接 (id: 4)、固件更新 (id: 5) 和位置监控 (id: 6) 的配置文件:
转到 Device Profiles,选择 “LWM2M”,转到 “Transport configuration” 选项卡,单击 “Edit” 按钮
从下拉菜单中添加对象。对象应上传到资源库
您可能会注意到 Device Object 支持 Manufacturer、model 和 serial number。让我们配置 蟹立方物联网平台 在设备连接时获取这些数据,并将其存储为 蟹立方物联网平台 属性。此外,我们还想观察无线电信号强度、链接质量和设备位置将其推送为 蟹立方物联网平台 遥测。Observe 是一项强大的 LwM2M 功能,它将指示设备报告这些值的变化。您还可以通过 LwM2M 属性定义报告特定资源的条件。高级文档中介绍了这些设置。
勾选 “Attrubutes” 以获取设备连接时要获取的数据,并将其存储为 蟹立方物联网平台 属性
勾选 Telemetry 和/或 Observe 框,如果您希望 Server 观察它们并获取更新的值
保存更改
注意:如果取消选中对象(遥测、属性、观察)中的所有项目 - 此对象将不会显示在设备配置文件中。
Transport Configuration 还允许您定义 bootstrap 和其他设置。
步骤 3.定义 LwM2M 设备凭证
我们假设您已经使用上一步创建了 LwM2M 设备配置文件。
现在,让我们使用我们的配置文件创建设备并配置 LwM2M 凭证。蟹立方物联网平台 支持 4 种不同类型的凭据:预共享密钥 (PSK)、原始公共 Ket (RPK)、X.509 证书和“无安全性”模式。
默认为 No Security mode
添加设备凭据:预共享密钥
添加设备凭证:原始公钥
添加设备凭据:X.509 证书
为简单起见,我们将使用普通 UDP 和 “No Security” 模式连接设备。要连接此类设备,我们只需要在设备凭证中指定其终端节点名称。
在 No Security 模式下,Endpoint Client Name 用于标识设备
您可以在启用 DTLS 模式的情况下使用其他类型的凭证。有关更多信息,请参阅 DTLS 配置。
步骤 4.连接设备
我们假设您已经使用上一步预置了 LwM2M 设备凭证,并且还构建了 Eclipse Wakaama 测试客户端。现在,你已准备好打开设备并观察传入的遥测数据。
让我们启动测试客户端:
./lwm2mclient -h lwm2m.蟹立方物联网平台.cloud -n UniqueEndpointName -p 5685 -c
where
'lwm2m.蟹立方物联网平台.cloud' 是 LwM2M 服务器的主机名;
'5685' 是 LwM2M 服务器的端口;
'UniqueEndpointName' 是终端节点的唯一名称。请将其替换为 IMEI 或其他唯一 ID。 LwM2M 传输实现还将与设备的通信日志存储到遥测中。您应该会在 device telemetry (设备遥测) 选项卡中看到 “transportLog”。
使用 Wakaama 客户端的终端窗口
您可以在 Transport Log (传输日志) 部分看到最后一条消息
RPC Commands
LwM2M 传输支持反映设备管理和服务支持接口和信息报告接口子集的 RPC 命令。 LwM2M 服务器使用设备管理和服务支持接口来访问已注册的 LwM2M 客户端提供的对象实例和资源。Resource 支持的作是使用 Object Template 在 Object 定义中定义的。 LwM2M 服务器使用信息报告接口来观察已注册的 LwM2M 客户端上资源的任何更改,并在新值可用时接收通知。此观察关系是通过向 Object、Object Instance 或 Resource 的 L2M2M Client 发送 “Observe” 或 “Observe-Composite”作来启动的。执行 “Cancel Observation” 或 “Cancel Observation-Composite”作时,观测结束。 我们将使用 Debug Terminal 小部件向设备发送命令。
要执行面向属性的命令,有两种方法可以指定目标资源:按 Resource ID 和 Key。
资源 ID 是“/ObjectId/ObjectInstance/ResourceID”数字的组合,其中:
- 'ObjectId' 表示对象编号。用于对设备上与特定功能相关的资源进行分组的对象。
- 'ObjectInstance' 表示要读取的对象实例。
- 'ResourceID' 表示要读取的资源。 示例:
Read {"id":"/3/0/9"}
Key 是分配给特定属性的自定义用户友好名称:
示例:
Read {"key":"batteryLevel"}
为了能够使用密钥,您必须将其分配给 Device Profile 配置部分中的属性:
- 转到 Device Profiles 页面;
- 单击 Profile name;
- 点击右上角的 “pencil” 按钮编辑个人资料;
- 转到 Transport configuration (传输配置) 选项卡;
- 切换到 LWM2M 型号选项卡;
- 选择目标对象并展开 Attributes 列表;
- 勾选所需属性上的“Attribute”复选框,然后键入 Key name;
- 单击 save。
您可以在下面找到 蟹立方物联网平台 平台支持的 LWM2M 协议的命令的使用示例。请注意,您的目标客户端可能并不支持所有这些命令,请参阅客户端的文档以获取有关支持命令的详细信息。
读取作
“Read”作用于访问 Resource、Resource Instance、Resource Instances 数组、Object Instance 或 Object 的所有 Object Instances 的值。
示例:通过 ID 读取资源的值
# Request:
Read {"id":"/3/0/9"}
# Response:
{"result":"CONTENT","value":"LwM2mSingleResource [id=9, value=100, type=INTEGER]"}
More examples:
- 按 ID 和版本读取资源的值
# Request:
Read {"id":"/3_1.0/0/9"}
# Response:
{"result":"CONTENT","value":"LwM2mSingleResource [id=9, value=20, type=INTEGER]"}
- 通过 key 读取资源的值
# Request:
Read {"key":"batteryLevel"}
# Response:
{"result":"CONTENT","value":"LwM2mSingleResource [id=9, value=27, type=INTEGER]"}
- 读取对象实例
# Request:
Read {"id":"/3/0"}
# Response:
{"result":"CONTENT","value":"LwM2mObjectInstance [id=0, resources={0=LwM2mSingleResource [id=0, value=蟹立方物联网平台 Test Device,
type=STRING], 1=LwM2mSingleResource [id=1, value=Model 500, type=STRING], 2=LwM2mSingleResource [id=2, value=TH-500-000-0001,
type=STRING], 3=LwM2mSingleResource [id=3, value=Test蟹立方物联网平台@TestMore1024_2.04, type=STRING], 6=LwM2mSingleResource [id=6,
value=1, type=INTEGER], 7=LwM2mSingleResource [id=7, value=96, type=INTEGER], 8=LwM2mSingleResource [id=8, value=37, type=INTEGER],
9=LwM2mSingleResource [id=9, value=75, type=INTEGER], 10=LwM2mSingleResource [id=10, value=110673, type=INTEGER],
11=LwM2mMultipleResource [id=11, values={0=LwM2mResourceInstance [id=0, value=1, type=INTEGER]}, type=INTEGER], 13=LwM2mSingleResource
[id=13, value=Thu Jul 01 16:39:49 EEST 2021, type=TIME], 14=LwM2mSingleResource [id=14, value=+03, type=STRING], 15=LwM2mSingleResource
[id=15, value=Europe/Kiev, type=STRING], 16=LwM2mSingleResource [id=16, value=U, type=STRING], 17=LwM2mSingleResource
[id=17, value=smart meters, type=STRING], 18=LwM2mSingleResource [id=18, value=1.01, type=STRING], 19=LwM2mSingleResource [id=19,
value=1.02, type=STRING], 20=LwM2mSingleResource [id=20, value=2, type=INTEGER], 21=LwM2mSingleResource [id=21, value=256000, type=INTEGER]}]"}
发现作
“发现”作用于发现对象或对象实例上可用的 LwM2M 资源。此作可用于发现在给定 Object Instance 中实例化了哪些 Resource。返回的负载是每个目标对象、对象实例或资源的应用程序/链接格式 CoRE 链接RFC6690列表,以及它们分配或附加的属性,包括对象版本属性(如果需要)。
示例:发现附加到对象的资源
# Request:
Discover {"id":"/3"}
# Response:
{"result":"CONTENT","value":"</3>,</3/0/0>,</3/0/1>,</3/0/2>,</3/0/3>,</3/0/4>,</3/0/5>,</3/0/6>,</3/0/7>,</3/0/8>,</3/0/9>,</3/0/10>,</3/0/11>,</3/0/12>,</3/0/13>,</3/0/
14>,</3/0/15>,</3/0/16>"}
更多示例:
- 发现附加到对象实例的资源
# Request:
Discover {"id":"/3/0"}
# Response:
{"result":"CONTENT","value":"</3/0>,</3/0/0>,</3/0/1>,</3/0/2>,</3/0/3>,</3/0/4>,</3/0/5>,</3/0/6>,</3/0/7>,</3/0/8>,</3/0/9>,</3/0/10>,</3/0/11>,</3/0/12>,</3/0/13>,</3/
0/14>,</3/0/15>,</3/0/16>"}
- 发现资源是否由 Id 实例化
# Request:
Discover {"id":"/3/0/1"}
# Response:
{"result":"CONTENT","value":"</3/0/1>"}
- 发现属性是否由 Key 实例化
# Request:
Discover {"key":"batteryLevel"}
# Response:
{"result":"CONTENT","value":"</3/0/9>"}
写入作
“Write”作用于更改 Resource 的值、Resource Instance 的值、数组的值 的资源实例或对象实例中多个资源的值。“Write”作也可以是 用于请求删除或分配多实例资源的特定实例。
该请求包括要写入的值,以 7.4 中定义的数据格式之一进行编码。用于传输资源信息的数据格式:纯文本、不透明、TLV、JSON、CoRE Link、CBOR、SenML JSON 和 SenML CBOR。
有两种机制可以更改多个 Resource 或 Resource Instances 数组:
Replace:将 Object Instance 或 Resource 替换为 “Write”作中提供的新值。当 Resource 是 Multiple-Instance Resource 时,现有的 Resource Instances 数组将替换为 LwM2M Client 授权该作的条件。
Partial Update:更新新值中提供的 Resource,并保持其他现有 Resource 不变。当资源是多实例资源时,现有的资源实例数组会更新,这意味着可能会创建或覆盖一些实例,以满足 LwM2M 客户端授权此类作的条件。无法通过部分更新进行删除。 示例:WriteUpdate 单个 ObjectInstance 资源
# Request:
WriteUpdate {"id":"/3/0","value":{"14":"+5","15":"Kiyv/Europe"}}
# Response:
{"result":"CHANGED"}
更多示例:
WriteUpdate 多个 ObjectInstance 资源
# Request:
WriteUpdate {"id": "/19/0","value": {"0":{"0":"00ad456756", "25":"25ad456756"}}}
# Response:
{"result":"CHANGED"}
WriteUpdate 多个资源
# Request:
WriteUpdate {"id": "/19/0/0","value": {"0":"00ad456756", "25":"25ad456756"}}
# Response:
{"result":"CHANGED"}
WriteReplace 单个资源
# Request:
WriteReplace {"id":"/19/0/0","value":"0081"}
# Response:
{"result":"CHANGED"}
write按 Key 替换单个资源
# Request:
WriteReplace {"key":"timezone","value":"+10"}
# Response:
{"result":"CHANGED"}
WriteReplace 多个资源
# Request:
WriteReplace {"id": "/19_1.1/0/0","value": {"0":"00ad456797", "25":"25ad456700"}}
# Response:
{"result":"CHANGED"}
Write-Attributes作
在使用“Write-Attributes”作时,只能更改 NOTIFICATION 类中的属性。Object and Resource attributes 部分提供了有关 “Write-Attributes”作支持的属性的说明: 最小期间、最大期间、大于、小于、步长。 该作允许在同一作中修改多个 Attributes。
示例:编写多个属性
# Request:
WriteAttributes {"id":"/19/0/0","attributes":{"pmax":120, "pmin":10}}
# Response:
{"result":"CHANGED"}
Read-Composite作
LwM2M 客户端可以支持“Read-Composite”作。 LwM2M 服务器可以使用 “Read-Composite”作来选择性地读取对象的任意组合, 单个请求中不同或相同对象的 Object Instance(s)、Resources(资源)和/或 Resource Instances(资源实例)。的列表 要读取的元素以 SenML Pack 的形式提供,其中记录包含基本名称和/或名称字段,但没有值 领域。Read-Composite作被视为非原子作,并由客户端作为最大努力处理。也就是说,如果有的话 没有要返回的有效值,则它们将不会包含在响应中。
示例:读取多个对象
# Request:
ReadComposite {"ids":["/3/0/9", "/1_1.2"]}
# Response:
{"result":"CONTENT","value":"{/3/0/9=LwM2mSingleResource [id=9, value=75, type=INTEGER], /1=LwM2mObject [id=1, instances={0=LwM2mObjectInstance [id=0, resources={0=LwM2mSingleResource [id=0, value=123, t
ype=INTEGER], 1=LwM2mSingleResource [id=1, value=300, type=INTEGER], 6=LwM2mSingleResource [id=6, value=false, type=BOOLEAN], 22=LwM2mSingleResource [id=22, value=U, type=STRING], 7=LwM2mSingleResource [
id=7, value=U, type=STRING]}]}]}"
更多示例:
按 Key 读取复合多个资源
# Request:
ReadComposite {"keys":["state", "updateResult", "pkgversion", "batteryLevel"]}
# Response:
{"result":"CONTENT","value":"{/5/0/7=LwM2mSingleResource [id=7, value=, type=STRING], /5/0/5=LwM2mSingleResource [id=5, value=0,
type=INTEGER], /5/0/3=LwM2mSingleResource [id=3, value=0, type=INTEGER], /
3/0/9=LwM2mSingleResource [id=9, value=81, type=INTEGER]}"}
Read-Composite 多个对象实例
# Request:
ReadComposite {"ids":["/3/0", "/1_1.2/0"]}
# Response:
{"result":"CONTENT","value":"{/3/0=LwM2mObjectInstance [id=0, resources={0=LwM2mSingleResource [id=0, value=蟹立方物联网平台 Test Device,
type=STRING], 1=LwM2mSingleResource [id=1, value=Model 500, type=STRING], 2=LwM2mSingleResource [id=2, value=TH-500-000-0001, type=STRING],
3=LwM2mSingleResource [id=3, value=Test蟹立方物联网平台@TestMore1024_2.04, type=STRING], 6=LwM2mSingleResource [id=6, value=1, type=INTEGE
R], 7=LwM2mSingleResource [id=7, value=2, type=INTEGER], 8=LwM2mSingleResource [id=8, value=61, type=INTEGER], 9=LwM2mSingleResource [id=9,
value=25, type=INTEGER], 10=LwM2mSingleResource [id=10, value=102044, type=INTEGER], 11=LwM2mMultipleResource [id=11,
values={0=LwM2mResourceInstance [id=0, value=1, type=INTEGER]}, type=INTEGER], 13=LwM2mSingleResource [id=13,
value=Thu Jul 01 16:49:25 EEST 2021, type=TIME], 14=LwM2mSingleResource [id=14, value=+03, type=STRING], 15=LwM2mSingleResource [id=15,
value=Europe/Kiev, type=STRING], 16=LwM2mSingleResource [id=16, value=U, type=STRING], 17=LwM2mSingleResource [id=17, value=smart meters,
type=STRING], 18=LwM2mSingleResource [id=18, value=1.01, type=STRING], 19=LwM2mSingleResource [id=19, value=1.02, type=STRING],
20=LwM2mSingleResource [id=20, value=1, type=INTEGER], 21=LwM2mSingleResource [id=21, value=256000, type=INTEGER]}], /1/0=LwM2mObjectInstance
[id=0, resources={0=LwM2mSingleResource [id=0, value=123, type=INTEGER], 1=LwM2mSingleResource [id=1, value=300, type=INTEGER],
6=LwM2mSingleResource [id=6, value=false, type=BOOLEAN], 22=LwM2mSingleResource [id=22, value=U, type=STRING], 7=LwM2mSingleResource [id=7,
value=U, type=STRING]}]}"}
Write Composite作
LwM2M 客户端可以支持 “Write-Composite”作。 与 “Write”作相反,“Write”作的范围仅限于单个 Object 的单个实例的 Resource, Server 可以使用 “Write-Composite”作来更新多个不同 Resource 的值 一个或多个 Object 的不同实例。Write-Composite作提供 所有要更新的资源及其新值,使用 SenML JSON/CBOR 格式。与 write作不同, 未提供的资源不受作的影响。
“Write-Composite”作是原子作,不能部分成功。也就是说,如果客户端支持此功能 作中,它必须拒绝 Server 请求,因为它无法成功地将所有请求的值写入请求的 资源列表。因此,在处理 Write-Composite 之前,客户端必须确保所有寻址对象都存在 以及 Server 对这些 Object 和 Resource 具有写入访问权限。
示例:WriteComposite 到多个对象
# Request:
WriteComposite {"nodes":{"/3/0/14":"+04", "/1/0/2":100, "/5/0/1":"coap://localhost:5685"}}
# Response:
{"result":"CHANGED"}
更多示例:
具有多个 Key 的 WriteComposite
#
WriteComposite {"nodes":{"timezone":"+04", "defaultMinimumPeriod":100, "packageUri":"coap://localhost:5685"}}
# Response:
{"result":"CHANGED"}
执行作
LwM2M 服务器使用“执行”作来启动某些作,并且只能对单个资源执行。
示例:执行资源
# Request:
Execute {"id":"5/0/2"}
# Response:
{"result":"CHANGED"}
删除作
“删除”作用于 LwM2M 服务器删除 LwM2M 客户端中的对象实例。 LwM2M 服务器在 LwM2M 客户端中删除的对象实例必须是符合以下条件的对象实例 由 LwM2M 客户端使用客户端的 “Register” 和 “Update”作向 LwM2M 服务器公布 注册界面。
唯一的例外是强制性设备对象 (ID:3) 的单个实例,它不应受 任何 Delete作。
示例:删除对象实例
# Request:
Delete {"id":"/19/1"}
# Response:
{"result":"DELETE"}
观察作
LwM2M 服务器对特定 Resource(Object 中的资源)的更改发起观察请求 实例或 LwM2M 客户端中对象的所有对象实例。 “观察”作的相关参数在通知属性 Write-Attributes作中介绍,以及 参数由 “Write-Attributes”作配置。
示例:观察资源
# Request:
Observe {"id":"/3/0/9"}
# Response:
{"result":"CONTENT","value":"LwM2mSingleResource [id=9, value=28, type=INTEGER]"}
更多示例:
观察对象实例
# Request:
Observe {"id":"/3/0"}
# Response:
{"result":"CONTENT","value":"LwM2mObjectInstance [id=0, resources={0=LwM2mSingleResource [id=0, value=蟹立方物联网平台
Test Device, type=STRING], 1=LwM2mSingleResource [id=1, value=Model 500, type=STRING], 2=LwM2mSingleResource [id=2,
value=TH-500-000-0001, type=STRING], 3=LwM2mSingleResource [id=3, value=Test蟹立方物联网平台@TestMore1024_2.04, type=STRING],
6=LwM2mSingleResource [id=6, value=1, type=INTEGER], 7=LwM2mSingleResource [id=7, value=90, type=INTEGER], 8=LwM2mSingleResource
[id=8, value=29, type=INTEGER], 9=LwM2mSingleResource [id=9, value=19, type=INTEGER], 10=LwM2mSingleResource [id=10, value=76962,
type=INTEGER], 11=LwM2mMultipleResource [id=11, values={0=LwM2mResourceInstance [id=0, value=1, type=INTEGER]}, type=INTEGER],
13=LwM2mSingleResource [id=13, value=Wed Jul 31 22:49:45 EET 1940, type=TIME], 14=LwM2mSingleResource [id=14, value=+5, type=STRING],
15=LwM2mSingleResource [id=15, value=Kiyv/Europe, type=STRING], 16=LwM2mSingleResource [id=16, value=U, type=STRING],
17=LwM2mSingleResource [id=17, value=smart meters, type=STRING], 18=LwM2mSingleResource [id=18, value=1.01, type=STRING],
19=LwM2mSingleResource [id=19, value=1.02, type=STRING], 20=LwM2mSingleResource [id=20, value=6, type=INTEGER], 21=LwM2mSingleResource
[id=21, value=256000, type=INTEGER]}]"}
取消观察作
“取消观察”作从 LwM2M 服务器发送到 LwM2M 客户端以结束观察 之前使用 “Observe”作创建的关系
示例:按 ID 取消对资源的观察
# Request:
ObserveCancel {"id":"/5/0/7"}
# Response:
{"result":"CONTENT","value":"1"}
更多示例:
示例:按 Key 取消对资源的观察
# Request:
ObserveCancel {"key":"updateResult"}
# Response:
{"result":"CONTENT","value":"1"}
取消所有观测作 “取消所有观察”作是 蟹立方物联网平台 特定的作,允许取消所有观察 在设备上
示例:取消所有观测值
# Request:
ObserveCancelAll
# Response:
{"result":"CONTENT","value":"8"} // - cancelled 8 observations
读取所有观测值作 “Read All Observations”作是特定于 蟹立方物联网平台 的作,允许获取所有观察结果 。
示例:读取所有观测值
# Request:
ObserveReadAll
# Response:
{"result":"CONTENT","value":"[\"/5/0/7\",\"/3/0/3\",\"/5/0/3\",\"/5/0/5\"]"}
发现所有作
“Discover All Observations”作是特定于 蟹立方物联网平台 的作,允许获取对象和资源的层次结构。 在客户端上实例化。执行 DiscoverAll 时,它不会向客户端设备发送任何请求,而是向客户端设备发送任何请求 返回客户端设备的 LwM2M 模型,该模型是在设备连接到服务器期间创建的。 此命令对于设备设置和故障排除非常有用,因为它允许查看可用对象及其 版本。
示例:发现所有资源
# Request:
DiscoverAll
# Response:
{"result":"CONTENT","value":"[{\"url\":\"/\",\"attributes\":{\"ct\":\"110\",\"rt\":\"\\\"oma.lwm2m\\\"\"}},
{\"url\":\"/1\",\"attributes\":{\"ver\":\"1.1\"}},{\"url\":\"/1/0\",\"attributes\":{}},{\"url\":\"/2/0\",
\"attributes\":{}},{\"url\":\"/3/0\",\"attributes\":{}},{\"url\":\"/4/0\",\"attributes\":{}},{\"url\":\"/5/0\",
\"attributes\":{}},{\"url\":\"/6/0\",\"attributes\":{}},{\"url\":\"/7/0\",\"attributes\":{}},{\"url\":\"/31024\",
\"attributes\":{\"ver\":\"1.0\"}},{\"url\":\"/31024/10\",\"attributes\":{}},{\"url\":\"/31024/11\",\"attributes\":{}},
{\"url\":\"/31024/12\",\"attributes\":{}}]"}
固件无线更新
LwM2M 协议允许您将无线 (OTA) 固件更新上传和分发到设备。请先阅读 阅读以下文章 OTA 更新,了解如何上传和管理 固件包和更新过程。
LwM2M 为 OTA 目的定义了对象 5:固件更新对象,该对象支持固件映像的管理,并包含用于安装固件包的资源。 更新固件,并在更新固件后执行作。
请注意,Object 5 是一个可选对象,某些设备可能不支持。
为了能够使用对象 5 运行更新,您必须确保对象 5 存在于设备配置文件 LwM2M 模型中,并在设备上设置以下属性的观察值,服务器使用这些属性从中获取反馈 设备状态 更新进程:
"/3/0/3" - Firmware Version
"/5/0/3" - State
"/5/0/5" - Update Result
"/5/0/7" - PkgVersion
固件更新过程如下所示:描述为 UML 2.0 状态图的固件更新机制。状态图由绘制为圆角矩形的状态和过渡 绘制为连接各州的箭头。
有几种方法可以使用 LwM2M 传输运行 OTA 固件更新。您可以在设备中选择策略 配置文件,因此它将应用于该配置文件的所有设备:
使用 Object 5 和 Resource 0 将固件更新作为二进制文件推送。
固件包通过分块传输到 Resource 0 直接从服务器推送到设备 对象 5.下载完成后,应使用可执行文件触发更新过程 资源 “/5/0/2”。完整过程如下所示:LwM2M 服务器将固件映像推送到 LwM2M 客户端的示例。
自动生成唯一的 CoAP URL 以下载软件包并通过 Object 5 和资源 1 推送固件包。
此选项允许使用位于第三方存储上的映像文件运行固件更新。在这种情况下, server 生成一个 CoAP-URL 并发送给客户端,客户端从外部下载固件镜像 资源,而无需将图像传输到服务器。下载完成后,更新过程应 使用可执行资源 “/5/0/2” 触发。完整过程如下所示:客户端获取示例 固件映像
软件无线更新
LwM2M 协议允许您将无线 (OTA) 软件更新上传和分发到设备。请先阅读 阅读以下文章 OTA 更新,了解如何上传和管理 软件包和更新过程。
与固件更新过程相比,设备软件更新有一些差异:软件管理 过程分为 2 个子过程:软件包安装过程和软件激活过程。
LwM2M 为软件管理目的定义了对象 9:软件管理对象,它使远程 M2M 设备中的软件管理,包括用于交付、执行安装和激活的资源 软件包和报告状态。
请注意,Object 9 是一个可选对象,某些设备可能不支持。
为了能够使用 Object 9 运行更新,您必须确保 Object 9 存在于设备配置文件中 LwM2M 模型,并在设备上设置以下属性的观察值,服务器使用这些属性来获取 设备对更新过程状态的反馈:
"/3/0/19" - Software Version
"/9/0/0" - PkgName
"/9/0/1" - PkgVersion
"/9/0/2" - Package ID
"/9/0/3" - Package URI
"/9/0/7" - Update State
"/9/0/9" - Update result
有几种方法可以使用 LwM2M 传输运行 OTA 软件更新。您可以在设备中选择策略 配置文件,因此它将应用于该配置文件的所有设备:
使用 Object 9 和 Resource 2 将软件更新作为二进制文件推送。
软件包通过分块传输到 Resource 2 从 Server 直接推送到设备 对象 9.
自动生成唯一的 CoAP URL 以下载软件包并通过 Object 9 和 Resource 3 推送软件包。
此选项允许使用位于第三方存储上的映像文件运行软件更新。在这种情况下 服务器生成一个 CoAP-URL 并发送给客户端,客户端从外部下载软件镜像 资源,而无需将图像传输到服务器。
高级主题
Object 和 Resource 属性
请注意,LwM2M 上下文中的属性是不同的,并且与 Server、Client 或 Shared 属性无关 蟹立方物联网平台 平台。
在 LwM2M 协议中,属性是可以附加到 Object、Object Instance 或 Resource 的元数据。这些 attributes 可以扮演各种角色,从仅携带信息到携带参数以设置某些 LwM2M 客户端上的作(例如,通知)。
附加到 Objects、Object Instances、Resources 的属性分别命名为 O-Attribute、OI-Attribute、R-Attribute。
这些属性可以携带在 Registration 和 Discover作的消息负载中;他们也可能是 updated - 当可写时 - 通过 Write-Attributes作。
有两种类型的属性:
PROPERTIES 类属性或 Object 属性
这些 Attributes 的作用是提供元数据,这些元数据可以将有用的信息传达给 LwM2M 服务器,以便 示例 简化数据管理。蟹立方物联网平台 支持 Object Version 属性,该属性表示 关联的 Object,并显示在 DiscoverAll 命令的结果中。
您可以在此处找到有关 LwM2M 对象属性中所有可用属性的更多详细信息:PROPERTIES 类属性
NOTIFICATION 类属性或资源属性
这些 R 属性的作用是向 “Notify”作提供参数,该作用于资源 观察。任何可读的 Resource 都可以具有这样的 R 属性。
TB 平台上提供了以下 NOTIFICATION 属性来配置观察参数:
“pmin” - 最短时间段 - 指示 LwM2M 客户端必须在两个通知之间等待的最短时间(以秒为单位)。 如果应该生成观察到的 Resource 的通知,但它是在 pmin 到期之前, 通知必须在 pmin 过期后立即发送。在没有此参数的情况下,Minimum Period 为 由 LwM2M 服务器账户中设置的默认最小期间定义。
“pmax” - 最长期限 - 指示 LwM2M 客户端在两个通知之间可以等待的最长时间(以秒为单位)。 当此 “最长期限” 在最后一次通知后过期时,必须发送新的通知。在缺席 中,“最大周期”由 LwM2M 服务器中设置的默认最大周期定义 Account 或视为 0。值 0 表示必须忽略 pmax。最大 period 参数 必须大于 minimum period 参数,否则将忽略 pmax 到 应用了这种不一致的 timing 条件。
“gt” - 大于 - 定义阈值上限。当存在此属性时,LwM2M 客户端必须通知 每次 Observed Resource 值超过 pmin 参数的此阈值时,Server 以及 有效的“更改值条件”(请参阅上面的通知条件)。
“lt” - 小于 - 定义阈值下限。当存在此属性时,LwM2M 客户端必须通知 Server 每次 Observed Resource 值超过 pmin 参数和 valid 的阈值时 “更改值条件”(请参阅上面的通知条件)。
“st” - Step - 定义阈值下限值。当存在此属性时,LwM2M 客户端必须通知服务器 每次 Observed Resource 值超过 pmin 参数的此阈值和有效的 “Change Value Conditions“(请参阅上面的通知条件)。
请在此处找到有关LwM2M NOTIFICATION属性中所有可用的更多详细信息..
通知属性可以在 Device Profile 中配置,请按照指南进行作:
DTLS 配置
蟹立方物联网平台 平台支持使用 DTLS 的安全连接。DTLS,代表数据报传输层 安全性基于传输层安全性 (TLS) 协议,并建立在用户数据报协议 (UDP) 之上。 蟹立方物联网平台 允许将 DTLS 与设备的 LwM2M 传输连接一起使用。
您可以在此处找到有关的详细信息。
蟹立方物联网平台 上有三种可用于 LwM2M DTLS 的身份验证方法:使用预共享密钥 (PSK)、使用 原始公钥 (RPK) 并使用 X.509 证书。
要使用 DTLS,最终用户设备必须使用安全端口 5686 连接到 蟹立方物联网平台 服务器。
为了演示目的,我们将使用乐山 Demo Client,请参考链接进行下载和配置:这里
1. 预共享密钥模式 (PSK)。
预共享密钥配置文件为将 DTLS 集成到 LwM2M 中提供了自预共享以来最节省资源的解决方案 [RFC7925] 中推荐的密码套件需要设备中的最小闪存空间和 RAM。
对称加密算法只需要最小的计算开销。交换消息的大小 也保持在最低限度。但是,它也有一个缺点:对称密钥需要预先配置为两者 通信端点。
您只需三个字符串即可在 Device 配置文件中配置连接:
- 终端节点客户端名称:用于标识设备,可以是任何文本字符串。
- 客户端身份 (PSK 身份) 密钥:任何文本字符串。
- PSK 密钥(安全密钥):应为 HexDec 格式的随机序列,长度为 32、64 或 128 个字符。 乐山 Demo 客户端使用示例:
Endpoint client name= "ClientPsk";
Client identity (PSK identity) = "ClientPskIdentity";
Client key (PSK key or PSK security key) = "0123456789ABCDEF0123456789ABCDEF";
在 PSK 模式下启动 “Leshan client demo” 的示例命令:
java -jar leshan-client-demo.jar -u localhost:5686 -lh 0.0.0.0 -lp 10004 -n ClientPsk -i ClientPskIdentity
-p 0123456789ABCDEF0123456789ABCDEF
Leshan Client Demo Interactive Console :
...
DefaultRegistrationEngine 2021-09-30 19:09:52,789 [INFO] Trying to register to coaps://192.168.1.81:5686 ...
LeshanClientDemo 2021-09-30 19:09:52,830 [INFO] DTLS Full Handshake initiated by client : STARTED ...
LeshanClientDemo 2021-09-30 19:09:52,949 [INFO] DTLS Full Handshake initiated by client : SUCCEED
DefaultRegistrationEngine 2021-09-30 19:09:52,990 [INFO] Registered with location '/rd/vXMGfVFgQi'.
...
2. 原始公钥 (RPK) 模式。
原始公钥配置文件提供位于预共享密钥和基于证书的模式之间的功能,以及 结合了这两个配置文件的优点。使用非对称加密技术可以提高安全性,但避免 与证书和公钥基础设施相关的开销。
要配置连接,您需要执行以下步骤:
- 生成客户端密钥并将客户端公钥复制粘贴到 蟹立方物联网平台 平台上的 Device Credentials - Client Key 中。
- 生成 Server 密钥并将其添加到 Server 密钥存储文件 lwm2mserver.jks 中,将文件复制回 Server 安装文件夹。
- 配置客户端的连接。 我们将使用 OpenSSl 工具并按照乐山的指南进行作:这里
**注意:**此步骤需要安装了 Java 的基于 Linux 的作系统。
- 创建一个单独的文件夹,我们将在其中保存所有生成的密钥。
- 蟹立方物联网平台 将服务器密钥保存在密钥存储文件 “lwm2mserver.jks” 中,请找到此文件并将其复制到我们的文件夹中。 默认密钥文件位置为:
/common/transport/lwm2m/src/main/resources/credentials/lwm2mserver.jks
- 我们将使用下面的脚本来生成所有必要的密钥。只需使用任何文本编辑器创建文本文件,复制 脚本,并使用 *.sh 扩展名保存文件,例如 'generate-rpk.sh' generate-rpk.sh
#!/bin/bash
#
# Copyright © 2016-2021 The 蟹立方物联网平台 Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# RPK. Generation of the keys.
echo "====START RPK ========"
echo "Generating client keys..."
# Create EC key pair (private and public) using default openssl pem encoding:
openssl ecparam -out keysClient.pem -name prime256v1 -genkey
# Convert Client Private Key to PKCS#8 format (DER encoding):
openssl pkcs8 -topk8 -inform PEM -outform DER -in keysClient.pem -out cprik.der -nocrypt
# Output Client Public Key portion in SubjectPublicKeyInfo format (DER encoding):
openssl ec -in keysClient.pem -pubout -outform DER -out cpubk.der
echo "Client public key in base64 format. Copy this key to the 蟹立方物联网平台 - Client Key field in Device Credentials"
base64 cpubk.der
# get server keys
# Importing keystore lwm2mserver.jks alias="server" to scertServer.p12
keytool -importkeystore -srckeystore lwm2mserver.jks -alias server -destkeystore scertServer.p12 -deststoretype PKCS12
# Importing keystore lwm2mserver.jks to scert.p12...
# Enter destination keystore password: server_ks_password
# Re-enter new password: server_ks_password
# Enter source keystore password: server_ks_password
# Generating scertServer.pem:
openssl pkcs12 -in scertServer.p12 -nodes -nocerts -out scertServer.pem
echo Enter Import Password: server_ks_password
# Server public key in base64 format (spubk.pem):
openssl ec -in scertServer.pem -pubout -outform DER -out spubk.der
请注意,请使用 “lwm2mserver.jks” 文件的默认密码编写脚本。如果您打算使用其他密码, 请在 “蟹立方物联网平台.yml” 配置文件中更新它:
...
lwm2m:
...
server:
...
security:
...
key_alias: "${LWM2M_SERVER_KEY_ALIAS:server}"
key_password: "${LWM2M_SERVER_KEY_PASSWORD:server_ks_password}"
...
- 要运行该脚本,请使用以下命令:
chmod +x generate-rpk.sh
sudo ./generate-rpk.sh
此脚本将运行 keytool 和 ssh 实用程序。它将生成以下输出文件:
- lwm2mserver.jks - 服务器密钥库文件。
- keysClient.pem - 客户端公钥 \ 私钥对
- cprik.der - 采用 Base64 加密的 DER 格式的客户端私钥
- cpubk.der - DER 格式的客户端公钥
- spubk.der - DER 格式的服务器公钥
- scertServer.pem - 无加密的服务器公钥
- 在 蟹立方物联网平台 平台上配置 Device: 终端节点名称:输入用于标识客户端设备的唯一文本字符串 客户端密钥: 在终端中,使用 Base64 命令打开 cprik.der 文件,并将代码复制到 Client key 字段:
#command:
$ Base64 cpubk.der
#Output:
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEdvBZZ2vQRK9wgDhctj6B1c7bxR3Z0wYg1+YdoYFnVUKWb+rIfTTyYK9tmQJx5Vlb5fxdLnVv1RJOPiwsLIQbAA==
- RPK 模式下启动 “Leshan demo client” 的示例命令:
#command:
$ java -jar leshan-client-demo.jar -u localhost:5686 -lh 0.0.0.0 -lp 10004 -n ClientRpk -cpubk cpubk.der -cprik cprik.der -spubk spubk.der
#Output:
Leshan Client Demo Interactive Console :
Commands:
help Displays help information about the specified command
create Enable a new Object
delete Disable a new object
update Trigger a registration update.
send Send data to server
move Simulate client mouvement.
Press Ctl-C to exit.
LeshanClient 2021-10-27 10:37:21,196 [INFO] Starting Leshan client ...
CaliforniumEndpointsManager 2021-10-27 10:37:21,470 [INFO] New endpoint created for server coaps://18.184.200.162:5686 at coaps://[0:0:0:0:0:0:0:0]:10004
LeshanClient 2021-10-27 10:37:21,472 [INFO] Leshan client[endpoint:leshan-rpkz] started.
DefaultRegistrationEngine 2021-10-27 10:37:21,474 [INFO] Trying to register to coaps://18.184.200.162:5686 ...
LeshanClientDemo 2021-10-27 10:37:21,549 [INFO] DTLS Full Handshake initiated by client : STARTED ...
LeshanClientDemo 2021-10-27 10:37:21,729 [INFO] DTLS Full Handshake initiated by client : SUCCEED
DefaultRegistrationEngine 2021-10-27 10:37:21,771 [INFO] Registered with location '/rd/yyIIQFyg6H'.
DefaultRegistrationEngine 2021-10-27 10:37:21,773 [INFO] Next registration update to coaps://18.184.200.162:5686 in 53s...
```