<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/ZLIOTA/Air724UG/aliyun.html" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>
<iframe frameborder="0" height="1500" name="ifd" scrolling="auto" src="https://mnifdv.cn/resource/cnblogs/ZLIOTA/Air724UG/aliyun.html" width="100%"></iframe>
说明
这一节实现Android扫码绑定模组并通过阿里云物联网平台实现远程通信控制.
概要:
APP和单片机设备分别作为设备以动态注册方式连接阿里云物联网平台,然后通过规则引擎实现APP和设备之间通信.
此节教程是前面所有知识点的整合,希望用户按部就班的学习了前面的内容,然后再学习此节.
测试准备
1.打开这节的APP工程和单片机工程
2.登录自己的云平台
注:选择哪个产品,设备就会注册到哪个产品下
3,查看并替换自己产品的ProductSecret; ProductKey; (单片机程序里面和android程序里面都需要替换)
4,查看并替换自己instanceId
提示:在2021年7月30日之前购买的实例是没有 instanceId 的, 程序里面可保持空
提示:有 instanceId 的, 填写上实例的 instanceId
配置规则引擎
1.规则引擎 ,云产品流转,创建规则
2.选择编写 SQL
3.添加操作
4.注意①自己填写 ${TargetDevice}
5.启动规则
测试
1.修改完成以后编译下载单片机程序
单片机日志打印订阅主题成功说明单片机程序正常运行
2.在平台上可以看到在相应的产品下面注册了设备
注:设备名字使用的是模组的IMEI号
3.重新编译并安装APP软件到手机, 运行APP会弹出注册页面.
注:接入的设备的名字做成了需要用户去填写
4.填写 111111(随意哈) 后点击 注册设备
5.注册成功将会跳转到主页(允许权限)
6.在平台上可以看到在相应的产品下面注册了设备
7.点击APP右上方的菜单栏,选择 扫一扫
8.扫描模组上面的二维码
9.扫描成功以后将会在主页面添加一个设备
10.点击显示的设备,进入设备控制页面
整体通信流程说明
1.通信流程详细说明
APP和单片机各自作为阿里云的设备接入阿里云服务器.
APP接入的名字为用户注册时填写的名字;
单片机接入的名字为模组的IMEI号;
APP 添加设备的时候添加的模组的IMEI号.
假设APP注册的设备的名字为: 111111
假设模组的IMEI为: 868591050594364
APP发布的主题: /a1m7er1nJbQ/111111/user/update
APP发布的消息为: {"TargetDevice":"868591050594364","DeviceName":"111111","data":"switch","status":"1"} (以控制继电器吸合的数据为例子)
注:
TargetDevice 字段的值是APP扫码添加的设备的名字
DeviceName 字段的值是APP本身设备的名字.
这个主题发给云平台以后,经过了转发规则里面的SQL语句
注: /a1m7er1nJbQ/+/user/update (里面的 + 代表任意)
APP发布的主题为 /a1m7er1nJbQ/111111/user/update 符合咱设置的规则.规则便会提取这个主题里面的消息.
然后下面的配置是对提取的消息进行操作
发布到另一个 Topic /a1kalhdMH2Z/${TargetDevice}/user/get
${TargetDevice}意思是提取消息里面字段为 TargetDevice 的字段值,然后替换上面的 ${TargetDevice}
咱的消息是 {"TargetDevice":"868591050594364","DeviceName":"111111","data":"switch","status":"1"}
所以最终消息转发给下面的主题(也就是单片机订阅的主题)
/a1m7er1nJbQ/868591050594364/user/get
然后单片机就收到了消息 {"TargetDevice":"868591050594364","DeviceName":"111111","data":"switch","status":"1"}
单片机接收到消息以后,提取 "DeviceName":"111111"
然后用自己的发布主题发布消息
发布的主题: /a1m7er1nJbQ/868591050594364/user/update
发布的消息: {"TargetDevice":"111111","DeviceName":"868591050594364","data":"switch","status":"1"}
TargetDevice 字段的值改为了 111111
DeviceName 字段的值为单片机设备的名字 868591050594364
消息发给了服务器,然后经过转发规则,同理 ,消息便会转发给了APP
最后APP 提取消息里面的数据,就完成了通信
单片机程序说明
单片机程序就是前面的动态注册, 规则引擎 的结合
APP和设备通信使用的是自定义主题.
里面的大部分都是前面的程序, 只是订阅发布的主题改为了自定义的
还有就是在接收回调函数里面接收并处理数据.
1.注册,连接服务器
2.连接成功之后订阅主题
3.在MQTT回调函数里面接收处理和返回消息
Android程序详细说明
1.如果APP没有注册,跳转到注册设备页面
2.点击按钮注册设备,并把注册信息存储以后跳转到主页面
3.获取注册的数据,组合MQTT参数,并执行连接
4.点击扫描二维码,进入扫描页面
5.扫码成功,携带着数据跳转到主页
6.MainActivity在onNewIntent中接收返回的数据
7.把数据存储到数据库,并刷新页面
8.点击设备,携带着提取点击的设备名字跳转到控制页面
9.获取APP设备的productKey和deviceName,并拼接其自定义的主题
10.获取传递进来的所点击的设备的名字,组合开关控制数据
11.APP订阅自身的自定义主题
12.定时请求设备数据
13.点击按钮发送控制继电器指令
14.接收数据
细节说明
1.APP每隔一段时间发送查询继电器状态和查询温湿度数据
如果发送完查询命令之后设备返回了数据,则设备在线
如果在下次查询时,设备上次没有返回数据,则认为设备离线
2.建议用户优化的问题
现在是每隔一段时间查询继电器状态会出现一个问题: (假设是控制继电器吸合)
如果刚刚发送了查询继电器状态,然后用户突然点击了控制继电器的按键,
这样子的话会发送了一个查询和一个控制指令给设备, 设备会先返回继电器状态(继电器是断开状态)
设备呢再返回控制状态(继电器吸合状态)
所以就会发现APP那个按键先变为吸合状态,然后又变为断开状态, 然后又变为吸合状态.
建议用户查询继电器状态的时候呢,只要查询上了继电器状态就不要去查询了.
但是呢又来个问题, 如果是多个人使用APP控制设备继电器呢?
我这边不去查询的话,又不能知道设备的真实状态了, 咱需要让设备主动上报才可以.
那么就需要单片机去记录所有的APP设备名称, 发送数据的时候呢,
轮训把消息发送给每个控制过自己的APP.
但是呢,单片机不能无限的去记录各个APP的名称, 咱希望的是有限的记录, 并且可以对这些APP进行等级排序
经常控制设备的APP呢就把它记录到前面, 不经常甚至是太久远的呢可以自动去丢弃掉.
为此我设计了一套缓存
https://www.cnblogs.com/yangfengwu/p/14164215.html
实现的话大家伙去实现吧, 现在程序里面之所以没加上是为了便于大家入门.