1 前面的话
在onenet的 onenet studio 服务001里面我们已经讲过了使用postman调用onenet官方的API。
但是请求的URL是有问题的,并不是官方给的一个标准的请求方式。
这里我们一获得设备的详细信息为例子,
2 获取设备最新信息API(瞎猫版)
2.1 在onenet平台里面调试API
进到品台的运维监控—API调试——应用开发类,就会发现里面有连个接口,一个是获取设备属性,一个是设备属性最新数据查询。 前者需要设备在线,后者设备属性最新数
据查询,这个不需要设备在线,可以获得设备里面的最后一条数据,但是这个数据包含设备里面所有的数据流。
我们这里就以设备属性最先数据查询。为例,因为这个API不需要设备在线。
品台里面调试开始,配置好设备的,产品名,产品id,设备名,之后我们点击执行,可以看到已经得到了服务器返回来的设备数据了。
我们看看平台发送的http请求的数据,这个是一个get方式的请求,我们可以打开postman,将url和请求头,以及鉴权信息写进去,应该也可以得到设备的数据。
{
"url": "https://open.iot.10086.cn/studio/debug/api/application?version=1&action=QueryDeviceProperty&project_id=ZIVS7i&product_id=FkWRPqXmGF&device_name=CWBW_02",
"method": "get",
"header": {
"Accept": "application/json, text/plain, */*",
"authorization": "version=2020-05-29&res=userid%2F274573&et=1682055413&method=sha1&sign=LA7NJFNiZBBwsJvQtkWLgdoHwhU%3D"
},
"query": {
"version": 1,
"action": "QueryDeviceProperty",
"project_id": "ZIVS7i",
"product_id": "FkWRPqXmGF",
"device_name": "CWBW_02"
}
}
2.2 postman调用平台API
我们可以看到借助平台里面的API调试,我们确实可以得到 平台的设备数据
但是但是但是,这种方式完全就是瞎猫碰到死耗子。
3 获取设备最新数据API(文档版)
在2里面我们确实可以借助平台调试,然后赋值平台调试的时候的请求参数 ,得到设备的最新数据,但是上面的方式就是瞎猫碰到死耗子
这里我们根据onenet平台提供的API文档来看看标准的请求方式是怎么实现的。
这里我们用的onenet的服务是 onenet studio服务,我们就去查看onenet studio的开发文档,文档地址
https://open.iot.10086.cn/doc/v5/develop/detail/634
进到文档里面
- 应用开发 — 应用API ——使用说明 先看一下API的使用规则
可以看到 里面有一个 namespace字段和action字段是需要我们自己根据调用的方法自己写的。我们使用的是应用开发类里面的 设备最新数据获取,所以namespace这个字段就写 application
https://openapi.heclouds.com/application?action=xxxx&version=1
- 然后我们进到 应用开发 — 应用开发类 —- 应用API。
可以看到设备最新数据查询这个方法,的接口名是 QueryDeviceProperty ,请求方法是get那么这个链接
https://openapi.heclouds.com/application?action=xxxx&version=1
可以变为
https://openapi.heclouds.com/application?action=QueryDeviceProperty&version=1
但是这个时候可以看到 设备属性最新数据要求了几个参数,project_id(项目id),product_id(产品id),device_name(设备名)
这三个参数,我们要在url里面穿入这三个参数,所以右边为了
https://openapi.heclouds.com/application?action=QueryDeviceProperty&version=1&project_id=ZIVS7i&product_id=FkWRPqXmGF&device_name=CWBW_02
这样请求的url就好了。
- 然后我们吧这个链接放到postman里面进行调试,看到他报错说我们鉴权失败了
下面我们就开始解决鉴权失败的问题
- 通过查看文档 应用开发——应用API—-安全鉴权
找一下四个参数:
——————————————————————————————-
version = 2020-05-29
res = userid/274573
et = 1653116504 时间按不需要我们自己转换了,java代码里面会将我们当前时间往后40天
method = sha1
accessKey=
HUsjVYRsu6qnGyd+FUGVPM9QDTZ/n+5sttdpSA+IcYU3QNtaxKdS96XY97sWjSlNdcIZFUHuSL9+DGvdQif5rA==
————————————————————————————————————-
然后呢他们有给了一个java生成签名结果的字符串,
java方法,我们使用这方法,放到idea里面,设置上面的5个 参数,就可以使用 签名结果了
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class productSING {
public static String assembleToken(String version, String resourceName, String expirationTime, String signatureMethod, String accessKey)
throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
StringBuilder sb = new StringBuilder();
String res = URLEncoder.encode(resourceName, "UTF-8");
String sig = URLEncoder.encode(generatorSignature(version, resourceName, expirationTime, accessKey, signatureMethod), "UTF-8");
sb.append("version=")
.append(version)
.append("&res=")
.append(res)
.append("&et=")
.append(expirationTime)
.append("&method=")
.append(signatureMethod)
.append("&sign=")
.append(sig);
return sb.toString();
}
public static String generatorSignature(String version, String resourceName, String expirationTime, String accessKey, String signatureMethod)
throws NoSuchAlgorithmException, InvalidKeyException {
String encryptText = expirationTime + "\n" + signatureMethod + "\n" + resourceName + "\n" + version;
String signature;
byte[] bytes = HmacEncrypt(encryptText, accessKey, signatureMethod);
signature = Base64.getEncoder().encodeToString(bytes);
return signature;
}
public static byte[] HmacEncrypt(String data, String key, String signatureMethod)
throws NoSuchAlgorithmException, InvalidKeyException {
//根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
SecretKeySpec signinKey = null;
signinKey = new SecretKeySpec(Base64.getDecoder().decode(key),
"Hmac" + signatureMethod.toUpperCase());
//生成一个指定 Mac 算法 的 Mac 对象
Mac mac = null;
mac = Mac.getInstance("Hmac" + signatureMethod.toUpperCase());
//用给定密钥初始化 Mac 对象
mac.init(signinKey);
//完成 Mac 操作
return mac.doFinal(data.getBytes());
}
public enum SignatureMethod {
SHA1, MD5, SHA256;
}
public static void main(String[] args) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException {
String version = "2020-05-29";
String resourceName = "userid/274573";
String expirationTime = System.currentTimeMillis() / 1000 + 100 * 24 * 60 * 60 + "";
String signatureMethod = SignatureMethod.SHA1.name().toLowerCase();
String accessKey = "HUsjVYRsu6qnGyd+FUGVPM9QDTZ/n+5sttdpSA+IcYU3QNtaxKdS96XY97sWjSlNdcIZFUHuSL9+DGvdQif5rA==";
String token = assembleToken(version, resourceName, expirationTime, signatureMethod, accessKey);
System.out.println("Authorization:" + token);
}
}
可以看到他生成的一个鉴权用的签名字符串。
现在鉴权信息也有了 ,我们回到postman里面,点击Authorization,选择API key
好了到目前位置我们已经可以 使用平台给的 API 使用标准的方法 拿到平台返回来的数据了。
4 设备属性设置(失败)
模拟2.2 里面的方式,通过读取文档 应用开发—-应用开发类——设备属性设置
我们可以在postman里面发送请求
当设备不在线时候报错:设备不在线
当设备在线的时候又报错: 设备没有订阅
5 设备属性上报
4 里面的设备属性设置API我上传数据的时候失败了,我有看到了文档里面有另外一个API
5.1 先看使用API使用说明
从图片里面可以看到 使用说明,发送的是post请求,而且 url, 请求头,请求体里面都需要我们设置一些参数
我们先把这个格式打出来
POST https://${Address}/${url}?${url参数}
Header参数:token,Content-Type
请求体Body:OneJson 其实就是json格式的数据
目前已经这知道
Address是 https://open.iot.10086.cn/studio/http
url是 /device/thing/property/post
修改格式
POST https://open.iot.10086.cn/studio/http/device/thing/property/post?${url参数}
Header参数:token,Content-Type
请求体Body:OneJson 其实就是json格式的数据
url参数里面有连个参数,一个是topic 一个是 Protocol 我们就开始找这连个参数
可以看到 设备属性上报topic是 $sys/{pid}/{device-name}/thing/property/post
我们将自己的pid 产品id ,device-name 设备名填写进去 ,
topic就是 $sys/FkWRPqXmGF/CWBW_02/thing/property/post
Protocol给了三个值,我们这里使用的是MQTT我也不知道为什么要用这个,不然回报错 协议不匹配
修改请求的模板
POST https://open.iot.10086.cn/studio/http/device/thing/property/post?topic=$sys/FkWRPqXmGF/CWBW_02/thing/property/post&protocol=mqtt
Header参数:token,Content-Type
请求体Body:OneJson 其实就是json格式的数据
5.2 设置token和content-type
- url里面的参数我们已经看完了,现在开始设置请求头里面的参数
可以看到请求头里面有两个参数,一个是 token ,一个是 Content-type
我们点进去这个链接里面有生成token的方法,和工具生成token的方法和工具
我们打开工具
et就是unix时间,在线的unix事件转换工具unix时间在线转换工具这个时间一定要是未来的时间,不然就会被拒绝访问。
这里我使用的et是 : 1653116504
打开token生成工具
可以看到我们还缺少key这个参数,我们在看看文档
这个key就是秘钥,产品级,设备级都可以,
说的在具体一点:产品级的key叫产品key,设备级的key叫做设备秘钥 ,这两个值都是可以的,
以我的产品为例
产品key是 :QvgnqE1kZBomEJmZsX6geOrQmZdBJd5DJK5EremSI7Y=
生成的token是:version=2018-10-31&res=products%2FFkWRPqXmGF%2Fdevices%2FCWBW_02&et=1653116504&method=md5&sign=rehMS%2Foqkvo%2FRHzElv%2BzOQ%3D%3D
设备key是:P6oyCh/SOmR8727I6DeDpxMZgn4mnGs6zvx5d6Yt218=
生成的token是:version=2018-10-31&res=products%2FFkWRPqXmGF%2Fdevices%2FCWBW_02&et=1653116504&method=md5&sign=S7MkTpcqNXO47heUFoR%2Fbw%3D%3D
这里我先使用产品key的token
好了这个时候我们来修改请求参数
POST https://open.iot.10086.cn/studio/http/device/thing/property/post?topic=$sys/FkWRPqXmGF/CWBW_02/thing/property/post&protocol=mqtt
Header参数:token=version=2018-10-31&res=products%2FFkWRPqXmGF%2Fdevices%2FCWBW_02&et=1653116504&method=md5&sign=rehMS%2Foqkvo%2FRHzElv%2BzOQ%3D%3D,
Content-Type=application/json
请求体Body:OneJson 其实就是json格式的数据
5.3 请求体的参数
到文档里面—-设备接入与管理——http协议接入—-直连设备设备属性上报
文档里面给了个请求体的数据格式
我们来写一个json格式的请求体数据,想我的设备的Alerm这个数据点里面传递一个1
{
"id": "123",
"version": "1.0",
"params": {
"Alerm": {
"value": 1
}
}
}
5.4 最终的请求数据
[x] Header参数:token=version=2018-10-31&res=products%2FFkWRPqXmGF%2Fdevices%2FCWBW_02&et=1653116504&method=md5&sign=rehMS%2Foqkvo%2FRHzElv%2BzOQ%3D%3D
Content-Type=application/json
[x] 请求体Body:OneJson 其实就是json格式的数据
{
"id": "123",
"version": "1.0",
"params": {
"Alerm": {
"value": 1
}
}
}
5.5 在postman里面设置最终请求数据
注意我们的请求参数是post
- 设置请求url
- 设置请请求头
请求头里面的鉴权信息
设置请求头里面的content-Type
- 设置请求体数据,发送请求
可以看到数据已近发送过去了,我们到设备里面看一下,数据已经过来了