mirror of
https://github.com/m5stack/ESP-Claw.git
synced 2026-05-20 11:51:49 -07:00
feat: split lua modules
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
+9
-3
@@ -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", ×tamp_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
|
||||
)
|
||||
+2
@@ -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
|
||||
}
|
||||
+15
-9
@@ -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
|
||||
)
|
||||
+10
@@ -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
|
||||
+40
-29
@@ -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
Reference in New Issue
Block a user