问题
行空板的常规数据通信方式为MQTT,但App Inventor开发环境自带的官方组件中没有对应组件类型。尽管可以通过采用社区开发的插件来解决,但可能存在一定的稳定性以及因系统升级带来的失效风险。因此,需要另外采取其他成熟的通信技术进行间接解决。
方案
由于App Inventor自身提供的云数据库(CloudDB)组件支持基于Redis的实时通信技术,而后者又是一个成熟且流行的跨平台内存数据库产品,支持基于订阅/发布的轻量级消息传递机制,具有低延迟以及高可靠等突出特点,常用于消息代理、分布缓存以及实时通信等应用场景。因此,可以通过在行空板系统中安装redis服务器以及对应的Python开发库,并开发相应的后端应用程序,来解决二者之间的通信问题。
步骤
连接行空板
将行空板连接到开发用计算机上,并开启计算机
在计算机浏览器中访问10.1.2.3,然后选择页面中的网络设置功能,将行空板接入本地WiFi网络
在计算机上安装并运行Mind+
Mind+启动成功后,点击控制台区域上侧的终端按钮,开启远程连接终端
安装Redis
在提示符后的下划线处输入 apt update -y & apt upgrade -y并回车,进行系统资源的更新和升级
当升级和更新完成后,在重新重现的系统提示符后输入 apt install redis-server并回车,安装redis服务器
安装结束后,在提示符后输入 systemctl status redis,检查安装情况。如果返回的信息中出现绿色的active (running)信息,表示安装成功
在提示符后输入 cp /etc/redis/redis.conf .,复制Redis服务器的配置文件。然后点击文件目录面板右侧的刷新按钮,如看到“行空板的文件”中出现redis.conf名称,表明复制成功
点击“行空板的文件”中redis.conf文件,并点击其右侧的上下文菜单(纵向的三个点),选择“在编辑区打开”菜单项,对配置文件进行修改
在编辑区打开的redis.conf文件中寻找bind参数,将第69行 bind 127.0.0.1 ::1之前添加#号将其取消;然后寻找port参数,将92行port之后的默认端口值6379,修改为6381;最后寻找requirepass参数,删除507行requirepass之前的#号,并在其后添加一个空格,输入大写的APPINVENTOR。全部完成后,点击保存按钮
修改完成后,在控制台的提示符后,输入 systemctl stop redis,暂停Redis服务器运行
在提示符后输入 cp redis.conf /etc/redis/redis.conf,覆盖Redis服务器的配置文件
在提示符后输入 systemctl start redis,重新启动Redis服务器
测试连接
打开App Inventor,并创建一个新项目test
在设计视图中添加一个云数据库组件,将其名称修改为”行空板”,并将“启用SSL”属性设为假,访问令牌属性设为APPINVENTOR,服务地址设为行空板在无线网中的IP地址,如 192.168.1.110等
- 再向屏幕中分别添加一个名称为”对话框1”的对话框组件、一个名称为“写入按钮”的按钮组件,以及一个名为“读取按钮”的按钮组件。然后将两个按钮组件的文本属性分别修改为“写入”和“读取”
在编程视图中,点击写入按钮组件对象,并向工作区拖入“当写入按钮被点击时”事件块。然后在“当写入按钮被点击时”的执行区域,添加行空板板组件对象的“让行空板保存数据”方法块,将其标记参数设置为”你好”、存储数据参数设置为“行空板”
向工作区中添加读取按钮组件的“当读取按钮被点击时”事件块,在其执行区域添加行空板组件对象的“让行空板请求数据”方法块,将后者的标记参数设为“你好”,无标记返回参数设为空文本
向工作区中添加行空板组件对象的“当行空板收到数据时”事件块,在其执行区域添加对话框1的“让对话框1显示消息对话框”方法块,将其消息参数设为事件块的数值块,标题参数设为事件块的标记块,按钮文本参数设为“关闭”文本
连接AI伴侣,先点击手机屏幕上的写入按钮,然后再点击读取按钮,如果弹出标题为“你好”、消息为“行空板”的对话框窗口,表示App Inventor应用与行空板上的Redis服务器之间的通信正常
应用示例
功能描述
在手机屏幕上切换开关组件的状态,可以点亮或关闭连接在行空板上的LED灯
按下行空板的a键,打开板上连接的LED灯,按b键关闭LED灯。同时,手机屏幕上的开关组件,会随着LED灯的开闭,同步切换其状态。即LED开,则开关组件开启;LED关,则开关组件关闭
行空板部分
将DFRobot的LED模块连接到行空板的22口
- 点击Mind+左上部的代码按钮,接着点击右侧的库管理按钮
然后在弹出的窗口中选择PIP模式,并在其右侧的下拉菜单中选择“清华大学源”
- 在PIP手动安装下的输入框中输入“redis”,然后点击右侧的运行按钮。观察窗口下部区域中的安装信息,当出现“命令运行完成”时,表示redis库安装完成。此时,点击窗口右上角的x号,将其关闭
在打开的main.py文件中,输入以下代码
import jsonimport redisfrom unihiker import GUIfrom pinpong.extension.unihiker import *from pinpong.board import Board,Pin# 切换led灯状态def switching_led_status(s):level = 1 if s.strip('"') == "on" else 0p_p22_out=Pin(Pin.P22, Pin.OUT)p_p22_out.write_digital(level)# 按a键打开led灯def on_buttona_click():client.publish(channel, '["unihiker", ["on"]]')# 按b键关闭led灯def on_buttonb_click():client.publish(channel, '["unihiker", ["off"]]')# 接收来自ai2的消息def getting_ai2_data(ch):pubsub = client.pubsub()pubsub.subscribe(ch)for msg in pubsub.listen():if msg['type'] == 'message':yield json.loads(msg['data'])# 处理来自ai2的数据def processing_ai2_data(data):for d in data:switching_led_status(d[1][0])# 第一步、初始化行空板u_gui=GUI()u_gui.on_a_click(on_buttona_click)u_gui.on_b_click(on_buttonb_click)Board().begin()# 第二步、连接Redis服务器client = redis.Redis(host='localhost',port=6381,password='APPINVENTOR',db=0,decode_responses=True)# 第三步、接收并处理App Inventor应用消息channel = 'test' # 频道名称应与云数据库组件的项目编号属性值相同ai2_data = getting_ai2_data(channel)processing_ai2_data(ai2_data)while True:pass
App Inventor部分
打开App Inventor,新建一个名为test的新项目
在设计视图中,向应用主屏幕Screen1分别加入一个开关组件和一个云数据库组件,并采用默认“开关1“和“云数据库1”名称
- 参照下图设置云数据库1的属性
进入编程视图,先创建一个用于表示控制消息发送者的全局变量”ai2发送”,初始值为真
向工作区加入开关组件的“当开关1状态改变时”事件块,用于设置开关组件对led器件的控制逻辑。由于行空板上的a、b键也会改变开关1的状态,所以需要对控制消息发送者进行甄别,确保只有手机屏幕上的操作才能触发后续的消息发送动作
向工作区添加云数据库组件的“当云数据库1数据被改变时”事件块,用于接收行空板侧发来的消息,对开关组件的状态进行控制。在改变开关组件状态之前,需要先将全局变量“ai2发送”设为假,然后才能设置开关组件的开通属性,避免因触发状态改变事件造成的循环控制问题。属性设置完成后,将全局变量恢复为初始值
连接AI伴侣,点击屏幕上的开关组件,改变其开通状态,同时观察行空板上连接led灯的亮灭情况。然后,分别按动行空板上的a、b键,点亮和熄灭led灯,同时观察手机屏幕上开关组件的相应变化。
其它方案
尽管将Redis服务器作为替代MQTT的通信方式,能够实现类似的双向实时通信效果,但由于需要进行额外的安装和配置过程,因此对开发人员的技术和能力有一定的要求。如果所开发的应用对实时性要求不高,还可以采用更简单的HTTP通信方案,也就是利用App Inventor的Web客户端组件,直接向行空板SIoT的WebAPI端口发起请求,以实现相关的控制功能。具体的WebAPI功能,可参考SIoT使用手册(https://siot./zh-cn/latest/6.advanced/03_webapi.html)中的相关说明。
我们可以将云数据库(Redis)方案中的示例项目,以Web客户端和HTTP通信方式进行改写,具体做法如下。
App Inventor部分
将test项目中的云数据库组件删除后,向Screen1中加入Web客户端组件,名称为默认的Web客户端1
删除编程视图中的原有代码块
- 在编程视图的工作区中输入以下代码块
Mind+部分
在Mind+中,点击系统菜单中的项目,并进一步选择新建项目
点击左侧图形块列表上部的模块,进入图形化开发界面
点击图形块列表下部的扩展图标。进入扩展库面板后,选择行空板和MQTT-py,然后选择返回
在舞台中输入以下图形代码,其中要将“初始化MQTT”的SIoT服务器参数设为127.0.0.1