在LUAT中使用MQTT客户端,游戏脚本,办公脚本自动操作
本文将介绍在LUAT中工程化使用MQTT客户端的方法及注意事项。实验平台为合宙AIR724UG,其固件版本为
Luat_V4001_RDA8910_FLOAT_TMP。
面向对象
使用middleclass库为脚本提供基础面向对象支持,将此repo中的middleclass.lua文件添加到项目中即可使用。middleclass库典型用法如下:
-- file: test.lua
local class = require 'middleclass'
local Test = class 'Test' -- 创建Test类-- Test对象初始化函数, 其形参个数可以是任意的
function Test:initialize(initA)self.a = initA -- 初始化成员变量
end-- Test对象成员函数
function Test:inc()self.a = self.a + 1
endfunction Test:getA()return self.a
endreturn Test
-- file: app.lua
local Test = require 'test'local test = Test:new(5) -- 创建Test对象-- 调用成员函数
test:inc()
print(test:getA()) -- 输出6
print(test.class.name) -- 输出对象类名'Test'
此外,通过middleclass还可实现继承及多态。
LUAT MQTT库介绍
使用mqtt库前,须先引入对应模块
require 'mqtt'
mqtt库相关函数如下:
local mqttc = mqtt.client('clientId') -- 创建mqtt客户端
mqttc:connect('host.com', PORT) -- 连接mqtt服务器
mqttc:subscribe('/topic') -- 订阅MQTT主题
mqttc:publish('/topic', 'payload') -- 发布MQTT主题
mqttc:receive(TIMEOUT, 'EVENT_NAME') -- 接收消息
详情请参阅官方文档。
LUAT MQTT库用法
由于socket库的限制,subscribe、publish、receive函数仅可在调用了connect函数的协程被调用,但对于一个完整的MQTT客户端应用,发布、订阅主题都是必不可少的环节。如何在同一协程中发布、订阅、接收MQTT主题?mqtt库对此也提供了所需接口,其中mqttc:receive的返回值是解决此问题的关键。
local TIMEOUT = 60000
local EVENT_NAME = 'CUSTOM_MQTT_EVENT'
local res, data, param = mqttc:receive(TIMEOUT, EVENT_NAME)
if res then-- 正确接收到MQTT消息,此时 type(res) == 'table'-- res.topic为消息主题、res.payload为消息负载
elseif data == 'timeout' then-- 超时错误,此时应当重新调用mqttc:receive函数
elseif data == EVENT_NAME then-- mqttc:receive所指定的名为EVENT_NAME的系统事件被发布-- 此时param为发布事件时所携带的参数-- <== 我们将在这里根据param变量进行实际的MQTT主题发布、订阅工作 ==>handleMqttAct(params) -- 此函数的实现将在下文给出
else-- 未知MQTT错误, 此时应当尝试重新连接MQTT
end
通过调用sys.publish函数,即可发布可中断mqttc:receive函数调用堵塞的系统消息。
由于socket库的限制,一般只允许在调用sys.publish时携带额外的string型参数,否则socket库内部会在接收系统事件时发生错误。通过修改socket库的源码,还可以令其允许发布对应名称系统事件时携带任意类型的参数。
--- a/lib/socket.lua
+++ b/lib/socket.lua
@@ -336,7 +336,12 @@ function mt:recv(timeout, msg, msgNoResume)if r == nil thenreturn false, "timeout"elseif r == 0xAA then
- local dat = table.concat(self.output)
+ local dat
+ if #self.output > 0 and type(self.output[1]) ~= 'string' then
+ dat = self.output[1]
+ else
+ dat = table.concat(self.output)
接着,定义subscribe及publish的包装函数:
function subscribe(topic)sys.publish(EVENT_NAME, {type = 'sub',topic = topic,})
endfunction publish(topic, payload)sys.publish(EVENT_NAME, {type = 'pub',topic = topic,payload = payload,})
end
外部代码通过这两个包装函数以发布、订阅MQTT主题,而实际的发布、订阅逻辑发生在handleMqttAct函数中:
function handleMqttAct(param)local sels = {sub = function()mqttc:subscribe(param.topic)end,pub = function()mqttc:publish(param.topic, param.payload)end,}local found = sels[param.type]if found ~= nil thenfound()end
end
MQTT初始化及断线重连流程
为保证程序健壮性,实际应用时常常需要涉及程序自动从错误状态恢复的逻辑,MQTT的断线重连便是其中一种:
开始套接字 就绪?连接MQTT服务器成功?获取消息处理消息延时yesnoyesnoyesno
对MQTT库进行OOP封装
最后,给出基本的Cloud类实现:
-- file: cloud.lua
require 'mqtt'
local class = require 'middleclass'
local Cloud = class 'Cloud'-- 自定义事件名
local M_MQTT_ACT = 'M_MATT_ACT'
local TIMEOUT = 60000function Cloud:initialize(host, port, clientId)self.ready = falsesys.taskInit(function()while true dowhile not socket.isReady() do sys.wait() endself.mqttc = mqtt.client(clientId)if self.mqttc:connect(host, port) thenself.ready = trueself:onConn()while true dolocal res, data, param = self.mqttc:receive(TIMEOUT, M_MQTT_ACT)if res thenself:handleMqttMsg(res.topic, res.payload)elseif data == 'timeout' then-- DO NOTHINGelseif data == M_MQTT_ACT thenself:handleMqttAct(param)elsebreak -- 断线重连endendself.ready = falseendendend)
endfunction Cloud:onConn()-- 由派生类重写
endfunction Cloud:subscribe(topic)sys.publish(M_MQTT_ACT, {type = 'sub',topic = topic,})
endfunction Cloud:publish(topic, payload)sys.publish(M_MQTT_ACT, {type = 'pub',topic = topic,payload = payload,})
endfunction Cloud:handleMqttMsg(topic, payload)-- TODO: MQTT消息处理
endfunction Cloud:handleMqttAct(param)local sels = {sub = function()self.mqttc:subscribe(param.topic)end,pub = function()self.mqttc:publish(param.topic, param.payload)end,}local found = sels[param.type]if found ~= nil thenfound()end
endreturn Cloud
于Cloud,还可以拓展出自动在恢复连接后重注册已订阅主题的子类
-- file: cloudAutoReSub.lua
require 'mqtt'
local class = require 'middleclass'
local Cloud = require'cloud'
local CloudAutoReSub = class('CloudAutoReSub', Cloud)function CloudAutoReSub:initialize(host, port, clientId)self.subscribedTopics = {}self.class.super.initialize(self, host, port, clientId)
endfunction CloudAutoReSub:onConn()for _, v in ipairs(self.subscribedTopics) doself.mqttc:subscribe(v)end
endfunction CloudAutoReSub:subscribe(topic)table.insert(self.subscribedTopics, topic)self.class.super.subscribe(self, topic)
endreturn CloudAutoReSub相关文章:
在LUAT中使用MQTT客户端,游戏脚本,办公脚本自动操作
本文将介绍在LUAT中工程化使用MQTT客户端的方法及注意事项。实验平台为合宙AIR724UG,其固件版本为Luat_V4001_RDA8910_FLOAT_TMP。 面向对象 使用middleclass库为脚本提供基础面向对象支持,将此repo中的middleclass.lua文件添加到项目中即可使用。middl…...
如何解决maven中snapshot相关jar无法拉取问题
Maven中的SNAPSHOT版本是指正在开发中的版本,这些版本可能会频繁地更新。在使用Maven构建项目时,有时会遇到无法拉取SNAPSHOT相关jar的问题。以下是几种常见的解决方案: 1. 检查Maven配置文件(settings.xml) 确保你的M…...
类似crossover的容器软件有哪些 除了crossover还有什么 Mac虚拟机替代品
CrossOver是Mac用来运行exe文件的一款软件,但是并不是所有的exe文件CrossOver都支持运行。想要在Mac上运行exe文件的方法并不是只有使用CrossOver这一种,那么有没有类似的软件也可以实现exe文件在Mac上运行呢? CrossOver类似软件有哪些 1、Pl…...
以sqlilabs靶场为例,讲解SQL注入攻击原理【54-65关】
【Less-54】 与前面的题目不同是,这里只能提交10次,一旦提交超过十次,数据会重新刷新,所有的步骤需要重来一次。 解题步骤: 根据测试,使用的是单引号闭合。 # 判断字段的数量 ?id1 order by 3 -- aaa# …...
详解 Flink 的时间语义和 watermark
一、Flink 时间语义类型 Event Time:是事件创建的时间。它通常由事件中的时间戳描述,例如采集的日志数据中,每一条日志都会记录自己的生成时间,Flink 通过时间戳分配器访问事件时间戳Ingestion Time :是数据进入 Flink…...
Unreal Engine项目结构与关卡设置详解
引言 Unreal Engine 是一款功能强大的游戏引擎,为开发者提供了丰富的工具来创建和管理游戏项目。本文将详细介绍一个基本的 Unreal Engine 项目结构,并讲解如何在 Unreal 编辑器中进行关卡设置与操作。 Unreal Engine 项目结构 一个基本的 Unreal Eng…...
Access数据中的SQL偏移注入
使用场景: 目标数据表的字段较多,无法一一获取的时候,尝试使用偏移注入的方式实现SQL注入。 原理: 例如:一个表有6个字段,而你想获取的目标表admin的字段不知道,此时可以使用联合查询的方式获…...
Unity 编辑器扩展,获取目录下所有的预制件
先看演示效果 实现方案 1创建几个用于测试的cube 2,创建一个Editor脚本 3,编写脚本内容 附上源码 using UnityEditor; using UnityEngine;public class GetPrefeb : EditorWindow {private string folderPath "Assets/Resources"; // 指定预…...
【Python】解决Python报错:ValueError: not enough values to unpack (expected 2, got 1)
文章目录 引言1. 错误详解2. 常见的出错场景2.1 函数返回值解包2.2 遍历含有不同长度元组的列表 3. 解决方案3.1 检查和调整返回值3.2 安全的解包操作 4. 预防措施4.1 使用异常处理4.2 单元测试 结语 引言 在Python编程中,ValueError 是一个常见的异常类…...
政安晨【零基础玩转各类开源AI项目】解析开源:gradio:改进真实虚拟试穿的扩散模型
政安晨的个人主页:政安晨 欢迎 👍点赞✍评论⭐收藏 收录专栏: 零基础玩转各类开源AI项目 希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正! Gradio 是一个开源 Python 软件包,可以让你…...
深入解读Prometheus Adapter:云原生监控的核心组件
一、引言 Prometheus Adapter的背景与重要性 在现代的云原生架构中,微服务和容器化技术得到了广泛的应用。这些技术带来了系统灵活性和扩展性的提升,但同时也增加了系统监控和管理的复杂度。Prometheus作为一款开源的监控系统,因其强大的指标…...
【计算机视觉】数字图像处理基础:以像素为单位的图像基本运算(点运算、代数运算、逻辑运算、几何运算、插值)
0、前言 在上篇文章中,我们对什么是数字图像、以及数字图像的组成(离散的像素点)进行了讲解🔗【计算机视觉】数字图像处理基础知识:模拟和数字图像、采样量化、像素的基本关系、灰度直方图、图像的分类。 我们知道&a…...
Spring Boot整合WebSocket和Redis实现直播间在线人数统计功能
😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~ 🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志 🎐 个人CSND主页——Mi…...
uniapp自定义的下面导航
uniapp自定义的下面导航 看看效果图片吧 文章目录 uniapp自定义的下面导航 看看效果图片吧  前言一、写组件、我这里就没有写组件了直接写了一个页面?总结 前言 在…...
【Python】selenium使用find_element时解决【StaleElementReferenceException】问题的方法
StaleElementReferenceException 是 Selenium WebDriver 中的一种异常,通常在元素与当前页面的状态不同步时抛出,比如页面已经刷新或导航到另一个页面,但是尝试操作的元素引用仍然是旧页面上的元素。 以下是一些解决 StaleElementReferenceE…...
Apache IoTDB 分布式架构三部曲(三)副本与共识算法
IoTDB 首创并应用的共识协议统一框架,为用户提供了灵活选择不同共识算法的可能性。 对于一个分布式集群而言,为了使得海量数据场景下集群能够横向扩展,集群需要按照一定的规则将全部数据分成多个子集存储在不同的节点上,从而能够更…...
数据挖掘--聚类分析:基本概念和方法
数据挖掘--引论 数据挖掘--认识数据 数据挖掘--数据预处理 数据挖掘--数据仓库与联机分析处理 数据挖掘--挖掘频繁模式、关联和相关性:基本概念和方法 数据挖掘--分类 数据挖掘--聚类分析:基本概念和方法 聚类分析 聚类分析是把一个数据对象&…...
APP单页分发源码下载安卓苹果自动识别apk描述文件免签自动安装
下载地址:APP单页分发源码下载安卓苹果自动识别apk描述文件免签自动安装...
golang定时器使用示例
1.定时器创建与停止 //定时器使用t1 : time.NewTimer(2 * time.Second)<-t1.Cfmt.Println("timer1 fired")t2 : time.NewTimer(5 * time.Second)go func() {fmt.Println("go协程处理中,等待5秒后输出...")<-t2.Cfmt.Println("timer2 fired&quo…...
[FSCTF 2023]Tea_apk
得到密文和密钥 import base64 from ctypes import c_uint32import libnumDELTA 0x9E3779B9def decrypt(v, n, k):rounds 6 int(52 / n)sum c_uint32(rounds * DELTA)y v[0].valuewhile rounds > 0:e (sum.value >> 2) & 3p n - 1while p > 0:z v[p …...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
scikit-learn机器学习
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...
【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
