一、 Device Management connectivity
- Device Management 提供受限IoT设备和企业级软件或Web应用间一种连接方案。
- Device onboarding(下面翻译为“初始化”):设备第一次建立连接到我们的设备管理帐户
- 设备可以在生产阶段预分配到一个帐户;如果没有,会有一个注册ID,在Onboarding阶段将其和帐户绑定。
二、 Establishing a connection
- 设备由两种信息来标识:
①设备ID:全局唯一的,由Device Management 生成,用于在使用API时可以引用设备。设备首次连接时,设备管理服务会自动生成此ID。在 Key and Configuration Manager 中是mbed.InternalEndpointName。
②终端名称:工厂生产设备时给出。 在 Key and Configuration Manager 中是 mbed.InternalEndpointName。 - 注册完成后,Web应用或APP回得到设备ID的返回,可以在后面通过设备ID操作设备。
- 设备建立连接有两个重要概念:Bootstrap(引导)和Registration(注册)。
- 设备管理提供两种初始化设备的方式,用不同的方式会影响到后面的连接保持:
①通过Bootstrap:设备出厂时有一个Bootstrap证书。设备会先连接到Bootstrap服务,该服务会提供一个LwM2M 账户证书用于注册。通过这种方式的,后面设备可以恢复到Bootstrap阶段,更新LwM2M证书。
②直接使用Pelion LwM2M 服务证书:设备出厂时有一个LwM2M服务证书,设备会直接注册到LwM2M服务。通过这种方式的,没法恢复到Bootstrap阶段。对后面证书更新和连接保持存在一定限制。 - 设备会根据你的设置去选择用那种方式连接,要设置好use-bootstrap参数的值。
- 在开发期间,可以使用“ Developer certificate”(开发人员证书)选项。它使用bootstrap、并从设备管理网站获得证书(并编译成二进制文件),而无需工厂工具。
- Bootstrap(引导)流程:设备从Device Management bootstrap服务获取其Pelion LwM2M服务证书。此流程为连接维护提供了一个优势:如果设备过期或变为无效,设备可以回退到引导流程以续订其LwM2M凭据。
①设备管理客户端通过setup()函数检查是否有LwM2M服务器证书。如果有证书,设备会直接注册到LwM2M服务器;没有的话,会先连接到bootstrap服务器。设备通过出厂预置的证书(或者开发人员证书)连接到bootstrap 服务器。
②对于一个新设备,设备管理会在设备目录中新建一个设备记录,分配一个新的设备ID给它,将其状态设置为cloud enrolling。如果设备已经初始化过,不会分配新的设备ID,设备目录中的设备记录会更新。
③Bootstrap服务会将所需信息发送个客户端,让它可以连接到LwM2M服务器。这些信息包括:LwM2M证书、设备ID、服务器的URI。
④当设备引导成功,会开始进入注册流程。
- 引导过后,设备在设备目录中已经有了一个设备记录,并且可以通过设备ID去管理设备。但这个设备还是没有注册到设备管理,暂时还不可以进行Connect和Update操作。
- 注册流程:注册流程将设备连接到LwM2M服务,设备将有权限使用所有设备管理的服务。
- 两种进入注册流程的方式(上面也提到过):
①通过bootstrap获得LwM2M证书的。设备ID用于区分设备,如果有两个设备有相同的ID,新注册的会覆盖旧的。
②直接用LwM2M的。终端名称用于区分设备,如果有两个设备名称相同的设备,新注册的会覆盖旧的。 - 在注册过程中,设备管理客户端和设备管理服务器之间发生的事情:
①设备通过LwM2M 证书注册到LwM2M服务器,并提供其资源结构。
a. setup() API 建立注册设备和LwM2M服务器之间的连接。
b. 注册过程会协商好本次注册设备会话的生命周期,它的初始配置在客户端。
c. Device Management Connect 实现CoAP 资源目录,用于存储设备资源结构。
d. 如果设备已经存在于设备目录,会直接更新条目。否则,新建设备记录和分配设备ID。
②LwM2M 服务器通过Event通知通道来通知 应用程序服务器 已注册的设备。
a. LwM2M 提供设备名称(oep)和设备ID(ep)给应用程序服务器。
b. 应用程序服务器 必须用 设备ID 才能管理设备。(通过REST API)
c. 该通知也包括设备的资源结构。
③设备通过向服务器发送“注册更新(包含生命周期)”来自动维持更新。注册更新也包括资源结构的细节(因为设备上的应用可能改变资源结构)。
④LwM2M服务器通知应用程序服务器发生更新:register_update()。
- 连接到设备管理需要的两组证书:
①身份证书和私钥。
②清单验证证书。 - 客户端要向设备管理服务器提供必要的信息,并发出一个setup命令:
①设备证书。
②设备管理客户端将配置参数定义在MbedCloudClientConfig.h 文件中。应用需要设置或者重写这些参数,放在一个叫mbed_cloud_client_user_config.h 的文件中。此文件在编译过程中要传递给设备管理客户端的API。会用此文件去配置好客户端、并且进行注册。
该文件中至少应该定义以下的参数(其他参数也可以定义或者修改,参考MbedCloudClientConfig.h的文档):#define MBED_CLOUD_CLIENT_SUPPORT_CLOUD #define MBED_CLOUD_CLIENT_ENDPOINT_TYPE "default" #define MBED_CLOUD_CLIENT_LIFETIME 3600 #define MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP
- Mbed Client支持三种传输模式:TCP,UDP或UDP_QUEUE。对于期望通过互联网保持与服务器的持续连接的设备,建议使用TCP。在本地局域网或通过VPN,UDP可能是更理想的选择。对于节能终端, 带队列的UDP是推荐模式。
- 对于节能设备,生命周期不应低于一小时。对于不必主动管理的设备,建议使用多个小时甚至几天的生命周期。
- 对所有希望通过设备管理来监控的资源进行注册。为此,要创建Resource Object,并把它们添加到设备管理客户端用于注册。
- 例如,要注册基于OMA LwM2M的设备对象,请创建对象,并设置必需资源的值:
#include "mbed-client/m2mdevice.h" M2MDevice* device = M2MInterfaceFactory::create_device(); if(device) { device->create_resource(M2MDevice::Manufacturer, MANUFACTURER); device->create_resource(M2MDevice::DeviceType, TYPE); device->create_resource(M2MDevice::ModelNumber, MODEL_NUMBER); device->create_resource(M2MDevice::SerialNumber, SERIAL_NUMBER); }
- 调用API将您的资源添加到注册列表中:
MbedCloudClient::add_objects(const M2MObjectList& object_list); - 设置回调函数,用以获取注册状态、注销状态、错误的信息:
注册状态:MbedCloudClient::on_registered(void(*fn)(void));
注销状态:MbedCloudClient::on_unregistered(void(*fn)(void));
错误状态:MbedCloudClient::on_error(void(*fn)(int));
您可以在 MbedCloudClient::Error 枚举中看到映射的错误代码。 - 调用setup API以设置设备ID(如果尚未存在),并将设备和资源注册到设备管理服务器:
MbedCloudClient::setup(); - 如果注册操作成功,并且客户端可以将所有资源注册到Device Management Connect,则应用程序将通过已注册的回调接收结果:
MbedCloudClient::on_registered(void(*fn)(void));
- 设备注册到LwM2M服务器时,它会通过MBED_CLOUD_CLIENT_LIFETIME定义一个生命周期(单位为s),该注册在生命周期内有效。服务器端最大注册时间为72小时。
- 客户端会根据生命周期自动更新注册,但如果要从应用程序中明确续订注册,则可以使用此API:
MbedCloudClient::register_update()
如果设备在生命周期内没有发送注册更新,服务器会自动将设备注销。 - 调用register_update()是一项非常消耗资源的操作,并不适合于低功耗设备。如果用的是TCP连接设备,最好是使用TCP的keepalive选项。
- 有一个注册速率限制,所以不要经常循环调用register_update。在10秒内注册10次以上的客户将被列入黑名单(所有传入流量被阻止)60秒。
- 除了上面提到的服务器自动注销设备,客户端可以通过调用MbedCloudClient::close(); 来注销设备。
- 设备初始化的时候,会连接到一个账户,会用以下一种方式:
①在设备制造阶段将设备预分配到一个账户。在设备出厂设置Bootstrap configuration时,包括一个账户ID在里面。这种方式适用于你自己制造设备时就知道设备应该连接到哪一个账户。
②设备会被提供一个注册ID,用于在初始化时连接到任一账户。 - CA:Certificate authorities
三、 Optimization
- IoT设备使用LwM2M服务时,有两种模式:
①Normal:设备主动监听来自服务器的传入包。当服务器Web应用收到请求时,可以立即推送到设备。
②Queue:服务器将所有来自Web应用的请求放入队列,它仅当设备进行registration update的时候才会将这些请求推送到设备。仅UDP支持队列模式。 - 出于功耗原因,多数IoT设备在多数时候都是非活动状态,因此它们需要工作在queue模式。通过设置LwM2M的binding mode为Q。
- Queue模式情况下:
①每台设备限制100条消息。
②对于消息的存储时间没有限制,它们会一直存在队列中直到:
a. 设备发送注册更新消息。这时候服务器会传输消息,并从队列中删除已传输的消息。
b. 如果服务端的设备生命时间到期(仍未收到注册更新),服务器会删除所有关于该设备的存储信息,包括队列中的消息。
c. 如果设备发送一个完整的注册信息,服务器也会清空队列中的消息。
- 默认情况下,CoAP协议不允许服务器和设备之间同时进行多个事物。如果有事务正在进行中,则任何请求都会得到响应429 Too Many Requests,直到第一个事务完成。
使用设备端队列模式时,服务器通过向队列添加请求来解决问题(如上所述)。但对于非队列模式设备,要通过应用程序拥塞交付控制。它为非队列模式设备提供一个新的队列:如果设备忙于一个请求,则服务器会存储其他请求,直到设备可以自由接收它们。
该队列一次最多可存储20个请求。在以下情况下,服务器向Web应用程序发送错误消息:
队列已满:429 Too many requests。
设备使用寿命到期:429 Queue was cleared。 - 可以通过资源缓存,在一定时间内存储一些资源值在LwM2M服务器中。当下次有其他应用请求时,可以直接使用。
- 缓存的生命周期可以设置,通过在客户端资源层面设置max-age参数(以秒为单位)。
- 尽可能避免在应用程序中使用动态内存。特别是,您不需要更改的任何资源都应设置为static。
- 尽可能使用资源缓存和队列模式。降低设备功耗。
四、 Collecting data from devices
- 资源(Resources)就是设备上的 传感器 或 执行器(actuators)。也就是说设备资源管理,主要就是读诸如温度值或者控制一个门锁。
- Device Management Connect依赖于LwM2M 设备处理逻辑。LwM2M有一个用Objects 和 Resources分层的数据结构。
- 资源结构:
①Object:一个Object会收集设备上的Resources,可以理解为是一个关联诸如温度传感器的接口。
②Object Instance:一个Object可以拥有多个Instance。
③Resource:来自设备的任何信息都是资源,它具有静态值(永不改变的值)或动态值(在设备操作期间更改的值)。您可以阅读,写入或执行资源信息。资源也可以是具有多个值的数组。
- 示例数据结构
这是一个遵循OMA的定义的示例数据结构。
该设备有两个不同的对象,温度传感器和湿度传感器。
温度传感器Object有五种不同的资源。您可以读取其值,重置其最小值/最大值并更改单位值。
该设备有三个温度传感器实例。 - 有三种类型的对象(Objects):设备Object、安全Object、自定义Object。
- 使用M2MObject 类可以创建和配置所有类型的对象。
- 创建一个设备对象:
static M2MDevice* create_device(); - 创建一个安全对象:
static M2MSecurity* create_security(M2MSecurity::ServerType server_type); - 创建一个自定义对象,你需要传递一个对象的名称:
static M2MObject* create_object(const String &name); - 删除一个设备对象:
M2MDevice::delete_instance(); - 每一个设备或安全对象都只能有一个绑定的实例。所以创建对象会自动创建一个实例。
- 通过M2MObjectInstance 来创建一个自定义对象的实例。自定义对象实例需要ID,当我们创建一个对象实例的时候,我们需要把ID作为参数传递。
- 通过设置一个对象实例的操作模式,决定Device Management Connect 可以处理哪些操作(GET、PUT、POST、DELETE):
①对于一个对象:virtual void set_operation(M2MBase::Operation operation); _object->set_operation(M2MBase::GET_PUT_POST_ALLOWED);
②对于一个对象实例:
virtual void set_operation(M2MBase::Operation operation); object_instance->set_operation(M2MBase::GET_PUT_DELETE_ALLOWED);
- 默认情况下,对象和对象实例不可观察。您可以将它们设置为可观察,或将它们更改为不可观察。
- 相对应的,也有三种资源:设备对象资源、安全对象资源、自定义对象资源。
- 资源和资源实例可以是静态的也可以是动态的:
静态(static):资源或者资源实例的值是不会随时间改变的,它们是不可观测的。
动态(dynamic):资源或资源实例的值可以改变,可以通过API获取值,它们是可观测的。 - 创建设备对象资源,可以根据类型创建资源:
①资源是字符串值的:
M2MResource* create_resource(DeviceResource resource, const String &value);
②资源是整型值的:
M2MResource* create_resource(DeviceResource resource, uint32_t value);
③资源有多个实例的:
M2MResourceInstance* create_resource_instance(DeviceResource resource, uint32_t value, uint16_t instance_id); - 创建安全对象资源,创建M2MSecurity对象会自动创建大部分必需资源。您可以根据其数据类型设置其值。
①自动创建(强制)的资源:SecurityMode、ShortServerID、M2MServerUri、BootstrapServer、PublicKey、ServerPublicKey、Secretkey。
②可选资源:SMSSecurityMode、M2MServerSMSNumber、ClientHoldOffTime。 - 对于自定义对象,您可以创建两种类型的资源:
①M2MResource:例如,具有单个实例的资源/3303/0/5700。
②M2MResourceInstance:具有多个实例的资源,例如/3303/0/5700/0和/3303/0/5700/1。
- 要使用静态值(/3303/0/5700)创建单实例资源:
#include "mbed-client/m2mobject.h"
#include "mbed-client/m2mobjectinstance.h"
#include "mbed-client/m2mresource.h"
_object = M2MInterfaceFactory::create_object("3303");
if(_object) {
M2MObjectInstance* inst = _object->create_object_instance();
if(inst) {
inst->create_static_resource("5700",
"ResourceTest",
STATIC_VALUE,
sizeof(STATIC_VALUE)-1);
- 要创建具有动态值的可观察的单实例资源,您可以稍后设置(/3303/0/5700):
#include "mbed-client/m2mobject.h"
#include "mbed-client/m2mobjectinstance.h"
#include "mbed-client/m2mresource.h"
_object = M2MInterfaceFactory::create_object("3303");
if(_object) {
M2MObjectInstance* inst = _object->create_object_instance();
if(inst) {
M2MResource* res = inst->create_dynamic_resource("5700", "ResourceTest", true);
char buffer[20];
int size = sprintf(buffer, "%d", _value);
res->set_operation(M2MBase::GET_PUT_ALLOWED);
res->set_value((const uint8_t*)buffer,
(const uint32_t)size);
五、Provisioning development devices
- 开发过程中,不必每次都要经过完整的工厂流程。设备管理提供一个开发人员模式,用于加速开发进程。该模式依赖于可以添加到软件二进制文件的开发人员证书。开发人员证书允许您的测试设备连接到您的设备管理帐户。
- 创建和下载开发人员证书、将开发人员证书添加到您的应用程序 的步骤可见:该连接