# ML307C-Lua **Repository Path**: chauncyma/ML307C-Lua ## Basic Information - **Project Name**: ML307C-Lua - **Description**: ml307c 集成 lua开发环境 - **Primary Language**: C - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 1 - **Created**: 2025-08-29 - **Last Updated**: 2025-10-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: ML307C, Lua, 嵌入式 ## README # ML307C Lua 高性能脚本环境 本项目为 ML307C OpenCPU SDK 深度集成了一套强大、稳定且可用于生产的 Lua 5.3.6 脚本环境。它并非简单的解释器移植,而是一个完整的开发生态,包含了抢占式调度器、非阻塞 API 以及丰富的硬件与网络接口绑定,专门为构建复杂、可靠且支持远程更新的物联网应用而设计。 其核心设计理念是:让开发者使用上层 Lua 语言处理业务逻辑,而底层 RTOS、硬件和网络协议栈的复杂性则由高度优化的 C 模块来处理。 --- ## 核心特性 - **抢占式协程调度器**: 此环境的核心。它能有效防止任何单个 Lua 脚本(即使包含死循环)独占 CPU 而导致系统看门狗复位,从而确保了系统的稳定性和多任务并发执行能力。 - **动态脚本加载**: 支持从文件系统 (`sys.dofile`) 或字符串 (`sys.loadstring`) 加载并执行 Lua 代码。这是实现远程逻辑更新(热更新)的关键,无需进行完整的固件升级。 - **事件驱动的非阻塞 API**: 所有可能引起阻塞的操作,尤其是 `mcu.sleep` 和 `http` 客户端,都被设计为非阻塞模式。它们通过调度器挂起当前 Lua 任务,稍后在操作完成时恢复,而不会阻塞底层的 C 线程。 - **丰富的 C 接口绑定**: 提供了一系列清晰、上层的 Lua 模块,用于访问 ML307C 的核心硬件与网络功能。 --- ## 快速上手 1. **C 入口**: C 语言部分的入口函数 `lua_test_entry_start()` 负责初始化 Lua 虚拟机和调度器。 2. **主脚本**: 系统启动后,会首先从文件系统加载并执行 `/main.lua` 脚本。该脚本是所有用户业务逻辑的起点。 3. **并发任务**: 所有的应用逻辑都应通过 `sys.task(function() ... end)` 来启动。这会将一个函数注册为调度器管理的新任务,确保其与其他任务安全地并发运行。 ### `main.lua` 示例 ```lua log.info('--- Lua 主脚本已启动 ---') -- 任务1: 周期性上报信号质量 sys.task(function() while true do local _, rsrp = net.get_signal_quality() log.info('信号质量 RSRP: ', rsrp, ' dBm') mcu.sleep(30000) -- 非阻塞休眠 30 秒 end end) -- 任务2: 监听 UART1 串口指令 sys.task(function() uart.setup(1, 115200) uart.on(1, function(uart_id) local data = uart.read(uart_id, 128) log.info('从 UART1 收到数据:', data) if data == 'reboot' then mcu.reboot() end end) log.info('UART1 命令监听已启动') end) -- 任务3: 一个用于测试调度器稳定性的死循环任务 -- 由于抢占式调度器的存在,此任务不会导致系统崩溃 sys.task(function() log.info('死循环任务已启动,系统应保持稳定') while true do -- 这个循环在常规脚本环境中会导致看门狗复位, -- 但我们的调度器会周期性地强制让出 CPU。 end end) ``` --- ## API 参考 ### `sys` - 系统与调度器 - `sys.dofile(filepath)`: 从文件系统加载并执行一个 Lua 脚本。成功返回 `true`,失败返回 `false, error_message`。 - `sys.loadstring(script_string)`: 从字符串加载并执行 Lua 脚本。成功返回 `true, ...` (附带脚本返回值),失败返回 `false, error_message`。 - `sys.task(function, ...args)`: 创建一个由调度器管理的新并发任务。第一个参数必须是函数,后续参数会传递给该函数作为启动参数。 ### `log` - 日志 - `log.info(...)` - `log.warn(...)` - `log.error(...)` ### `mcu` - MCU 控制 - `mcu.reboot()`: 重启设备。 - `mcu.chip_id()`: 返回芯片的唯一 ID 字符串。 - `mcu.sleep(milliseconds)`: **非阻塞休眠**。挂起当前任务,但不会阻塞其他任务。 ### `gpio` - GPIO - `gpio.setup(pin_id, mode)`: `mode` - `0`为输出, `1`为输入。 - `gpio.write(pin_id, value)`: `value` - `0`或`1`。 - `gpio.read(pin_id)`: 返回 `0`或`1`。 ### `timer` - 定时器 - `timer.start(callback_func, interval_ms, is_periodic)`: 启动一个定时器。`is_periodic` 是布尔值,`true`代表周期执行。 ### `fs` - 文件系统 - `fs.open(filepath, mode)`: 打开文件。`mode` 可为 "rb", "wb", "ab", "rb+", "wb+", "ab+"。返回文件句柄或 `nil`。 - `file:read(bytes)`: 从文件读取数据。 - `file:write(content)`: 向文件写入数据。 - `file:close()`: 关闭文件句柄。 - `fs.remove(filepath)` - `fs.exists(filepath)` - `fs.rename(old_path, new_path)` ### `net` - 网络信息 - `net.get_signal_quality()`: 返回 `rssi, rsrp, rsrq` 三个数值。 - `net.get_reg_status()`: 返回网络注册状态码。 - `net.on_reg_change(callback_func)`: 注册网络状态变更回调。 ### `mqtt` - MQTT 客户端 - `client = mqtt.create()`: 创建一个新的 MQTT 客户端实例。 - `client:on(event, callback)`: `event` 可为 "connect", "disconnect", "message"。 - `client:connect(host, port, client_id, user, pass)`: `user` 和 `pass` 为可选参数。 - `client:publish(topic, payload, qos)` - `client:subscribe(topic, qos)` ### `uart` - 串口通信 - `uart.setup(id, baudrate, databits, parity, stopbits)` - `uart.write(id, data)` - `uart.read(id, max_bytes)` - `uart.on(id, callback_func)`: 注册串口数据接收回调。 ### `sim` - SIM 卡信息 - `sim.get_imsi()` - `sim.get_iccid()` ### `ntp` - 网络时间同步 - `ntp.sync(server, port, callback_func)`: 启动 NTP 同步。完成后将调用 `callback(is_ok, time_str)`。 ### `http` - 异步 HTTP 客户端 - `client = http.create()`: 创建一个新的 HTTP 客户端实例。 - `client:set_timeout(connect_ms, response_ms)`: 设置连接和响应超时。 - `client:on(event, callback)`: - `"done"`: 请求成功。内存响应模式为 `callback(status_code, body_string)`;文件下载模式为 `callback(status_code)`。 - `"error"`: 请求失败。`callback(error_code)`。 - `"progress"`: 下载进度。`callback(received_bytes, total_bytes)`。 - `client:request(method, url, headers, body)`: 发起请求。`headers` 是一个 table,`body` 是字符串。`headers` 和 `body` 均为可选。 - `client:download(method, url, filepath, headers, body)`: 用法同 request,但会将响应体保存到 `filepath` 指定的文件。