跳转至

LuatOS 的消息机制详解

LuatOS 的消息机制是其多任务协作和事件驱动编程的核心部分,主要通过 syssysplus 这两个核心库实现。

消息机制包括消息的发送、接收、订阅,以及系统消息的定义和使用,下面分别详细描述其原理和使用方法。

一、LuatOS 消息机制的原理

1.1 消息机制的基本原理描述

LuatOS 基于消息队列实现任务间通信,消息队列遵循先进先出(FIFO)原则。

消息机制配合 Lua 的协程(coroutine),可以非常丝滑的实现协作式多任务。

每一个协程的运行,是相互逻辑独立的;

在协程之间收发消息,可以实现不同协程间的通信。

消息发布者调用 LuatOS 的 API 发送全局消息或者定向消息。

订阅者通过回调函数或协程等待消息并处理,实现异步事件驱动。

消息调度流程大致如下:

(1)发布消息时,将消息及参数插入消息队列。

(2)消息分发函数从队列取出消息,根据消息 ID 查找订阅者列表。

(3)调用订阅者的回调函数或恢复协程,传递消息参数。

(4)订阅者处理消息,实现任务间通信和事件响应。

这种设计使得任务间解耦,消息驱动程序结构清晰,适合物联网设备的异步事件处理需求。

1.2 LuatOS 的消息队列

LuatOS 的消息队列有两个: 用户消息队列和系统消息队列。

1.1.1 用户消息队列:

用户消息队列,存储在Lua层,由Lua脚本内部使用。

用户消息队列的发送接口有两个: `sys.publish()`和 `sysplus.sendMsg()`。

用户消息队列的接收接口有三个: sys.waitUntil(),sysplus.waitMsg(),sys.subscribe()

1.1.2 系统消息队列:

系统消息队列,存储在RTOS层,是RTOS操作系统的基本单元。

系统消息只能是使用 RTOS 的接口发送该消息,并且该发送消息接口是不开放给用户的。

系统消息队列的消息, 由 sys 核心库收取,并传送给对应的协程或者回调函数进行处理。

系统消息队列用于硬件事件,网络事件和定时器事件的传递。

比如说,当 Lua 脚本的某个协程运行了这行代码:
sys.wait(1000)
   sys 核心库就会调用 rots 的timer 接口, 注册一个定时器消息。 

   当定时器超时后,rots 会发送给sys库一个定时器超时消息,sys库就能够通知对应的协程,可以恢复运行了。

1.3 topic 和消息的差异

1.3.1 topic 和消息的差异

LuatOS 的消息,分为两类: topic 和消息。

topic 跟事件的概念是类似的,在 LuatOS 语境里面,topic 往往就是指事件。

topic 是全局消息,是广播消息。

而消息跟 topic 的不同,消息是有特定接收方的,而 topic 没有特定接收方。

LuatOS 的 sys.publish 接口是发布一个全局消息,也就是发布了一个 topic,也是发布了一个事件。

sys.subscribe 接口订阅了一个 topic,也就是订阅了一个事件。

sysplus.sendMsg, 是发送的消息, sysplus.waitMsg, 是等待和处理一个消息,是有特定的协程名字作为接收方的。

为了简化描述,在下文的其余部分,如果没有特别的说明,我们不再区分 topic 和消息的差异,统一把 topic 和消息称为消息。

1.3.2 mqtt 和 LuatOS 的 topic 的差异

mqtt 的 topic 与 sys 的 topic 有如下差异:

mqtt 的 topic 的订阅关系是服务器侧(borker)维护的,支持严格匹配和通配符匹配;

sys 的 topic 的订阅关系是 LuatOS 嵌入式系统内部维护的,只支持严格匹配。

1.4 LuatOS 消息的使用

尽管有用户消息队列和系统消息队列两种差异,但是在使用消息的时候,可以不关注这种差异。

用户只需要调用 sys.publish()接口和 sysplus.sendMsg()接口,按照自己的需要发送消息。

在接收和处理消息的时候,用 sys.subscribe()接口,指定某个消息的回调函数,这时候的消息,也不需要区分用户队列的消息还是系统消息,只要知道消息的名字,都可以指定消息的回调处理函数。

使用 sys.waitUtil()接口,sysplus.waitMsg 接口的时候,也不需要关心是用户队列的消息还是系统队列的消息,只要知道消息名字,都可以处理。

所有的发送消息,和接收处理消息的接口的使用,接下来都会做消息的介绍。

二、消息的发送

2.1 全局消息(sys 库)

全局消息,也可以理解为广播消息,所有的协程都是可以监听和处理的。

使用`sys.publish(topic, arg1, arg2, ...)`向所有订阅该消息的广播发送该消息。

由于这个接口的发送是没有目标的标识,所以任何的协程都可以订阅处理这个消息。

例如:

sys.publish("NET_READY", true)
sys.publish("SENSOR_DATA", 25.5, "℃")

该消息发布后,会放入用户的消息队列,等待被订阅者处理。

2.2 定向消息(sysplus 库)

使用 sysplus.sendMsg(taskName, target, arg2, arg3, arg4) 向指定任务发送消息,可以指定接收消息的协程的名字,也可以同时给出消息携带的参数。

这种消息很适用于协程间的点对点通信。 例如:

-- 向名字为“NET_TASK” 的协程发送 “HTTP_RESP”消息,携带的参数有两个,分别给出来。
sysplus.sendMsg("NET_TASK", "HTTP_RESP", 200, "{data:123}")
  • 该消息直接发送给指定任务,很适合请求-响应模型。

三、消息的接收处理

LuatOS 消息的接收处理有三种方式: 订阅消息,取消订阅息,等待消息。

3.1 订阅消息

通过 sys.subscribe(id, callback) 订阅指定消息的 ID,注册回调函数,当消息到达时调用回调函数进行处理。 例如:

local function TempFunc(t)
  if t > 30 then sys.publish("FAN_ON") end
end

sys.subscribe("TEMP_UPDATE", TempFunc)

3.2 取消订阅

  使用`sys.unsubscribe(id, callback)`取消订阅,解除消息与回调的绑定。

3.3 等待消息

LuatOS 有两个等待消息的接口: waitUntil 和 waitMsg。

3.3.1 sys.waitUntil 接口

使用`sys.waitUntil(id, timeout)`阻塞当前协程,直到收到指定消息或超时,返回消息参数。

waitUntil 是等待特定全局消息的触发,可以被用于协程内监听系统级消息(如网络状态、硬件事件),也可以用于监听sys.publish发布的全局消息。

接口原型为:

local ok, data = sys.waitUntil(topic, timeout)
-- topic:消息字符串,事件标识(如 "NET_READY")。
-- timeout:整数,超时时间(毫秒),若为 nil 则无限等待。
-- 返回值:
-- ok:布尔值,true 表示收到消息,false 表示超时。
-- data:消息携带的数据。

使用示例:

local function SMSfunc()
  result, data = sys.waitUntil("SIM_IND", 120000)
  if result then
    -- 处理消息
  end
end

local function NetFunc()
    -- 等待网络就绪消息,超时30秒
    local ok, ip = sys.waitUntil("NET_READY", 30000)
    if ok then
        log.info("网络已连接,IP:", ip)
    else
        log.warn("网络连接超时")
    end
end

sys.taskInit(SMSFunc)
sys.taskInit(NetFunc)
  • 该机制基于协程挂起和恢复实现,方便同步等待异步事件。

3.3.2 sysplus.waitMsg 接口

waitMsg 接口用于定向接收协程间的消息,用于协程间的通信,比较适合请求-响应的多协程合作的工作模式。

接口原型:

local msg = sysplus.waitMsg(taskName, target, timeout)
-- taskName:字符串,接收消息的协程的名称(需唯一)。注意是等待消息的协程名称,也就是自己的协程名称,不是发送消息的协程的名称
-- target:字符串,接收的消息标识(若为 nil 则接收任意消息)。
-- timeout:整数,超时时间(毫秒),若为 nil 则无限等待。
--返回值:
-- msg:消息表(含 target、arg2、arg3 等字段),超时返回 false

使用示例:

-- 协程A:发送配置请求给到名为 "CONFIG_TASK" 的协程
sysplus.sendMsg("CONFIG_TASK", "GET_CONFIG", "param1")

-- 协程 "CONFIG_TASK":接收配置
local msg = sysplus.waitMsg("CONFIG_TASK", "GET_CONFIG", 5000)
if msg then
    log.info("收到配置参数:", msg.arg2) -- 输出 "param1"
end

waitMsg 有如下几个特点:

(1)精准定向:可以通过 taskNametarget 指定发送方与消息名称;

(2)参数传递:sendMsg 可以支持最多 3 个参数(通过 arg2~arg4 字段);

(3)适用协程之间的通信(如 HTTP 请求响应、任务间数据同步)。

四、sys 系统消息

4.1 系统消息是什么

LuatOS 框架预定义了一些系统消息,开发者可以直接订阅这些消息实现对硬件和系统事件的响应。

系统消息是由 LuatOS 内核或底层驱动自动发布的全局事件,面向所有订阅者广播,适用于硬件状态、网络事件等。

LuatOS 的系统消息,跟普通的消息并没有区别,但是由于是 LuatOS 底层发布的消息,并没有指定明确的接收协程名称,所以系统消息只能是当做全局的广播消息来处理。

用户可以使用 sys.WaitUntil 和 sys.subscibe 接口来处理系统消息,不能用 susplus.waitMsg 接口处理系统消息。

以下按功能模块分类详细说明所有系统消息及其触发条件和参数:

4.2 系统消息详解

序号
消息名称
触发条件/说明
参数说明
1
SIM_IND
SIM 卡状态变化
status, value
2

CELL_INFO_UPDATE
基站数据已更新

3
SCELL_INFO
服务小区额外信息更新

4
IP_READY
网络已连接,分配到 IP
ip, adapter
5
IP_LOSE
网络断开
adapter
6
NTP_UPDATE
基站时间同步成功

7
NTP_ERROR
时间同步失败

8
CSCON
RRC(无线资源控制)状态变化
state
9
CC_IND
通话状态变化
status, value
10
SMS_INC
收到短信
phoneno,smscontent
11
GNSS_STATE
GNSS状态变化
event, ticks
12
DTIMER_WAKEUP
deep sleep timer定时时间到回调
(timer_id
13
LORA_TX_DONE
LORA 发送完成

14
LORA_RX_DONE
LORA 接收完成
data, size, rssi, snr
15
LORA_TX_TIMEOUT
LORA 发送超时

16
LORA_RX_TIMEOUT
LORA 接收超时

17
LORA_RX_ERROR
LORA 接收错误

4.2.1 SIM_IND -- SIM 卡状态变化

1,功能说明:SIM 卡插拔、状态切换等都会触发。

2,参数:

3,代码示例:

local function simFunc(status, value)
    log.info("sim status", status, value)
**end**

sys.subscribe("SIM_IND", simFunc**)**

4.2.2 CELL_INFO_UPDATE -- 基站数据已更新

1,说明:基站(小区)信息发生变化时触发,适合周期性获取基站列表。

2,参数:无

3,代码示例:

local function cellinfoFunc(status, value)
    log.info("cell", json.encode(mobile.getCellInfo()))
**end**

sys.subscribe("CELL_INFO_UPDATE", cellinfoFunc)

4.2.3 SCELL_INFO -- 服务小区额外信息更新

1,说明:服务小区(主小区)详细信息变化时触发。

2,参数:无

3,代码示例:

local function scellFunc(status, value)
    log.info("service cell", mobile.scell())
**end**

sys.subscribe("SCELL_INFO", scellFunc)

4.2.4 IP_READY -- 网络已连接

1,说明:蜂窝网络成功分配 IP 后触发。

2,参数:

3,代码示例:

local function ipreadyFunc(ip, adapter)
    log.info("mobile", "IP_READY", ip, (adapter **or** -1) == socket.LWIP_GP)
**end**

sys.subscribe("IP_READY", ipreadyFun)

4.2.5 IP_LOSE -- 网络断开

1,说明:蜂窝网络断开时触发。

2,参数:

3,代码示例:

local function ipcloseFunc(adapter)
    log.info("mobile", "IP_LOSE", (adapter **or** -1) == socket.LWIP_GP)
**end**

sys.subscribe("IP_LOSE", ipreadyFun)

4.2.6 NTP_UPDATE -- 基站时间同步成功

1,说明:基站下发时间同步成功时触发。

2,参数:无

3,代码示例:

local function ntpupdateFunc()
    log.info("mobile", "time", os.date())
**end**

sys.subscribe("NTP_UPDATE", ntpupdateFunc)

-

4.2.7 NTP_ERROR -- 时间同步失败

1,说明:基站时间同步失败时触发。

2,参数:无

3,代码示例:

local function ntperrorFunc()
    log.info("mobile", "time sync error")
**end**

sys.subscribe("NTP_ERROR", ntperrorFunc)

4.2.8 CSCON -- RRC 状态变化

1,说明:无线资源控制状态变化(连接/空闲)。

2,参数:

3,代码示例:

local function csconFunc(state)
    log.info("mobile", "CSCON", state)
**end**

sys.subscribe("CSCON", csconFunc()

4.2.9 CC_IND -- 通话状态变化

1,说明:呼叫、通话等事件变化。

2,参数:

3,代码示例:

local function csconFunc(state, value)
    log.info("cc status", status, value)
**end**

sys.subscribe("CC_IND", csconFunc)

4.2.10 SMS_INC - 收到短信

1, 说明: 新短信到达之后,会收到这个消息

2, 参数:

  • phoneno:发送方的手机号
  • sms:收到的短信内容,UTF8 编码

3, 代码示例

--使用的例子,可多行-- 接收短信, 支持多种方式, 选一种就可以了
-- 1. 设置回调函数
local function newsmsFunc(phone,sms)
  log.info("sms",phone,sms)
end

sms.setNewSmsCb(newsmsFunc)

-- 2. 订阅系统消息
sys.subscribe("SMS_INC", newsmsFunc)

4.2.11 GNSS_STATE - GNSS 状态变化

1, 说明: GNSS 状态变化的时候,会收到这个消息

2, 参数:

  • event

状态变化的事件,取值有: -- FIXED 定位成功 -- LOSE 定位丢失 - ticks:事件发生的时间,一般可以忽略

3, 代码示例

local function gnssFunc(event, ticks)
  -- event取值有
  -- FIXED 定位成功
  -- LOSE  定位丢失
  -- ticks是事件发生的时间,一般可以忽略
  log.info("gnss", "state", event, ticks)
end

sys.subscribe("GNSS_STATE", gnssFunc)

4.2.12 DTIMER_WAKEUP - deep sleep timer 定时时间到回调

1, 说明: deep sleep timer 定时时间到的时候,会收到这个消息

2, 参数:

timer_id:  定时器Id

3, 代码示例

local function dtimerFunc(timer_id)
    log.info("deep sleep timer", timer_id)
end

sys.subscribe("DTIMER_WAKEUP", dtimerFunc)

4.2.13 LORA_TX_DONE - LORA 发送完成

1, 说明: Lora 发送完成后,收到这个消息

2, 参数:

3, 代码示例

local function loraSFunc()
    lora.recive(1000)
end

sys.subscribe("LORA_TX_DONE", loraSFunc)

4.2.14 LORA_RX_DONE - LORA 接收完成

1, 说明: Lora 接收完成后,收到这个消息

2, 参数:

  • data:接收到的数据内容
  • size:数据长度
  • rssi:信号强度(2023-09-06 后新增)
  • snr:信噪比(2023-09-06 后新增)

3,典型用法:收到数据后进行处理,并可选择立即发送数据或再次进入接收状态。

4, 代码示例

local function loraRFunc(data, size, rssi, snr)
    log.info("LORA_RX_DONE: ", data, size, rssi, snr)
    lora.send("PING")
end

sys.subscribe("LORA_RX_DONE", loraRFunc)

4.2.15 LORA_TX_TIMEOUT - LORA 发送超时

1, 说明: LoRa 数据发送超时后,收到这个消息

2, 参数:

3,典型用法: 发送超时后可重试或切换到接收模式,避免通信死锁。

4, 代码示例

local function loraTxTimeout()
    lora.recive(1000)
end

sys.subscribe("LORA_TX_TIMEOUT", loraTxTimeout)

4.2.16 LORA_RX_TIMEOUT - LORA 接收超时

1, 说明: LoRa 数据接收超时的时候,会收到这个消息

2, 参数:

3,典型用法: 接收超时后可重新进入接收状态,保证持续监听。

4, 代码示例

sys.subscribe("LORA_RX_TIMEOUT", function()
    lora.recive(1000)
end)

4.2.17 LORA_RX_ERROR - LORA 接收错误

1, 说明:LoRa 数据接收错误(如数据包损坏、校验失败等)的时候,会收到这个消息。

2, 参数:

3,典型用法:出现接收错误后,可选择重新进入接收状态或记录错误信息。

4, 代码示例

local function loraRxErrFunc()
  lora.recive(1000)
end

sys.subscribe("LORA_RX_ERROR", loraRxErrFunc)

4.3 补充说明

1, 这些系统消息均为系统自动发布,不能由用户主动发布。

2, 可结合 LuatOS 库的 API(如 mobile.getCellInfo()mobile.scell())获取详细数据。

五、LuatOS 的定时器机制

LuatOS 定时器机制基于消息驱动,常用的软件定时器接口集中在 sys 库中。

定时器到时后,会由 sys 库接收到定时器超时消息,并触发注册的回调函数或唤醒挂起的任务。

下面详细介绍其用法和原理。

5.1 LuatOS 定时器的基本原理

定时器到时后,会产生一条定时器消息(如 `rtos.MSG_TIMER`),并携带定时器 ID 作为参数。

系统主循环sys.run() 会检测到该消息,并根据注册信息分发给对应的回调函数或唤醒等待的任务。

5.2 常用定时器 API 及用法

5.2.1 单次定时器

1,创建方式:

sys.timerStart(function_name, timeout_ms, ...)
-- function_name:到时后执行的函数
-- timeout_ms:延时毫秒数
-- ...:可选参数,传递给回调函数

2,代码示例:

local function tFunc(arg)
  log.info("TIMER", "单次定时器触发", arg)
end

sys.timerStart(tFunc,200,"一次性参数")

5.2.2 循环定时器

1, 创建方式:

local timer_id = sys.timerLoopStart(function_name, interval_ms, ...)
-- 每隔 interval_ms 毫秒重复执行回调函数
-- 返回值 timer_id 可用于后续关闭定时器

2, 代码示例

-- 说明:每 5 秒触发一次
local function TFunc()
  log.info("TIMER", "循环定时器触发")
end

local tid = sys.timerLoopStart(TFunc, 5000)

5.2.3 停止定时器

1, 创建方式:

(1)停止指定定时器:

sys.timerStop(timer_id)

(2)停止所有绑定到某个回调的定时器:

sys.timerStopAll(function_name)

2,代码示例

-- 5 秒后关闭循环定时器
local tid = sys.timerLoopStart(my_func, 1000)
sys.wait(5000)
sys.timerStop(tid)

5.2.4 在任务中延时/等待消息

1, 函数说明

(1)sys.wait(ms):在 task 协程中挂起指定毫秒数,底层用定时器实现

(2)sys.waitUntil("MSG_ID", timeout_ms):等待某个消息或超时

代码示例

local function waitFunc()
    sys.wait(4000)
    log.info("TIMER", "4秒后继续")
    sys.waitUntil("MSG_ID")
    log.info("TIMER", "收到MSG_ID消息")
end

sys.taskInit(waitFunc)

5.2.5 判断定时器状态

1,使用方式

sys.timerIsActive(timer_id):判断定时器是否激活

2, 代码示例

-- sys.timerLoopStart 创建了一个2秒循环一次的定时器,返回定时器ID。
-- 在一个任务中,等待5秒后,使用 sys.timerIsActive(timer_id) 检查定时器是否还在运行。
-- 如果定时器激活,则打印提示并停止定时器;否则说明定时器已经被停止或超时。

local function tFun()
  log.info("TIMER", "循环定时器触发")
end

local timer_id = sys.timerLoopStart(tFun,2000)

-- 创建一个任务,5秒后检查定时器状态
local function chFunc()
    sys.wait(5000)  -- 等待5秒
    if sys.timerIsActive(timer_id) then
        log.info("TIMER", "定时器仍然激活,准备停止")
        sys.timerStop(timer_id)
    else
        log.info("TIMER", "定时器已经不激活")
    end
end

sys.taskInit(chFunc)

5.3 总结

1, sys.waitsys.waitUntil 只能在 task 协程中使用。

2, 定时器到时后,底层会向消息队列推送 rtos.MSG_TIMER 消息,并附带定时器 ID。

3, 系统主循环 sys.run() 检测到该消息后,会查找定时器池,将参数传递给注册的回调或唤醒挂起的协程

4, 定时器总结表

序号
功能
API 示例
说明
1
单次定时器
sys.timerStart(func, 2000, arg)
2 秒后执行一次
2
循环定时器
sys.timerLoopStart(func, 5000, arg)
每 5 秒执行一次
3
停止定时器
sys.timerStop(timer_id)
停止指定定时器
4
停止所有定时器
sys.timerStopAll(func)
停止所有同回调定时器
5
延时
sys.wait(1000)
协程中延时 1 秒
6
等待消息
sys.waitUntil("MSG_ID", 5000)
等待消息或超时
7
判断状态
sys.timerIsActive(timer_id)
查询定时器是否激活

六、消息机制的使用流程示例

如下的示例,展示了如何订阅消息、发布消息和在任务中等待消息,帮助理解 LuatOS 消息机制的核心用法。

该示例完整展示了 LuatOS 消息机制的核心用法,建议在真实设备运行时结合串口日志观察执行流程。

实际项目中可根据需要调整消息类型和定时器间隔。

6.1 代码示例

PROJECT = "STRUCTURED_MSG_DEMO"
VERSION = "1.0.0"
sys = require("sys")
sysplus = require("sysplus")

-- 全局变量定义
local mainTaskTimerId  -- 主任务循环定时器ID
local subTaskHandle    -- 子任务句柄

-- 模块级函数声明
local function globalEventHandler(data)
    log.info("全局处理器", "收到全局事件:", data)
end

local function loopTimerCallback()
    log.info("定时器", "循环定时器触发")
end

local function stopLoopTimer(tid)
    log.info("定时器", "停止循环定时器")
    sys.timerStop(tid)
end

local function subTaskProcessor()
    log.info("子任务", "启动")
    while true do
        local msg = sysplus.waitMsg("SUB_TASK", "DATA_CMD", -1)
        if msg then
            log.info("子任务", "收到数据", msg.arg2, msg.arg3)
            sys.publish("GLOBAL_EVENT", "处理完成:"..msg.arg2)
        end
    end
end

local function mainTask()
    -- 初始化循环定时器
    mainTaskTimerId = sys.timerLoopStart(loopTimerCallback, 1000)

    -- 设置5秒后停止定时器
    sys.timerStart(stopLoopTimer, 5000, mainTaskTimerId)

    -- 发送定向消息
    for i = 1, 3 do
        sysplus.sendMsg("SUB_TASK", "DATA_CMD", "数据包"..i, os.time())
        sys.wait(1500)
    end

    -- 处理全局事件
    while true do
        local ok, data = sys.waitUntil("GLOBAL_EVENT", 3000)
        if ok then
            log.info("主任务", "收到全局回调:", data)
        else
            log.warn("主任务", "等待全局事件超时")
            break
        end
    end
end

-- 初始化函数
local function init()
    -- 注册全局事件监听
    sys.subscribe("GLOBAL_EVENT", globalEventHandler)

    -- 启动子任务
    subTaskHandle = sysplus.taskInitEx(subTaskProcessor, "SUB_TASK")

    -- 启动主任务
    sys.taskInit(mainTask)
end

-- 系统启动
init()
sys.run()

6.2 代码的执行流程说明

1, 初始化阶段:

2, 消息传递流程:

sequenceDiagram
mainTask->>subTaskHandle: sendMsg(DATA_CMD)
subTaskHandle->>GLOBAL_EVENT: publish(处理完成)
GLOBAL_EVENT->>mainTask: waitUntil接收

3, 定时器生命周期:

6.3 执行日志

I/子任务 启动
I/定时器 循环定时器触发
I/主任务 收到全局回调: 处理完成:数据包1
I/定时器 循环定时器触发
I/子任务 收到数据 数据包2 1700000000
I/主任务 收到全局回调: 处理完成:数据包2
I/定时器 循环定时器触发
I/子任务 收到数据 数据包3 1700000001
I/主任务 收到全局回调: 处理完成:数据包3
I/定时器 停止循环定时器
I/主任务 等待全局事件超时

6.4 关键 API 对照表

功能
API
全局消息订阅
sys.subscribe
定时器管理
sys.timerStart/Stop
定向消息发送
sysplus.sendMsg
定向消息接收
sysplus.waitMsg
任务间延时
sys.wait
具名任务创建
sysplus.taskInitEx

七、总结

  • 消息机制原理:基于消息队列和协程,发布者将消息放入队列,订阅者通过回调或协程等待并处理,支持异步事件驱动。
  • 发送消息:sys.publish() 广播消息,sysplus.sendMsg() 定向发送消息。
  • 接收消息:sys.subscribe() 订阅消息,sys.waitUntil()sys.waitMsg()阻塞等待消息,sys.unsubscribe() 取消订阅。
  • 系统消息:框架预定义多种系统事件消息,直接订阅即可响应硬件和系统事件。
  • 应用场景:网络模块通信、传感器数据广播、定时器事件处理等。

通过合理使用 LuatOS 的消息机制,可以实现高效、解耦的物联网应用架构,支持复杂的事件驱动和多任务协作