feat: split lua modules

This commit is contained in:
loop
2026-04-03 18:02:50 +08:00
parent 7a8cf4d9b9
commit ca1f2f9eb4
21 changed files with 656 additions and 81 deletions
+3 -1
View File
@@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS "../../components")
set(EXTRA_COMPONENT_DIRS
"../../components"
"../../lua_modules")
if(NOT DEFINED IDF_TARGET)
set(IDF_TARGET "esp32s3" CACHE STRING "ESP-IDF target")
endif()
+5 -2
View File
@@ -7,8 +7,6 @@ idf_component_register(
"basic_demo_settings.c"
"basic_demo_wifi.c"
"config_http_server.c"
"lua_module/lua_module_gpio.c"
"lua_module/lua_module_led_strip.c"
INCLUDE_DIRS
"."
REQUIRES
@@ -39,6 +37,11 @@ idf_component_register(
json
nvs_flash
wear_levelling
lua_module_delay
lua_module_event_publisher
lua_module_gpio
lua_module_led_strip
lua_module_storage
EMBED_TXTFILES
"web/index.html"
"web/styles.css"
@@ -5,18 +5,35 @@
*/
#include "basic_demo_lua_modules.h"
#include "cap_lua.h"
#include "lua_module/lua_module_gpio.h"
#include "lua_module/lua_module_led_strip.h"
#include "lua_module_delay.h"
#include "lua_module_event_publisher.h"
#include "lua_module_gpio.h"
#include "lua_module_led_strip.h"
#include "lua_module_storage.h"
esp_err_t basic_demo_lua_modules_register(void)
{
static const cap_lua_module_t s_modules[] = {
{.name = "gpio", .open_fn = luaopen_gpio},
{.name = "led_strip", .open_fn = luaopen_led_strip},
};
esp_err_t err;
return cap_lua_register_modules(s_modules,
sizeof(s_modules) / sizeof(s_modules[0]));
err = lua_module_delay_register();
if (err != ESP_OK) {
return err;
}
err = lua_module_storage_register();
if (err != ESP_OK) {
return err;
}
err = lua_module_gpio_register();
if (err != ESP_OK) {
return err;
}
err = lua_module_led_strip_register();
if (err != ESP_OK) {
return err;
}
return lua_module_event_publisher_register();
}
+1 -3
View File
@@ -3,17 +3,15 @@ idf_component_register(
"src/cap_lua.c"
"src/cap_lua_runtime.c"
"src/cap_lua_async.c"
"src/cap_lua_module_delay.c"
"src/cap_lua_storage.c"
"src/cmd_cap_lua.c"
INCLUDE_DIRS
"include"
"src"
REQUIRES
claw_cap
console
esp_timer
freertos
georgik__lua
json
console
)
-14
View File
@@ -879,20 +879,6 @@ esp_err_t cap_lua_register_modules(const cap_lua_module_t *modules, size_t count
esp_err_t cap_lua_register_builtin_modules(void)
{
static const cap_lua_module_t builtin_modules[] = {
{.name = "delay", .open_fn = luaopen_delay},
{.name = "storage", .open_fn = luaopen_storage},
};
if (s_builtin_modules_registered) {
return ESP_OK;
}
ESP_RETURN_ON_ERROR(cap_lua_register_modules(builtin_modules,
sizeof(builtin_modules) /
sizeof(builtin_modules[0])),
TAG,
"Failed to register builtin Lua modules");
s_builtin_modules_registered = true;
return ESP_OK;
}
@@ -64,6 +64,3 @@ esp_err_t cap_lua_async_list_jobs(const char *status_filter,
esp_err_t cap_lua_async_get_job(const char *job_id,
char *output,
size_t output_size);
int luaopen_delay(lua_State *L);
int luaopen_storage(lua_State *L);
@@ -0,0 +1,9 @@
idf_component_register(
SRCS
"src/lua_module_delay.c"
INCLUDE_DIRS
"include"
REQUIRES
cap_lua
freertos
)
@@ -0,0 +1,20 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#include "lua.h"
#ifdef __cplusplus
extern "C" {
#endif
int luaopen_delay(lua_State *L);
esp_err_t lua_module_delay_register(void);
#ifdef __cplusplus
}
#endif
@@ -3,15 +3,16 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "cap_lua_internal.h"
#include "lua_module_delay.h"
#include <stdint.h>
#include "cap_lua.h"
#include "lauxlib.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
static int cap_lua_delay_ms(lua_State *L)
static int lua_module_delay_sleep_ms(lua_State *L)
{
lua_Integer ms = luaL_checkinteger(L, 1);
@@ -26,7 +27,12 @@ static int cap_lua_delay_ms(lua_State *L)
int luaopen_delay(lua_State *L)
{
lua_newtable(L);
lua_pushcfunction(L, cap_lua_delay_ms);
lua_pushcfunction(L, lua_module_delay_sleep_ms);
lua_setfield(L, -2, "delay_ms");
return 1;
}
esp_err_t lua_module_delay_register(void)
{
return cap_lua_register_module("delay", luaopen_delay);
}
@@ -0,0 +1,11 @@
idf_component_register(
SRCS
"src/lua_module_event_publisher.c"
INCLUDE_DIRS
"include"
REQUIRES
cap_lua
claw_event_router
esp_timer
json
)
@@ -0,0 +1,20 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#include "lua.h"
#ifdef __cplusplus
extern "C" {
#endif
int luaopen_event_publisher(lua_State *L);
esp_err_t lua_module_event_publisher_register(void);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,425 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "lua_module_event_publisher.h"
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cJSON.h"
#include "claw_event_router.h"
#include "esp_err.h"
#include "esp_timer.h"
#include "lauxlib.h"
#include "cap_lua.h"
static const char *LUA_MODULE_EVENT_PUBLISHER_NAME = "event_publisher";
static const char *lua_table_get_string_field(lua_State *L,
int index,
const char *field_name,
bool required)
{
const char *value = NULL;
int type;
lua_getfield(L, index, field_name);
type = lua_type(L, -1);
if (type == LUA_TNIL) {
lua_pop(L, 1);
if (required) {
luaL_error(L, "missing required field '%s'", field_name);
}
return NULL;
}
if (type != LUA_TSTRING) {
lua_pop(L, 1);
luaL_error(L, "field '%s' must be a string", field_name);
}
value = lua_tostring(L, -1);
lua_pop(L, 1);
return value;
}
static bool lua_table_get_integer_field(lua_State *L,
int index,
const char *field_name,
int64_t *out_value)
{
int is_num = 0;
lua_getfield(L, index, field_name);
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
return false;
}
*out_value = (int64_t)lua_tointegerx(L, -1, &is_num);
lua_pop(L, 1);
if (!is_num) {
luaL_error(L, "field '%s' must be an integer", field_name);
}
return true;
}
static cJSON *lua_module_event_publisher_json_from_value(lua_State *L, int index);
static bool lua_module_event_publisher_table_is_array(lua_State *L, int index)
{
lua_Integer expected = 1;
bool has_entries = false;
index = lua_absindex(L, index);
lua_pushnil(L);
while (lua_next(L, index) != 0) {
if (!lua_isinteger(L, -2) || lua_tointeger(L, -2) != expected) {
lua_pop(L, 2);
return false;
}
has_entries = true;
expected++;
lua_pop(L, 1);
}
return has_entries;
}
static cJSON *lua_module_event_publisher_json_from_table(lua_State *L, int index)
{
cJSON *json = NULL;
index = lua_absindex(L, index);
if (lua_module_event_publisher_table_is_array(L, index)) {
json = cJSON_CreateArray();
lua_pushnil(L);
while (lua_next(L, index) != 0) {
cJSON *child = lua_module_event_publisher_json_from_value(L, -1);
lua_pop(L, 1);
if (!child || !cJSON_AddItemToArray(json, child)) {
cJSON_Delete(child);
cJSON_Delete(json);
return NULL;
}
}
return json;
}
json = cJSON_CreateObject();
lua_pushnil(L);
while (lua_next(L, index) != 0) {
const char *key = NULL;
char key_buf[32];
cJSON *child = NULL;
if (lua_type(L, -2) == LUA_TSTRING) {
key = lua_tostring(L, -2);
} else if (lua_isinteger(L, -2)) {
snprintf(key_buf, sizeof(key_buf), "%" PRId64, (int64_t)lua_tointeger(L, -2));
key = key_buf;
} else {
lua_pop(L, 2);
cJSON_Delete(json);
return NULL;
}
child = lua_module_event_publisher_json_from_value(L, -1);
lua_pop(L, 1);
if (!child || !cJSON_AddItemToObject(json, key, child)) {
cJSON_Delete(child);
cJSON_Delete(json);
return NULL;
}
}
return json;
}
static cJSON *lua_module_event_publisher_json_from_value(lua_State *L, int index)
{
index = lua_absindex(L, index);
switch (lua_type(L, index)) {
case LUA_TNIL:
return cJSON_CreateNull();
case LUA_TBOOLEAN:
return cJSON_CreateBool(lua_toboolean(L, index));
case LUA_TNUMBER:
return cJSON_CreateNumber(lua_tonumber(L, index));
case LUA_TSTRING:
return cJSON_CreateString(lua_tostring(L, index));
case LUA_TTABLE:
return lua_module_event_publisher_json_from_table(L, index);
default:
return NULL;
}
}
static char *lua_table_get_payload_json_field(lua_State *L, int index, bool default_empty_object)
{
char *payload_json = NULL;
cJSON *json = NULL;
lua_getfield(L, index, "payload_json");
if (!lua_isnil(L, -1)) {
if (!lua_isstring(L, -1)) {
lua_pop(L, 1);
luaL_error(L, "field 'payload_json' must be a string");
}
payload_json = strdup(lua_tostring(L, -1));
lua_pop(L, 1);
if (!payload_json) {
luaL_error(L, "out of memory");
}
return payload_json;
}
lua_pop(L, 1);
lua_getfield(L, index, "payload");
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
if (!default_empty_object) {
return NULL;
}
payload_json = strdup("{}");
if (!payload_json) {
luaL_error(L, "out of memory");
}
return payload_json;
}
if (!lua_istable(L, -1)) {
lua_pop(L, 1);
luaL_error(L, "field 'payload' must be a table");
}
json = lua_module_event_publisher_json_from_value(L, -1);
lua_pop(L, 1);
if (!json) {
luaL_error(L, "failed to convert 'payload' to JSON");
}
payload_json = cJSON_PrintUnformatted(json);
cJSON_Delete(json);
if (!payload_json) {
luaL_error(L, "failed to serialize 'payload' as JSON");
}
return payload_json;
}
static claw_event_session_policy_t lua_module_event_publisher_parse_session_policy(lua_State *L,
int index,
bool *has_value)
{
const char *policy = NULL;
*has_value = false;
lua_getfield(L, index, "session_policy");
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
return CLAW_EVENT_SESSION_POLICY_CHAT;
}
if (!lua_isstring(L, -1)) {
lua_pop(L, 1);
luaL_error(L, "field 'session_policy' must be a string");
}
*has_value = true;
policy = lua_tostring(L, -1);
lua_pop(L, 1);
if (strcmp(policy, "chat") == 0) {
return CLAW_EVENT_SESSION_POLICY_CHAT;
}
if (strcmp(policy, "trigger") == 0) {
return CLAW_EVENT_SESSION_POLICY_TRIGGER;
}
if (strcmp(policy, "global") == 0) {
return CLAW_EVENT_SESSION_POLICY_GLOBAL;
}
if (strcmp(policy, "ephemeral") == 0) {
return CLAW_EVENT_SESSION_POLICY_EPHEMERAL;
}
if (strcmp(policy, "nosave") == 0) {
return CLAW_EVENT_SESSION_POLICY_NOSAVE;
}
luaL_error(L, "invalid session_policy '%s'", policy);
return CLAW_EVENT_SESSION_POLICY_CHAT;
}
static void lua_module_event_publisher_copy_field(char *dst,
size_t dst_size,
const char *value)
{
if (value) {
strlcpy(dst, value, dst_size);
}
}
static void lua_module_event_publisher_raise_publish_error(lua_State *L, esp_err_t err)
{
luaL_error(L, "event publish failed: %s", esp_err_to_name(err));
}
static int lua_event_publisher_publish_message(lua_State *L)
{
const char *source_cap = NULL;
const char *channel = NULL;
const char *chat_id = NULL;
const char *text = NULL;
const char *sender_id = NULL;
const char *message_id = NULL;
esp_err_t err;
luaL_checktype(L, 1, LUA_TTABLE);
source_cap = lua_table_get_string_field(L, 1, "source_cap", true);
channel = lua_table_get_string_field(L, 1, "channel", true);
chat_id = lua_table_get_string_field(L, 1, "chat_id", true);
text = lua_table_get_string_field(L, 1, "text", true);
sender_id = lua_table_get_string_field(L, 1, "sender_id", false);
message_id = lua_table_get_string_field(L, 1, "message_id", false);
err = claw_event_router_publish_message(source_cap,
channel,
chat_id,
text,
sender_id,
message_id);
if (err != ESP_OK) {
lua_module_event_publisher_raise_publish_error(L, err);
}
lua_pushboolean(L, 1);
return 1;
}
static int lua_event_publisher_publish_trigger(lua_State *L)
{
const char *source_cap = NULL;
const char *event_type = NULL;
const char *event_key = NULL;
char *payload_json = NULL;
esp_err_t err;
luaL_checktype(L, 1, LUA_TTABLE);
source_cap = lua_table_get_string_field(L, 1, "source_cap", true);
event_type = lua_table_get_string_field(L, 1, "event_type", true);
event_key = lua_table_get_string_field(L, 1, "event_key", true);
payload_json = lua_table_get_payload_json_field(L, 1, true);
err = claw_event_router_publish_trigger(source_cap,
event_type,
event_key,
payload_json);
free(payload_json);
if (err != ESP_OK) {
lua_module_event_publisher_raise_publish_error(L, err);
}
lua_pushboolean(L, 1);
return 1;
}
static int lua_event_publisher_publish(lua_State *L)
{
claw_event_t event = {0};
const char *event_id = NULL;
const char *source_cap = NULL;
const char *event_type = NULL;
const char *source_channel = NULL;
const char *target_channel = NULL;
const char *source_endpoint = NULL;
const char *target_endpoint = NULL;
const char *chat_id = NULL;
const char *sender_id = NULL;
const char *message_id = NULL;
const char *correlation_id = NULL;
const char *content_type = NULL;
const char *text = NULL;
char *payload_json = NULL;
int64_t timestamp_ms = 0;
bool has_timestamp = false;
bool has_policy = false;
esp_err_t err;
luaL_checktype(L, 1, LUA_TTABLE);
source_cap = lua_table_get_string_field(L, 1, "source_cap", true);
event_type = lua_table_get_string_field(L, 1, "event_type", true);
event_id = lua_table_get_string_field(L, 1, "event_id", false);
source_channel = lua_table_get_string_field(L, 1, "source_channel", false);
target_channel = lua_table_get_string_field(L, 1, "target_channel", false);
source_endpoint = lua_table_get_string_field(L, 1, "source_endpoint", false);
target_endpoint = lua_table_get_string_field(L, 1, "target_endpoint", false);
chat_id = lua_table_get_string_field(L, 1, "chat_id", false);
sender_id = lua_table_get_string_field(L, 1, "sender_id", false);
message_id = lua_table_get_string_field(L, 1, "message_id", false);
correlation_id = lua_table_get_string_field(L, 1, "correlation_id", false);
content_type = lua_table_get_string_field(L, 1, "content_type", false);
text = lua_table_get_string_field(L, 1, "text", false);
payload_json = lua_table_get_payload_json_field(L, 1, false);
has_timestamp = lua_table_get_integer_field(L, 1, "timestamp_ms", &timestamp_ms);
lua_module_event_publisher_copy_field(event.source_cap, sizeof(event.source_cap), source_cap);
lua_module_event_publisher_copy_field(event.event_type, sizeof(event.event_type), event_type);
lua_module_event_publisher_copy_field(event.source_channel, sizeof(event.source_channel), source_channel);
lua_module_event_publisher_copy_field(event.target_channel, sizeof(event.target_channel), target_channel);
lua_module_event_publisher_copy_field(event.source_endpoint, sizeof(event.source_endpoint), source_endpoint);
lua_module_event_publisher_copy_field(event.target_endpoint, sizeof(event.target_endpoint), target_endpoint);
lua_module_event_publisher_copy_field(event.chat_id, sizeof(event.chat_id), chat_id);
lua_module_event_publisher_copy_field(event.sender_id, sizeof(event.sender_id), sender_id);
lua_module_event_publisher_copy_field(event.message_id, sizeof(event.message_id), message_id);
lua_module_event_publisher_copy_field(event.correlation_id, sizeof(event.correlation_id), correlation_id);
lua_module_event_publisher_copy_field(event.content_type, sizeof(event.content_type), content_type);
if (event_id) {
lua_module_event_publisher_copy_field(event.event_id, sizeof(event.event_id), event_id);
} else {
snprintf(event.event_id, sizeof(event.event_id), "lua-%" PRId64, esp_timer_get_time() / 1000);
}
event.timestamp_ms = has_timestamp ? timestamp_ms : (esp_timer_get_time() / 1000);
event.session_policy = lua_module_event_publisher_parse_session_policy(L, 1, &has_policy);
if (!has_policy && strcmp(event_type, "trigger") == 0) {
event.session_policy = CLAW_EVENT_SESSION_POLICY_TRIGGER;
}
event.text = (char *)text;
event.payload_json = payload_json;
err = claw_event_router_publish(&event);
free(payload_json);
if (err != ESP_OK) {
lua_module_event_publisher_raise_publish_error(L, err);
}
lua_pushboolean(L, 1);
return 1;
}
int luaopen_event_publisher(lua_State *L)
{
lua_newtable(L);
lua_pushcfunction(L, lua_event_publisher_publish);
lua_setfield(L, -2, "publish");
lua_pushcfunction(L, lua_event_publisher_publish_message);
lua_setfield(L, -2, "publish_message");
lua_pushcfunction(L, lua_event_publisher_publish_trigger);
lua_setfield(L, -2, "publish_trigger");
return 1;
}
esp_err_t lua_module_event_publisher_register(void)
{
return cap_lua_register_module(LUA_MODULE_EVENT_PUBLISHER_NAME,
luaopen_event_publisher);
}
@@ -0,0 +1,9 @@
idf_component_register(
SRCS
"src/lua_module_gpio.c"
INCLUDE_DIRS
"include"
REQUIRES
cap_lua
driver
)
@@ -5,6 +5,7 @@
*/
#pragma once
#include "esp_err.h"
#include "lua.h"
#ifdef __cplusplus
@@ -12,6 +13,7 @@ extern "C" {
#endif
int luaopen_gpio(lua_State *L);
esp_err_t lua_module_gpio_register(void);
#ifdef __cplusplus
}
@@ -3,15 +3,16 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "lua_module/lua_module_gpio.h"
#include "lua_module_gpio.h"
#include <string.h>
#include "cap_lua.h"
#include "driver/gpio.h"
#include "esp_err.h"
#include "lauxlib.h"
static gpio_mode_t gpio_mode_from_string(const char *mode)
static gpio_mode_t lua_module_gpio_mode_from_string(const char *mode)
{
if (!mode || strcmp(mode, "input") == 0) {
return GPIO_MODE_INPUT;
@@ -31,11 +32,11 @@ static gpio_mode_t gpio_mode_from_string(const char *mode)
return GPIO_MODE_DISABLE;
}
static int lua_gpio_set_direction(lua_State *L)
static int lua_module_gpio_set_direction(lua_State *L)
{
gpio_num_t pin = (gpio_num_t)luaL_checkinteger(L, 1);
const char *mode_str = luaL_checkstring(L, 2);
gpio_mode_t mode = gpio_mode_from_string(mode_str);
gpio_mode_t mode = lua_module_gpio_mode_from_string(mode_str);
if (mode == GPIO_MODE_DISABLE && strcmp(mode_str, "disable") != 0) {
return luaL_error(L, "invalid gpio mode: %s", mode_str);
@@ -48,7 +49,7 @@ static int lua_gpio_set_direction(lua_State *L)
return 0;
}
static int lua_gpio_set_level(lua_State *L)
static int lua_module_gpio_set_level(lua_State *L)
{
gpio_num_t pin = (gpio_num_t)luaL_checkinteger(L, 1);
uint32_t level = (uint32_t)luaL_checkinteger(L, 2);
@@ -60,7 +61,7 @@ static int lua_gpio_set_level(lua_State *L)
return 0;
}
static int lua_gpio_get_level(lua_State *L)
static int lua_module_gpio_get_level(lua_State *L)
{
gpio_num_t pin = (gpio_num_t)luaL_checkinteger(L, 1);
@@ -71,11 +72,16 @@ static int lua_gpio_get_level(lua_State *L)
int luaopen_gpio(lua_State *L)
{
lua_newtable(L);
lua_pushcfunction(L, lua_gpio_set_direction);
lua_pushcfunction(L, lua_module_gpio_set_direction);
lua_setfield(L, -2, "set_direction");
lua_pushcfunction(L, lua_gpio_set_level);
lua_pushcfunction(L, lua_module_gpio_set_level);
lua_setfield(L, -2, "set_level");
lua_pushcfunction(L, lua_gpio_get_level);
lua_pushcfunction(L, lua_module_gpio_get_level);
lua_setfield(L, -2, "get_level");
return 1;
}
esp_err_t lua_module_gpio_register(void)
{
return cap_lua_register_module("gpio", luaopen_gpio);
}
@@ -0,0 +1,9 @@
idf_component_register(
SRCS
"src/lua_module_led_strip.c"
INCLUDE_DIRS
"include"
REQUIRES
cap_lua
espressif__led_strip
)
@@ -5,6 +5,16 @@
*/
#pragma once
#include "esp_err.h"
#include "lua.h"
#ifdef __cplusplus
extern "C" {
#endif
int luaopen_led_strip(lua_State *L);
esp_err_t lua_module_led_strip_register(void);
#ifdef __cplusplus
}
#endif
@@ -5,32 +5,34 @@
*/
#include "lua_module_led_strip.h"
#include <string.h>
#include "cap_lua.h"
#include "esp_err.h"
#include "lauxlib.h"
#include "led_strip.h"
#include "led_strip_rmt.h"
#include "led_strip_types.h"
#define LUA_LED_STRIP_METATABLE "led_strip"
#define LUA_LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000)
#define LUA_MODULE_LED_STRIP_METATABLE "led_strip"
#define LUA_MODULE_LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000)
typedef struct {
led_strip_handle_t strip;
} lua_led_strip_ud_t;
} lua_module_led_strip_ud_t;
static lua_led_strip_ud_t *lua_led_strip_get_ud(lua_State *L, int idx)
static lua_module_led_strip_ud_t *lua_module_led_strip_get_ud(lua_State *L, int idx)
{
lua_led_strip_ud_t *ud = (lua_led_strip_ud_t *)luaL_checkudata(L, idx, LUA_LED_STRIP_METATABLE);
lua_module_led_strip_ud_t *ud =
(lua_module_led_strip_ud_t *)luaL_checkudata(L, idx, LUA_MODULE_LED_STRIP_METATABLE);
if (!ud || !ud->strip) {
luaL_error(L, "led_strip: invalid or closed handle");
}
return ud;
}
static int lua_led_strip_gc(lua_State *L)
static int lua_module_led_strip_gc(lua_State *L)
{
lua_led_strip_ud_t *ud = (lua_led_strip_ud_t *)luaL_testudata(L, 1, LUA_LED_STRIP_METATABLE);
lua_module_led_strip_ud_t *ud =
(lua_module_led_strip_ud_t *)luaL_testudata(L, 1, LUA_MODULE_LED_STRIP_METATABLE);
if (ud && ud->strip) {
led_strip_del(ud->strip);
ud->strip = NULL;
@@ -38,9 +40,9 @@ static int lua_led_strip_gc(lua_State *L)
return 0;
}
static int lua_led_strip_set_pixel(lua_State *L)
static int lua_module_led_strip_set_pixel(lua_State *L)
{
lua_led_strip_ud_t *ud = lua_led_strip_get_ud(L, 1);
lua_module_led_strip_ud_t *ud = lua_module_led_strip_get_ud(L, 1);
uint32_t index = (uint32_t)luaL_checkinteger(L, 2);
uint32_t r = (uint32_t)luaL_checkinteger(L, 3);
uint32_t g = (uint32_t)luaL_checkinteger(L, 4);
@@ -52,9 +54,9 @@ static int lua_led_strip_set_pixel(lua_State *L)
return 0;
}
static int lua_led_strip_refresh(lua_State *L)
static int lua_module_led_strip_refresh(lua_State *L)
{
lua_led_strip_ud_t *ud = lua_led_strip_get_ud(L, 1);
lua_module_led_strip_ud_t *ud = lua_module_led_strip_get_ud(L, 1);
esp_err_t err = led_strip_refresh(ud->strip);
if (err != ESP_OK) {
return luaL_error(L, "led_strip refresh failed: %s", esp_err_to_name(err));
@@ -62,9 +64,9 @@ static int lua_led_strip_refresh(lua_State *L)
return 0;
}
static int lua_led_strip_clear(lua_State *L)
static int lua_module_led_strip_clear(lua_State *L)
{
lua_led_strip_ud_t *ud = lua_led_strip_get_ud(L, 1);
lua_module_led_strip_ud_t *ud = lua_module_led_strip_get_ud(L, 1);
esp_err_t err = led_strip_clear(ud->strip);
if (err != ESP_OK) {
return luaL_error(L, "led_strip clear failed: %s", esp_err_to_name(err));
@@ -72,9 +74,10 @@ static int lua_led_strip_clear(lua_State *L)
return 0;
}
static int lua_led_strip_close(lua_State *L)
static int lua_module_led_strip_close(lua_State *L)
{
lua_led_strip_ud_t *ud = (lua_led_strip_ud_t *)luaL_checkudata(L, 1, LUA_LED_STRIP_METATABLE);
lua_module_led_strip_ud_t *ud =
(lua_module_led_strip_ud_t *)luaL_checkudata(L, 1, LUA_MODULE_LED_STRIP_METATABLE);
if (ud->strip) {
led_strip_del(ud->strip);
ud->strip = NULL;
@@ -82,10 +85,13 @@ static int lua_led_strip_close(lua_State *L)
return 0;
}
static int lua_led_strip_new(lua_State *L)
static int lua_module_led_strip_new(lua_State *L)
{
int gpio = (int)luaL_checkinteger(L, 1);
int max_leds = (int)luaL_checkinteger(L, 2);
led_strip_handle_t strip = NULL;
esp_err_t err;
if (max_leds <= 0) {
return luaL_error(L, "max_leds must be positive");
}
@@ -101,46 +107,51 @@ static int lua_led_strip_new(lua_State *L)
};
led_strip_rmt_config_t rmt_config = {
.clk_src = RMT_CLK_SRC_DEFAULT,
.resolution_hz = LUA_LED_STRIP_RMT_RES_HZ,
.resolution_hz = LUA_MODULE_LED_STRIP_RMT_RES_HZ,
.mem_block_symbols = 0,
.flags = {
.with_dma = 0,
}
};
led_strip_handle_t strip = NULL;
esp_err_t err = led_strip_new_rmt_device(&strip_config, &rmt_config, &strip);
err = led_strip_new_rmt_device(&strip_config, &rmt_config, &strip);
if (err != ESP_OK) {
return luaL_error(L, "led_strip new failed: %s", esp_err_to_name(err));
}
lua_led_strip_ud_t *ud = (lua_led_strip_ud_t *)lua_newuserdata(L, sizeof(*ud));
lua_module_led_strip_ud_t *ud =
(lua_module_led_strip_ud_t *)lua_newuserdata(L, sizeof(*ud));
ud->strip = strip;
luaL_getmetatable(L, LUA_LED_STRIP_METATABLE);
luaL_getmetatable(L, LUA_MODULE_LED_STRIP_METATABLE);
lua_setmetatable(L, -2);
return 1;
}
int luaopen_led_strip(lua_State *L)
{
if (luaL_newmetatable(L, LUA_LED_STRIP_METATABLE)) {
lua_pushcfunction(L, lua_led_strip_gc);
if (luaL_newmetatable(L, LUA_MODULE_LED_STRIP_METATABLE)) {
lua_pushcfunction(L, lua_module_led_strip_gc);
lua_setfield(L, -2, "__gc");
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lua_led_strip_set_pixel);
lua_pushcfunction(L, lua_module_led_strip_set_pixel);
lua_setfield(L, -2, "set_pixel");
lua_pushcfunction(L, lua_led_strip_refresh);
lua_pushcfunction(L, lua_module_led_strip_refresh);
lua_setfield(L, -2, "refresh");
lua_pushcfunction(L, lua_led_strip_clear);
lua_pushcfunction(L, lua_module_led_strip_clear);
lua_setfield(L, -2, "clear");
lua_pushcfunction(L, lua_led_strip_close);
lua_pushcfunction(L, lua_module_led_strip_close);
lua_setfield(L, -2, "close");
}
lua_pop(L, 1);
lua_newtable(L);
lua_pushcfunction(L, lua_led_strip_new);
lua_pushcfunction(L, lua_module_led_strip_new);
lua_setfield(L, -2, "new");
return 1;
}
esp_err_t lua_module_led_strip_register(void)
{
return cap_lua_register_module("led_strip", luaopen_led_strip);
}
@@ -0,0 +1,8 @@
idf_component_register(
SRCS
"src/lua_module_storage.c"
INCLUDE_DIRS
"include"
REQUIRES
cap_lua
)
@@ -0,0 +1,20 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "esp_err.h"
#include "lua.h"
#ifdef __cplusplus
extern "C" {
#endif
int luaopen_storage(lua_State *L);
esp_err_t lua_module_storage_register(void);
#ifdef __cplusplus
}
#endif

Some files were not shown because too many files have changed in this diff Show More