prcxicloud iot device sdk
npm install prcxi-iot-device-sdk> 中析 IoT 官方版本
PrcxiIoT Device SDK 提供设备接入中析 IoT 物联网平台(LinkPlatform)的 JavaScript 版本的 sdk,可以运行在 node,broswer,微信小程序,支付宝小程序环境,封装 LinkPlatform 物联网平台的设备端能力,如设备连接云平台,数据 pub,sub 的上下行通讯。还有许多高级功能,如影子设备,远程配置,基于设备物模型(属性、服务、事件)的开发模式,网关和子设备的能力等,基于 SDK 的设备端开发或设备应用开发,可以极大简化开发门槛。
- 中析物联网平台 js 版本官方 sdk
- 支持 node、broswer、微信小程序、支付宝小程序环境运行
- 体积小,压缩版本仅有 418k
- 已为数十万设备或小程序提供链接服务
> 安装 Node.js 运行环境,版本 >=4.0.0 。
通过 npm 包管理工具安装:
``bash`
npm install prcxi-iot-device-sdk --save
当前稳定版本 1.0.0
当前最新版本 1.0.0
支付宝小程序使用注意:
支付宝最新版本容器升级后导致支付宝小程序无法使用 'prcxi-iot-device-sdk.js' ,请使用支付宝定制版本 'prcxi-iot-device-sdk-1.2.8-alimin-compatible.js',请在 dist 目录下下载
`javascript
// node引入包名
const iot = require("prcxi-iot-device-sdk");
// 浏览器、微信小程序,支付宝小程序引入./dist编译的js文件
// const iot = require('./dist/prcxi-iot-device-sdk.js');
// 特别注意:支付宝最新版本容器升级后导致支付宝小程序无法使用 'prcxi-iot-device-sdk.js' ,请使用支付宝定制版本 'prcxi-iot-device-sdk-1.2.8-alimin-compatible.js',请在dist目录下下载
// js版本下载地址:
// https://github.com/aliyun/prcxi-iot-device-sdk/tree/master/dist 或
// prcxi-iot-device-sdk.js 下载地址 https://unpkg.com/prcxi-iot-device-sdk@1.2.4/dist/prcxi-iot-device-sdk.js 或
// prcxi-iot-device-sdk.min.js 下载地址 https://unpkg.com/prcxi-iot-device-sdk@1.2.4/dist/prcxi-iot-device-sdk.min.js
//
const device = iot.device({
productKey: "
deviceName: "
deviceSecret: "
// 支付宝小程序和微信小程序额外需要配置协议参数
// "protocol": 'alis://', "protocol": 'wxs://',
});
device.subscribe("/
device.on("connect", () => {
console.log("connect successfully!");
device.publish("/
});
device.on("message", (topic, payload) => {
console.log(topic, payload.toString());
});
`
LinkPlatform 封装了物模型定义与 Alink 异步协议,SDK 封装使得设备与云端通信时不需要关心 MQTT topic,只需要调用属性上报(iot.device#postProps())、服务监听(iot.device#onService())、事件上报(iot.device#postEvent())等相关 API。
`javascriptpostProps:
device.on("connect", () => {
device.postProps(
{
LightSwitch: 0,
},
(res) => {
console.log(, res);`
}
);
});
调用 device.postProps() 等同于执行以下代码:
`javascript
// 发布属性上报 topic
device.publish('/sys/
{
id: msgId,
version: '1.0',
params: {
'LightSwitch': 25,
},
method: 'thing.event.property.post'
}
}));
// 监听属性上报响应 topic
device.subscribe('/sys/
device.on('message', function(topic, message){
const res = message.toString();
if (res.id === msgId) {
// 在这里处理服务端响应
console.log(res.data);
}
});
`
`javascript`
// 监听云端设置属性wakeup_async服务消息
device.onService("wakeup_async", function (res, reply) {
// 处理服务参数
console.log("wakeup_async", res);
// 返回云端异步服务处理消息
reply({
code: 200,
data: { out: 1 },
});
});
其他更多功能,请查 api 列表,值得注意的是,更多示例,见源码 example 文件夹
- device 继承自 mqtt.js 的 EventEmitter,可以使用其全部方法
- gateway 可以使用 device 的全部 api
- subDevice 也可以使用 device 的全部 api
设备相关
- iot.device()
- iot.device#publish()
- iot.device#subscribe()
- iot.device#unsubscribe()
- iot.device#postProps()
- iot.device#onProps()
- iot.device#postEvent()
- iot.device#onService()
- iot.device#end()
- iot.postTags#postTags()
- iot.deleteTags#deleteTags()
- iot.getConfig#getConfig()
- iot.onConfig#onConfig
- iot.onShadow#onShadow()
- iot.getShadow#getShadow()
- iot.postShadow#postShadow()
- iot.deleteShadow#deleteShadow()
网关相关(网关也可以使用设备相关的 api)
- iot.gateway()
- iot.gateway#addTopo()
- iot.gateway#getTopo()
- iot.gateway#removeTopo()
- iot.gateway#login()
- iot.gateway#logout()
子设备
- 与设备 api 相同,通过网关的 login()方法返回子设备实例
动态注册
- iot(register()
- iot.gateway#regiestSubDevice()
和云端建立连接,返回一个 Device 连接实例,入参:
- optionsproductKey
- (String)deviceName
- (String)deviceSecret
- (String)region
- (String) 中析 region,默认值:cn-shanghaitls
- (Bool) 是否开启 TLS 加密,Node.js 中如果开启将使用 TLS 协议进行连接,浏览器如果开启将上使用 WSS 协议keepalive
- (int) 心跳报文时间间隔,默认值 60 秒clean
- (bool) cleansession,是否清除连接 session 设置,默认值 false
`js`
const device = iot.device({
productKey: "
deviceName: "
deviceSecret: "
});
function(connack) {}
当连接到云端成功时触发。
`javascript
const iot = require("prcxi-iot-device-sdk");
const device = iot.device({
productKey: "
deviceName: "
deviceSecret: "
});
device.on("connect", () => {
console.log("connected!");
});
`
function(topic, message) {}
当接受到云端消息时触发,回调函数参数:
- topic 消息主题message
- 消息 payload
`js`
device.on("message", (res) => {
console.log("msg:", res);
});
注意:由于 nodejs 的 event 机制,如果未监听 error 事件,当出现错误时会 throw 一个 error,未 try catch 会导致程序终止,建议 error 事件需要监听
node 对于这个 error 处理的解释:
When an error occurs within an EventEmitter instance, the typical action is for an 'error' event to be emitted. These are treated as special cases within Node.js. If an EventEmitter does not have at least one listener registered for the 'error' event, and an 'error' event is emitted, the error is thrown, a stack trace is printed, and the Node.js process exits. 原文地址:https://nodejs.org/api/events.html
`js`
device.on("error", (err) => {
console.log("error:", err);
});
当连接出错触发
- topic :topic 值 String 类型message
- 需要发送的消息, 数据格式为Buffer or String 类型options
- qos
- qos 级别 number 类型 ,默认值 0retain
- dup
- callback
-
`js`
device.publish("/
device.publish("/
qos: 1, // default 0
});
订阅消息,等同于 mqtt.Client#subscribe() 方法。
取消订阅消息等同于 mqtt.Client#unsubscribe() 方法。
上报物模型属性:
- params 属性参数,Object 类型callback
- res
- 服务端 reply 消息内容
`js`
// 上报设备属性
device.postProps(
{
LightSwitch: 0,
},
(res) => {
console.log(res);
}
);
上报物模型属性:
- refunscb
- 回调函数
`js`
device.onProps((res) => {
console.log(">>>onProps", res);
});
上报物模型事件:
- eventName 事件名称 String 类型params
- 事件参数,Object 类型callback
- err
- 错误,比如超时res
- 服务端 reply 消息内容
`jspostEvent:${res}
// 上报设备事件
device.postEvent(
"lowpower",
{
power: 10,
},
(res) => {
console.log();`
}
);
监听物模型服务:
- seviceName 服务名称,String 类型callback
- res
- 服务端返回参数reply
- 响应服务的函数,可以使用同步可以异步方式响应
relpy(params,[async or sync])
- params 响应返回的数据id
- 返回服务端的消息 id,可以不填会自动生成code
- 响应服务端的 code,200 为成功data
- 响应服务端的数据type
- 响应服务的类型,根据选择物模型服务的类型,同步或异步,选填 'async' or 'sync'
`javascript
// 假设物模型中有 wakeup_async的异步服务和wakeup_sync的同步服务,输出值都为out
// 异步方式回复
device.onService("wakeup_async", function (res, reply) {
// 处理服务参数
console.log("^onService", res);
reply({
code: 200,
data: { out: 1 },
});
});
// 同步方式回复
device.onService("wakeup_sync", function (res, reply) {
// 处理服务参数
console.log("^onService", res);
reply(
{
code: 200,
data: { out: 1 },
},
"sync"
);
});
`
设备或网关断开连接,等同于 mqtt.Client#end() 方法。
上报设备标签:
- params 属性对象数组,array 类型,内容格式示例 [ {attrKey:'xxx',attrValue:'xxx'},{}...]attrKey
- 错误,比如超时或者 res.code !== 200attrValue
- 服务端 reply 消息内容callback
- res
- 服务端 reply 消息内容
* 每次重新上报设备标签相同 key 会覆盖内容,不同 key 会增加标签
* params 示例:
`jsadd tag ok res:${res.id}
const tags = [
{
attrKey: "Temperature",
attrValue: "36.8",
},
];
device.postTags(tags, (res) => {
console.log();`
done();
});
删除设备标签:
- tags 属性参数,array 类型,内容格式 [ 'string','string',....]string
- 内外为 tag 的标签名称
* 示例:
`javascript`
device.deleteTags(["tagA", "tagB"]);
获取设备远程配置:
- callback 回调函数
- res:当前设备的远程配置
* 示例:
`javascript`
device.getConfig((res) => {
console.log("getConfig:", res);
});
订阅设备远程配置,当云端修改远程配置时,设备端会收到消息:
- callback 回调函数
- res:当前设备的远程配置
* 示例:
`javascript`
device.onConfig((res) => {
console.log("onConfig,res:", res);
});
订阅设备影子回调函数方法:
- callback 回调函数
- res 当影子设备变化或获取影子设备消息,上报影子消息时回调
* 示例:
`javascript`
device.onShadow((res) => {
console.log("获取最新设备影子,%o", res);
});
获取设备影子最新:
- 示例:
`javascript`
// 设备主动获取影子,回调函数会触发onShadow方法,返回设备影子信息
device.getShadow();
上报设备影子数据
- params 上报影子设备的实际值
* 示例:
`javascript`
// 上报成功或错误都会触发onShadow方法,返回设备影子信息
device.postShadow({
a: "avalue",
});
删除影子设备的属性值
- keys 需要删除设备影子的属性的 key 数组
- 除了数组外,如果传入单个 key,可以删除单个属性,传入空会删除全部属性
* 示例:
`javascript`
// 删除单个影子设备属性
device.deleteShadow("a");
// 删除多个影子设备属性
device.deleteShadow(["a", "b"]);
// 删除所有影子设备属性
device.deleteShadow();
和云端建立连接,返回一个网关 Gateway 类连接实例,继承自 Device 类。网关可以使用设备的所有方法
- optionsproductKey
- (String)deviceName
- (String)deviceSecret
- (String)region
- (String) 中析 region,默认值:cn-shanghaitls
- (Bool) 是否开启 TLS 加密,Node.js 中如果开启将使用 TLS 协议进行连接,浏览器如果开启将上使用 WSS 协议keepalive
- (int) 心跳报文时间间隔,默认值 60 秒clean
- (bool) cleansession,是否清除连接 session 设置,默认值 false
`js`
const device = iot.gateway({
productKey: "
deviceName: "
deviceSecret: "
});
添加子设备到拓扑
- params 子设备三元组数组,[{productKey,deviceName,deviceSecret},{productKey,deviceName,deviceSecret},]callback
- res
- 服务端 reply 消息内容
`js`
gateway.addTopo([sub_device1, sub_device2], (res) => {
console.log(">>>>>getTopo", res.message, res.data);
});
添加子设备到拓扑关系
- callbackres
- 服务端 reply 消息内容
`js`
gateway.getTopo((res) => {
console.log(res);
});
从拓扑关系里移除子设备
- params 移除设备参数的数组,示例:[{"productKey": "xx","deviceName": "xx"},{"productKey": "xx","deviceName": "xx"},....]productKey
- deviceName
- callback
- res
- 服务端 reply 消息内容
`js`
gateway.removeTopo(
[
{ productKey: "xx", deviceName: "xx" },
{ productKey: "xx", deviceName: "xx" },
],
(res) => {
console.log(">>>>>getTopo");
console.log(res.message);
console.log(res.data);
}
);
子设备上线
- params 登录的设备信息示例:{"productKey": "xx","deviceName": "xx",}productKey
- (String)deviceName
- (String)deviceSecret
- (String)callback
- res
- 服务端 reply 消息内容返回值
- 返回一个子设备,子设备可以使用设备的 api,做相关的操作
`js`
gateway.on("connect", () => {
//子设备登录ok
sub1 = gateway.login(
{ productKey: "xx", deviceName: "xx", deviceSecret: "xxx" },
(res) => {
console.log(">>>>>login", res);
}
);
// 子设备连接状态
sub1.on("connect", () => {
console.log(">>>>sub connected!");
// do something
sub1.postProps(
{
LightSwitch: 0,
},
(res) => {
console.log(">>>>sub postProps!");
console.log(res);
}
);
});
});
子设备下线
- params 子设备身份productKey
- (String)deviceName
- (String)callback
- res
- 服务端 reply 消息内容
`js`
gateway.logout(
{"productKey": "xxxxx","deviceName": "xxxxx"},
(res) => {
console.log('>>>>>logout', res);
}
直连设备动态注册(小程序环境不支持此方法)
- params 子设备身份 object 实例 productKey:"a15YDgQGhU0",productKey
- productSecret
- deviceName
- callback
- res
- 服务端 reply 消息内容,包含设备三元组
`js`
const params = {
productKey: "xxxxxx",
productSecret: "xxxxxx",
deviceName: "xxxxxx",
};
iot.register(params, (res) => {
console.log("register:", res);
if (res.code == "200") {
// 注册成功请保存设备三元组,只会返回一次
}
});
通过网关注册子设备(小程序环境不支持此方法)
- params 子设备身份信息,可以是单个{productKey,deviceName}或者是一组[{productKey,deviceName},{productKey2,deviceName2}]进行批量注册productKey
- deviceName
- callback
- res
- 服务端 reply 消息内容
`js`
const gateway = iot.gateway({
productKey: "
deviceName: "
deviceSecret: "
});
gateway.on("connect", () => {
gateway.regiestSubDevice(
[{ deviceName: "xxx", productKey: "xxx" }],
(res) => {
if (res.code == "200") {
// 注册成功请保存设备三元组,只会返回一次
}
}
);
});
- id 发送请求的消息 id,sdk 中会自动生成message
- 返回的消息data
- 返回的数据code
- 服务端返回消息的状态码,常见 code 如下200
- 成功400
- 内部服务错误, 处理时发生内部错误429
- 请求过于频繁,设备端处理不过来时可以使用460
- 请求参数错误520
- 子设备会话不存在
> 注意: example 中的 iot 引用,const iot = require('../lib');,如果在 github 工程以外使用,需要换成 const iot = require('prcxi-iot-device-sdk');
example 见 github 开源工程中 example 目录 https://github.com/aliyun/prcxi-iot-device-sdk
- broswer 浏览器中使用 demo 路径 /example/broswer/index.html
- quickstart 快速开始 demo 路径 /example/quickstart
- props 物模型-属性 demo 路径 /example/props.js
- event 物模型-事件 demo 路径 /example/event.js
- service_async 物模型-异步服务 demo 路径 /example/service_async.js
- service_sync 物模型-同步服务 demo 路径 /example/service_sync.js
- origin 基础 mqtt pub,sub 使用 路径 /example/origin.js
- remote_confit_get 远程配置-主动获取 路径 /example/remote_confit_get.js
- remote_confit_sub 远程配置-订阅获取 路径 /example/remote_confit_sub.js
- tag 设备标签获取 路径 /example/tag.js
- shadow 设备影子 路径 /example/shadow.js
- one_model_one_secret 一型一密使用 demo 路径 /example/one_model_one_secret.js
- forward 通过规则引擎转发后订阅数据的示例
#### 1.2.8
- 使用 crypto-js 替代原生的 crypto 做设备签名加密功能,浏览器和微信支付宝小程序的编译大小,min 压缩版从 661k 减少到 418k,体积减少 37%
#### 1.2.7
- 增加 onProps 方法,用于监听云端对物模型属性设置的监听
- 解决 postEvent 和 postProps 回调中内容不正确的问题
#### 1.2.5
- 修复网关使用 mqtt pub 和 sub 时字符转译报错的警告
#### 1.2.4 稳定版本
- 包名的修改,从 aliyun-iot-device-sdk 正式改名为 prcxi-iot-device-sdk
- 增加对微信小程序,支付宝小程序的支持,浏览器的支持 教程连接 ./docs
- 增加 onService 中 reply 函数,并支持同步和异步调用
`javascript
// 假设物模型中有 wakeup_async的异步服务和wakeup_sync的同步服务,输出值都为out
// 异步方式回复
device.onService("wakeup_async", function (res, reply) {
// 处理服务参数
console.log("^onService", res);
reply({
code: 200,
data: { out: 1 },
});
});
// 同步方式回复
device.onService("wakeup_sync", function (res, reply) {
// 处理服务参数
console.log("^onService", res);
reply(
{
code: 200,
data: { out: 1 },
},
"sync"
);
});
`
- 增加 onConfig 方法用于订阅云端远程配置更新
- 增加部分功能的 example
- 重写了网关子设备 subdevice 的实现
#### 1.0.1 版本更新
- 对核心代码进行了重构
- 增加设备标签上报功能
- 增加删除标签功能
- 增加了设备动态注册功能
- 增加设备影子相关功能
- 增加获取设备配置功能
- [非兼容性升级]网关设备之前的删除 topo 方法名和文档不一致,去掉了 deleteTopo 方法,统一使用 removeTopo
- [非兼容性升级]网关类方法,入参需要 signUtil 的逻辑去除,直接传入设备信息
- [非兼容性升级]去掉 signUtil 方法导出
- [非兼容性升级]初始化 device 和 gateway 时候签名方法参数从 signAlgorithm 改为 signmethod
- [非兼容性升级]设备的 serve 方法改成 onService
- [非兼容性升级]修改返回函数的 res 格式,取消 err 作为第一个参数,code,mssage 都会放在 res 里面
- [非兼容性升级]去掉网关设备的方法 postSubDeviceProps,postSubDeviceEvent,serveSubDeviceService,改成使用子设备调用
`
// iot.gateway#postSubDeviceProps()
// iot.gateway#postSubDeviceEvent()
// iot.gateway#serveSubDeviceService()
const sub = gateway.login(
sub_device1,
(res)=>{console.log('>>>>>login',res);}
);
sub.on('connect', () => {
console.log(">>>>sub connected!");
sub.postProps({
LightSwitch: 0
},(res)=>{
console.log(">>>>sub postProps!");
console.log(res);
});
});
setTimeout(()=>{
gateway.logout(
sub_device1,
(res)=>{console.log('>>>>>logout',res);}
);
},5000)
`
#### 0.3.1 版本更新
- productKey,deviceName,deviceSecret 大小写经常容易忽略,新版本支持忽略大小写,也可以连接上
#### 0.3.0 版本更新
1:初始化连接 option 选择增加支持 keepalive 和 clean(cleansession)配置
2:修改 regionId 为 region,并兼容之前的 regionId 参数
#### 研发中常见的问题
1:onMessage 多次回调,示例如下
`js
// 错误示例
const device = iot.device({...,...});
device.on('connect', (res) => {
device.on('message',(topic,payload) => {
// you biz logic at here
});
});
// 错误原因 device.on('message')委托放在 device.on('connecnt')中会导致多次绑定,产生message中的函数多次重复触发
// 正确示例
const device = iot.device({...,...});
device.on('connect', (res) => {
});
device.on('message',(topic,payload) => {
// you biz logic at here
});
``