之前做了一个智能安防系统,用STM32单片机作为主控芯片,ESP8266-01s模块作为Wi-Fi模块,成功利用MQTT协议实现了连接阿里云物联网平台或中国移动OneNET平台,并支持实时上报环境温湿度、烟雾、有害气体浓度等信息和远程修改报警阈值、远程开关继电器、LED灯亮度调节、控制步进电机等功能。
后来为了完善功能,在物联网平台的官方文档里看到其开放了很多实用的API,其中有一部分是基于HTTP协议的POST和GET方式与服务器进行数据交换的,笔者突发奇想,利用这些API在iOS端“快捷指令”里执行HTTP请求,然后用Siri执行快捷指令,获取当前温湿度或设置报警阈值、下发命令控制设备等功能。
以下介绍如何实现这些功能,主要讲基于OneNET的快捷指令,至于如何连接阿里云和OneNET物联网平台,相关教程将在后续更新。
目录
摘要
1 准备工作
2 如何向设备发送命令
3 一个控制风扇打开的快捷指令
3.1 创建快捷指令
3.2 修改快捷指令属性
3.3 添加操作
(1)首先添加"URL"块
(2)添加“获取URL内容”操作
3.4 功能测试
3.4.1 服务器返回数据处理
3.4.2 如何用Siri运行这个快捷指令
3.5 改进与调试
4 如何批量添加快捷指令
5 扩展功能
6 附录 多协议接入API列表:
新增数据流
批量查询数据流信息
发送命令
准备一套正常连接OneNET物联网平台“多协议接入”下创建的设备的系统,笔者采用的是基于STM32和ESP8266-01s模块的系统(笔者将在后续文章给出此系统教程);
OneNET物联网平台设备数据流界面
需要提前记下设备ID、数据流名称、API-Key和API。数据流可以用之前添加的,比如“Cur_Temp”表示当前温度值,“LED_Light”表示LED亮度等,也可以后面通过HTTP请求进行添加、删除数据流等;
准备一台能运行iOS快捷指令的iPhone、iPad(如果有Appel Watch,那么你在手机平板编辑好的快捷指令也可以在Watch上使用);
对HTTP请求概念有一些基本的了解,知道JSON格式数据的含义以及如何提取键值等(有需要的话笔者后续会更文);
通过此以下API向设备发送命令,可以修改设备相关数据,比如开/关继电器、调节RGB灯颜色、修改报警阈值、修改期望温度值等:
请求方式:POST URL:http://api.heclouds.com/cmds
URL参数:device_id、qos、timeout
HTTP头部:api-key
请求体:用户自定义内容,json、字符串,数字、也可以是二进制数据(64KB以内)
其中,device_id为接受该命令的设备ID;qos等级可以为0或1,为0代表向设备发送命令后不需要设备应答;1表示向设备发送命令后需要等待设备回应,如果没有应答则会重发该命令;timeout为命令有效时间,在有效时间内命令才会重发,否则命令失效;api-key可以是平台给的MasterKry,也可以是自己添加具有该设备访问权限的api-key; 请求体可以是json格式数据,如:
{"SWITCH":1,"RGB":000000}
或者是一个字符串,如:
I am a Robot.
也可以是二进制数据,比如一张图片、一段录音等,但每条消息大小不能超过64KB;也可以是任意格式的命令,只要单片机端方便编程识别和处理。
打开iPhone或者iPad上的“快捷指令”app,点击右上角“+”新建一个快捷指令(要求iOS版本为iOS 12.4.1及以上,或者iPadOS 12.4.1及以上);
创建快捷指令
在新快捷指令里,可以点击右上方“...”来设置快捷指令名称,我们设置为“打开卧室小风扇”,然后修改图标和颜色和图形为自己喜欢的样式。
修改快捷指令属性
如果你后续有上传二进制文件的需求,可以打开“在共享表单中显示”选项,并在后面步骤里添加获取二进制文件的脚本; 如果你有Apple Watch并希望这个快捷指令能在上面运行,则可以打开“在Apple Watch上显示”;
以“打开卧室小风扇”为例,步骤如下:
输入格式如下:
http://api.heclouds.com/cmds?device_id=********&timeout=100&qos=1
其中,device_id、timeout、qos等URL参数在上面介绍过,这里不再赘述。
添加“URL”块
将“URL”变量设置为上面添加的URL(默认自动添加),其他参数如下:
方法:设置为“POST”;
头部:点击添加新头部,在“键”框内输入“api-key”(不带引号),在“文本”框内输入你的api-key;
请求体:请求体可以设置为JSON、表单和文件,你可以按照自己的STM32安防项目内解析命令的程序来选择相应的类型,笔者此处示范“JSON”类型的填法: 添加新字段,因为本例程是控制风扇开关,只需要true和false表示开关,所以选择“布尔值”,在键“框内输入“Fan”,键值默认为“false”,本处我们要打开风扇,所以点击修改为“true”。
添加“获取URL内容”操作
也可以按照你的设备端程序来添加相应的字段;比如选择“数字”,那么同样的,在“键”框内输入“Fan”(不包括引号),然后在显示“数字”提示的键值框内输入“1”代表开(取决于你设备端程序);
设置完以上步骤之后就可以控制风扇打开了。你也可以在后面添加脚本解析服务器返回的JSON数据,以下为服务器返回数据示例:
{"errno":0,"data":{"cmd_uuid":"cc70d6b0-3644-57c9-9aa6-72b2cffd10b3"},"error":"succ"}
其中,“errno”表示错误代码,此处返回0,表示没有错误;“error”表示错误原因,此处返回“succ”表示成功。
URL返回数据处理
通过解析JSON数据,可以判断返回的错误类型、错误原因,加入“如果”操作即可以根据不同的返回内容显示快捷指令运行结果; 笔者使用“获取词典值”操作进行JSON解析,输入选择“URL的内容”,“词典”设为“errno”,然后再用“如果”判断语句判断“errno”是否为0,如果为0则执行“显示结果”操作,我设置为结果为“卧室小风扇已打开”。
很简单,你只需要对设备说:“Hey Siri,打开卧室小风扇”,Siri就会自动执行快捷指令,不出意外的话,Siri会说:“好的,卧室小风扇已打开”(图中所示为笔者打开台灯的截图)。
由于单片机执行程序可能不及时,有时候下发的命令不一定会被单片机执行,这时候我们只需要添加“重复”操作,重复多次“获取URL的内容”操作即可,也可以添加“等待”操作,设置等待时间,实现类似单片机“delay”的效果。
重复执行命令
保存上面创建的打开风扇的快捷指令,然后在快捷指令列表里,长按“打开卧室小风扇”,选择“复制”,列表出现“打开卧室小风扇1”,我们点“…”符号编辑,再把请求体键值中“true”改为“false”,最后修改快捷指令名称为“关闭卧室小风扇”,就可以实现关闭功能了。
批量新建快捷指令
当然也可以直接在第三章创建的快捷指令里添加“选择”操作,通过语音、手动或特定输入条件,选择开或关、反转状态、定时开、延时开等各种操作,实现各种个性化的需求,有兴趣的可以打开快捷指令研究,笔者此处不再赘述。
有人说,ESP8266-本身就是基于一块非常强大的32位芯片开发的,为什么还要引入STM32?我认为,ESP8266和STM32相比各有优劣,外设种类和数量、稳定性、价格、开发难度等都有区别。只使用STM32W系列支持无线的芯片开发的物联网系统,或者只使用ESP-01s就能完成的物联网系统,都有其特定的使用环境,而将不支持无线功能的STM32F系列和ESP-01S运用在一个设备上,取长补短,不存在冲突一说。
除了上述打开、关闭电器以外,多协议接入还支持多种API,如下所示(点击下划线文字即可跳转到文档界面)。
新增设备 注册设备 更新设备 查询设备详情 批量查询设备详情 批量查询设备状态 删除设备
新增数据流 更新数据流 查询数据流 批量查询数据流 删除数据流 查询设备历史数据 批量查询设备数据 上传数据点
上传文件 获取文件 发送命令 查询命令状态 查询命令响应 查询设备历史命令
新增触发器 更新触发器 查询触发器 删除触发器
新增apikey 更新apikey 查询apikey 删除apikey
以下贴出常用的三种请求方式,详细文档可参考OneNET多协议接入开发手册。
请求方式:POST URL: http://api.heclouds.com/devices/device_id/datastreams
device_id:需要替换为设备ID
请求头部示例
POST http://api.heclouds.com/devices/20474930/datastreams HTTP/1.1
{ "id": "speed", "tags": ["mobile"], "unit": "m/s", "unit_symbol": "m/s" }
返回示例
{ "errno": 0, "data": { "ds_uuid": "856f8622-64e7-5549-8e55-44931f07db6e" }, "error": "succ" }
请求方式:GET URL: http://api.heclouds.com/devices/device_id/datastreams
device_id:需要替换为设备ID
请求示例
GET http://api.heclouds.com/devices/20474930/datastreams?datastream_ids=aaa,bbb HTTP/1.1
返回示例
{ "errno": 0, "data": [{ "update_at": "2017-11-20 10:03:10", "id": "aaa", "create_time": "2017-11-20 09:59:35", "current_value": { "Header": { "CipherType": 1, "DevType": 1 }, "Body": 3 } }, { "update_at": "2017-12-22 10:30:22", "id": "bbb", "create_time": "2017-12-22 10:12:36", "current_value": 1 }], "error": "succ" }
请求方式:POST URL:http://api.heclouds.com/cmds
请求示例
POST http://api.heclouds.com/cmds?device_id=8029377 HTTP/1.1
api-key: l2aH*************BRtAo=
Host: api.heclouds.com
Content-Length: 19
返回示例1:成功创建命令
{ "errno": 0, "error": "succ", "data": { "cmd_uuid": "81572aae-fc34-5deb-8f06-ab45d73cb12b" } }
返回示例2:设备不在线
{ "errno": 10, "error": "device not online: 8029377" }
------END------