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