summaryrefslogtreecommitdiffstats
path: root/Controler-afb
diff options
context:
space:
mode:
Diffstat (limited to 'Controler-afb')
-rw-r--r--Controler-afb/CMakeLists.txt3
-rw-r--r--Controler-afb/README.md234
-rw-r--r--Controler-afb/ctl-apidef.h71
-rw-r--r--Controler-afb/ctl-apidef.json48
-rw-r--r--Controler-afb/ctl-binding.h12
-rw-r--r--Controler-afb/ctl-dispatch.c1
-rw-r--r--Controler-afb/ctl-events.c2
-rw-r--r--Controler-afb/ctl-lua.c117
-rw-r--r--Controler-afb/ctl-misc.c122
9 files changed, 342 insertions, 268 deletions
diff --git a/Controler-afb/CMakeLists.txt b/Controler-afb/CMakeLists.txt
index 4fb97b2..78e66c8 100644
--- a/Controler-afb/CMakeLists.txt
+++ b/Controler-afb/CMakeLists.txt
@@ -33,7 +33,7 @@ endmacro(SET_TARGET_GENSKEL)
PROJECT_TARGET_ADD(control-afb)
# Define project Targets
- ADD_LIBRARY(${TARGET_NAME} MODULE ctl-binding.c ctl-events.c ctl-dispatch.c ctl-lua.c ctl-misc.c)
+ ADD_LIBRARY(${TARGET_NAME} MODULE ctl-binding.c ctl-events.c ctl-dispatch.c ctl-lua.c)
# Generate API-v2 hat from OpenAPI json definition
SET_TARGET_GENSKEL(${TARGET_NAME} ctl-apidef)
@@ -70,6 +70,7 @@ PROJECT_TARGET_ADD(audio-plugin-sample)
# Library dependencies (include updates automatically)
TARGET_LINK_LIBRARIES(${TARGET_NAME}
+ audio-common
${link_libraries}
)
diff --git a/Controler-afb/README.md b/Controler-afb/README.md
new file mode 100644
index 0000000..3274ede
--- /dev/null
+++ b/Controler-afb/README.md
@@ -0,0 +1,234 @@
+Controler AAAA(AGL Advance Audio Controler) and more.
+------------------------------------------------------------
+
+ * Object: Generic Controler to handle Policy,Small Business Logic, Glue in between components, ...
+ * Status: Release Candidate
+ * Author: Fulup Ar Foll fulup@iot.bzh
+ * Date : August-2017
+
+## Functionalities:
+ - Create an application dedicate controller from a JSON config file
+ - Each controls (eg: navigation, multimedia, ...) is a suite of actions. When all actions succeed control is granted, if one fail control acces is denied.
+ - Actions can either be:
+ + Invocation to an other binding API, either internal or external (eg: a policy service, Alsa UCM, ...)
+ + C routines from a user provider plugin (eg: policy routine, proprietary code, ...)
+ + LUA script function. LUA provides access to every AGL appfw functionalities and can be extended from C user provided plugins.
+
+## Installation
+ - Controler is a native part of AGL Advance Audio Framework but may be used independently with any other service or application binder.
+ - Dependencies: the only dependencies are audio-common for JSON-WRAP and Filescan-utils capabilities.
+ - Controler relies on LUA-5.3, when not needed LUA might be removed at compilation time.
+
+## Config
+
+Configuration is loaded dynamically during startup time. The controller scans CONTROL_CONFIG_PATH for a file corresponding to pattern
+"onload-bindername-xxxxx.json". When controller runs within AAAA binder it searches for "onload-audio-xxxx.json". First file found in the path the loaded
+any other files corresponding to the same pather are ignored and only generate a warning.
+
+Each bloc in the configuration file are defined with
+ * label: must be provided is used either for debugging or as input for the action (eg: signal name, control name, ...)
+ * info: optional used for documentation purpose only
+
+### Config is organised in 4 sections:
+
+ * metadata
+ * onload defines the set of action to be executed at startup time
+ * control defines the set of controls with corresponding actions
+ * event define the set of actions to be executed when receiving a given signal
+
+### Metadata
+
+As today matadata is only used for documentation purpose.
+ * label + version mandatory
+ * info optional
+
+### OnLoad section
+
+Defines startup time configuration. Onload may provide multiple initialisation profiles, each with a different label.
+ * label is mandatory. Label is used to select onload profile at initialisation through DispatchOneOnLoad("onload-label") API;
+ * info is optional
+ * plugin provides optional unique plugin name. Plugin should follow "onload-bindername-xxxxx.ctlso" patern
+ and are search into CONTROL_PLUGIN_PATH. When defined controller will execute user provided function context=CTLP_ONLOAD(label,version,info).
+ The context returned by this routine is provided back to any C routines call later by the controller.
+ * lua2c list of LUA commands shipped with provided plugin.
+ * require list of binding that should be initialised before the controller starts. Note that some listed requirer binding might be absent,
+ nevertheless any present binding from this list will be started before controller binding, missing ones generate a warning.
+ * action the list of action to execute during loadtime. Any failure in action will prevent controller binding from starting.
+
+### Control section
+
+Defines a list of controls that are accessible through (api="control", verb="request", control="control-label").
+
+ * label mandatory
+ * info optional
+ * privileges needed privileges to request this control
+ * action the list of actions
+
+### Event section
+
+Defines a list of actions to be executed on event reception. Even can do anything a controller can (change state,
+send back signal, ...) eg: if a controller subscribes to vehicule speed, then speed-event may ajust master-volume to speed.
+
+ * label mandatory
+ * info optional
+ * action the list of actions
+
+### Actions Categories
+
+Controler support tree categories of actions. Each action return a status status where 0=success and 1=failure.
+ * AppFw API, Provides a generic model to request other bindings. Requested binding can be local (eg: ALSA/UCM) or
+ external (eg: vehicle signalling).
+ * api provides requested binding API name
+ * verb provides verb to requested binding
+ * args optionally provides a jsonc object for targeted binding API. Note that 'args' are statically defined
+ in JSON configuration file. Controler client may also provided its own arguments from the query list. Targeted
+ binding receives both arguments defined in the config file and the argument provided by controller client.
+ * C-API, when defined in the onload section, the plugin may provided C native API with CTLP-CAPI(apiname, label, args, query, context).
+ Plugin may also create LUA command with CTLP-LUA2C(LuaFuncName, label, args, query, context). Where args+query are JSONC object
+ and context the value return from CTLP_ONLOAD function. Any missing value is set to NULL.
+ * LUA-API, when compiled with LUA option, the controller support action defined directly in LUA script. During "onload" phase the
+ controller search in CONTROL_LUA_PATH file with pattern "onload-bindername-xxxx.lua". Any file corresponding to this pattern
+ is automatically loaded. Any function defined in those LUA script can be called through a controller action. LUA functions receive
+ three parameters (label, args, query).
+
+## Config Sample
+
+Here after a simple configuration sample.
+
+```
+{
+ "$schema": "ToBeDone",
+ "metadata": {
+ "label": "sample-audio-control",
+ "info": "Provide Default Audio Policy for Multimedia, Navigation and Emergency",
+ "version": "1.0"
+ },
+ "onload": [{
+ "label": "onload-default",
+ "info": "onload initialisation config",
+ "plugin": "ctl-audio-plugin-sample.ctlso",
+ "require": ["intel-hda", "jabra-usb", "scarlett-usb"],
+ "actions": [
+ {
+ "label": "onload-sample-cb",
+ "info": "Call control sharelib install entrypoint",
+ "callback": "SamplePolicyInit",
+ "args": {
+ "arg1": "first_arg",
+ "nextarg": "second arg value"
+ }
+ }, {
+ "label": "onload-sample-api",
+ "info": "Assert AlsaCore Presence",
+ "api": "alsacore",
+ "verb": "ping",
+ "args": "test"
+ }, {
+ "label": "onload-hal-lua",
+ "info": "Load avaliable HALs",
+ "lua": "Audio_Init_Hal"
+ }
+ ]
+ }],
+ "controls":
+ [
+ {
+ "label": "multimedia",
+ "actions": {
+ "label": "multimedia-control-lua",
+ "info": "Call Lua Script function Test_Lua_Engin",
+ "lua": "Audio_Set_Multimedia"
+ }
+ }, {
+ "label": "navigation",
+ "actions": {
+ "label": "navigation-control-lua",
+ "info": "Call Lua Script to set Navigation",
+ "lua": "Audio_Set_Navigation"
+ }
+ }, {
+ "label": "emergency",
+ "actions": {
+ "label": "emergency-control-ucm",
+ "lua": "Audio_Set_Emergency"
+ }
+ }, {
+ "label": "multi-step-sample",
+ "info" : "all actions must succeed for control to be accepted",
+ "actions": [{
+ "label": "multimedia-control-cb",
+ "info": "Call Sharelib Sample Callback",
+ "callback": "sampleControlNavigation",
+ "args": {
+ "arg1": "snoopy",
+ "arg2": "toto"
+ }
+ }, {
+ "label": "navigation-control-ucm",
+ "api": "alsacore",
+ "verb": "ping",
+ "args": {
+ "test": "navigation"
+ }
+ }, {
+ "label": "navigation-control-lua",
+ "info": "Call Lua Script to set Navigation",
+ "lua": "Audio_Set_Navigation"
+ }]
+ }
+ ],
+ "events":
+ [
+ {
+ "label": "Vehicle-Speed",
+ "info": "Action when Vehicule speed change",
+ "actions": [
+ {
+ "label": "speed-action-1",
+ "callback": "Blink-when-over-130",
+ "args": {
+ "speed": 130
+ "blink-speed": 1000
+ }
+ }, {
+ "label": "Adjust-Volume",
+ "lua": "Adjust_Volume_To_Speed",
+ }
+ ]
+ },
+ {
+ "label": "Reverse-Engage",
+ "info": "When Reverse Gear is Engage",
+ "actions": [
+ {
+ "label": "Display-Rear-Camera",
+ "callback": "Display-Rear-Camera",
+ }, {
+ "label": "Prevent-Phone-Call",
+ "api" : "phone",
+ "verb" : "status",
+ "args": {
+ "call-accepted": false
+ }
+ }
+ ]
+ },
+ {
+ "label": "Neutral-Engage",
+ "info": "When Reverse Neutral is Engage",
+ "actions": [
+ {
+ "label": "Authorize-Video",
+ "api" : "video",
+ "verb" : "status",
+ "args": {
+ "tv-accepted": true
+ }
+ }
+ ]
+ }
+ ]
+}
+
+```
+
diff --git a/Controler-afb/ctl-apidef.h b/Controler-afb/ctl-apidef.h
index 1bd80f9..83b3308 100644
--- a/Controler-afb/ctl-apidef.h
+++ b/Controler-afb/ctl-apidef.h
@@ -37,35 +37,26 @@ static const char _afb_description_v2_control[] =
"name\":\"delay\",\"required\":false,\"schema\":{\"type\":\"interger\"}},"
"{\"in\":\"query\",\"name\":\"count\",\"required\":false,\"schema\":{\"ty"
"pe\":\"interger\"}}],\"responses\":{\"200\":{\"$ref\":\"#/components/res"
- "ponses/200\"}}}},\"/navigation\":{\"description\":\"Request Access to Na"
- "vigation Audio Channel.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/compo"
- "nents/x-permissions/navigation\"},\"parameters\":[{\"in\":\"query\",\"na"
- "me\":\"zone\",\"required\":false,\"schema\":{\"type\":\"string\"}}],\"re"
- "sponses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}},\"/multi"
- "media\":{\"description\":\"Request Access to Navigation Audio Channel.\""
- ",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permissions/navig"
- "ation\"},\"parameters\":[{\"in\":\"query\",\"name\":\"zone\",\"required\""
- ":false,\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"$ref"
- "\":\"#/components/responses/200\"}}}},\"/emergency\":{\"description\":\""
- "Request Access to Navigation Audio Channel.\",\"get\":{\"x-permissions\""
- ":{\"$ref\":\"#/components/x-permissions/navigation\"},\"parameters\":[{\""
- "in\":\"query\",\"name\":\"zone\",\"required\":false,\"schema\":{\"type\""
- ":\"string\"}}],\"responses\":{\"200\":{\"$ref\":\"#/components/responses"
- "/200\"}}}},\"/lua_docall\":{\"description\":\"Execute LUA string script."
- "\",\"get\":{\"x-permissions\":{\"$ref\":\"#/components/x-permissions/nav"
- "igation\"},\"parameters\":[{\"in\":\"query\",\"name\":\"func\",\"require"
- "d\":true,\"schema\":{\"type\":\"string\"}},{\"in\":\"query\",\"name\":\""
- "args\",\"required\":false,\"schema\":{\"type\":\"array\"}}],\"responses\""
- ":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}},\"/lua_dostring\""
- ":{\"description\":\"Execute LUA string script.\",\"get\":{\"x-permission"
- "s\":{\"$ref\":\"#/components/x-permissions/navigation\"},\"parameters\":"
- "[{\"in\":\"query\",\"required\":true,\"schema\":{\"type\":\"string\"}}],"
- "\"responses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}},\"/l"
- "ua_doscript\":{\"description\":\"Execute LUA string script.\",\"get\":{\""
- "x-permissions\":{\"$ref\":\"#/components/x-permissions/navigation\"},\"p"
- "arameters\":[{\"in\":\"query\",\"name\":\"filename\",\"required\":true,\""
- "schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"$ref\":\"#/co"
- "mponents/responses/200\"}}}}}}"
+ "ponses/200\"}}}},\"/select\":{\"description\":\"Request Access to Naviga"
+ "tion Audio Channel.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/component"
+ "s/x-permissions/navigation\"},\"parameters\":[{\"in\":\"query\",\"name\""
+ ":\"zone\",\"required\":false,\"schema\":{\"type\":\"string\"}}],\"respon"
+ "ses\":{\"200\":{\"$ref\":\"#/components/responses/200\"}}}},\"/lua_docal"
+ "l\":{\"description\":\"Execute LUA string script.\",\"get\":{\"x-permiss"
+ "ions\":{\"$ref\":\"#/components/x-permissions/navigation\"},\"parameters"
+ "\":[{\"in\":\"query\",\"name\":\"func\",\"required\":true,\"schema\":{\""
+ "type\":\"string\"}},{\"in\":\"query\",\"name\":\"args\",\"required\":fal"
+ "se,\"schema\":{\"type\":\"array\"}}],\"responses\":{\"200\":{\"$ref\":\""
+ "#/components/responses/200\"}}}},\"/lua_dostring\":{\"description\":\"Ex"
+ "ecute LUA string script.\",\"get\":{\"x-permissions\":{\"$ref\":\"#/comp"
+ "onents/x-permissions/navigation\"},\"parameters\":[{\"in\":\"query\",\"r"
+ "equired\":true,\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\""
+ ":{\"$ref\":\"#/components/responses/200\"}}}},\"/lua_doscript\":{\"descr"
+ "iption\":\"Execute LUA string script.\",\"get\":{\"x-permissions\":{\"$r"
+ "ef\":\"#/components/x-permissions/navigation\"},\"parameters\":[{\"in\":"
+ "\"query\",\"name\":\"filename\",\"required\":true,\"schema\":{\"type\":\""
+ "string\"}}],\"responses\":{\"200\":{\"$ref\":\"#/components/responses/20"
+ "0\"}}}}}}"
;
static const struct afb_auth _afb_auths_v2_control[] = {
@@ -74,9 +65,7 @@ static const struct afb_auth _afb_auths_v2_control[] = {
void ctlapi_monitor(struct afb_req req);
void ctlapi_event_test(struct afb_req req);
- void ctlapi_navigation(struct afb_req req);
- void ctlapi_multimedia(struct afb_req req);
- void ctlapi_emergency(struct afb_req req);
+ void ctlapi_select(struct afb_req req);
void ctlapi_lua_docall(struct afb_req req);
void ctlapi_lua_dostring(struct afb_req req);
void ctlapi_lua_doscript(struct afb_req req);
@@ -97,22 +86,8 @@ static const struct afb_verb_v2 _afb_verbs_v2_control[] = {
.session = AFB_SESSION_NONE_V2
},
{
- .verb = "navigation",
- .callback = ctlapi_navigation,
- .auth = &_afb_auths_v2_control[0],
- .info = NULL,
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "multimedia",
- .callback = ctlapi_multimedia,
- .auth = &_afb_auths_v2_control[0],
- .info = NULL,
- .session = AFB_SESSION_NONE_V2
- },
- {
- .verb = "emergency",
- .callback = ctlapi_emergency,
+ .verb = "select",
+ .callback = ctlapi_select,
.auth = &_afb_auths_v2_control[0],
.info = NULL,
.session = AFB_SESSION_NONE_V2
diff --git a/Controler-afb/ctl-apidef.json b/Controler-afb/ctl-apidef.json
index 28b8581..818dd80 100644
--- a/Controler-afb/ctl-apidef.json
+++ b/Controler-afb/ctl-apidef.json
@@ -178,53 +178,7 @@
}
}
},
- "/navigation": {
- "description": "Request Access to Navigation Audio Channel.",
- "get": {
- "x-permissions": {
- "$ref": "#/components/x-permissions/navigation"
- },
- "parameters": [
- {
- "in": "query",
- "name": "zone",
- "required": false,
- "schema": {
- "type": "string"
- }
- }
- ],
- "responses": {
- "200": {
- "$ref": "#/components/responses/200"
- }
- }
- }
- },
- "/multimedia": {
- "description": "Request Access to Navigation Audio Channel.",
- "get": {
- "x-permissions": {
- "$ref": "#/components/x-permissions/navigation"
- },
- "parameters": [
- {
- "in": "query",
- "name": "zone",
- "required": false,
- "schema": {
- "type": "string"
- }
- }
- ],
- "responses": {
- "200": {
- "$ref": "#/components/responses/200"
- }
- }
- }
- },
- "/emergency": {
+ "/select": {
"description": "Request Access to Navigation Audio Channel.",
"get": {
"x-permissions": {
diff --git a/Controler-afb/ctl-binding.h b/Controler-afb/ctl-binding.h
index 70ad0c3..a2cedbf 100644
--- a/Controler-afb/ctl-binding.h
+++ b/Controler-afb/ctl-binding.h
@@ -22,6 +22,8 @@
#define AFB_BINDING_VERSION 2
#include <afb/afb-binding.h>
#include <json-c/json.h>
+#include <filescan-utils.h>
+#include <wrap-json.h>
#ifndef PUBLIC
#define PUBLIC
@@ -41,16 +43,6 @@ typedef struct {
#define CTL_PLUGIN_REGISTER(pluglabel) CtlPluginMagicT CtlPluginMagic={.magic=CTL_PLUGIN_MAGIC,.label=pluglabel}; struct afb_binding_data_v2;
-// ctl-misc.c
-typedef enum {
- CTL_SCAN_FLAT=0,
- CTL_SCAN_RECURSIVE=1,
-} CtlScanDirModeT;
-
-PUBLIC const char *GetMidleName(const char*name);
-PUBLIC const char *GetBinderName();
-PUBLIC json_object* ScanForConfig (char* searchPath, CtlScanDirModeT mode, char *pre, char *ext);
-
// polctl-binding.c
PUBLIC int CtlBindingInit ();
diff --git a/Controler-afb/ctl-dispatch.c b/Controler-afb/ctl-dispatch.c
index 3318c8d..0594952 100644
--- a/Controler-afb/ctl-dispatch.c
+++ b/Controler-afb/ctl-dispatch.c
@@ -23,7 +23,6 @@
#include <string.h>
#include <dlfcn.h>
-#include "wrap-json.h"
#include "ctl-binding.h"
typedef void*(*DispatchPluginInstallCbT)(const char* label, const char*version, const char*info);
diff --git a/Controler-afb/ctl-events.c b/Controler-afb/ctl-events.c
index f76feca..18aac53 100644
--- a/Controler-afb/ctl-events.c
+++ b/Controler-afb/ctl-events.c
@@ -75,7 +75,7 @@ STATIC int DoSendEvent (void *context) {
else ctx->value =1;
ctlEventJ = json_object_new_object();
- json_object_object_add(ctlEventJ,"action", json_object_new_string(ctx->label));
+ json_object_object_add(ctlEventJ,"signal", json_object_new_string(ctx->label));
json_object_object_add(ctlEventJ,"value" , json_object_new_int(ctx->value));
int done = afb_event_push(afbevt, ctlEventJ);
diff --git a/Controler-afb/ctl-lua.c b/Controler-afb/ctl-lua.c
index 919230d..bf02a31 100644
--- a/Controler-afb/ctl-lua.c
+++ b/Controler-afb/ctl-lua.c
@@ -33,6 +33,7 @@
#define LUA_FIST_ARG 2 // when using luaL_newlib calllback receive libtable as 1st arg
#define LUA_MSG_MAX_LENGTH 255
+#define JSON_ERROR (json_object*)-1
static lua_State* luaState;
@@ -107,7 +108,7 @@ STATIC void LuaCtxFree (LuaAfbContextT *afbContext) {
// Push a json structure on the stack as a LUA table
STATIC int LuaPushArgument (json_object *argsJ) {
- AFB_NOTICE("LuaPushArgument argsJ=%s", json_object_get_string(argsJ));
+ //AFB_NOTICE("LuaPushArgument argsJ=%s", json_object_get_string(argsJ));
json_type jtype= json_object_get_type(argsJ);
switch (jtype) {
@@ -156,6 +157,7 @@ STATIC int LuaPushArgument (json_object *argsJ) {
}
STATIC json_object *PopOneArg (lua_State* luaState, int idx);
+
STATIC json_object *LuaTableToJson (lua_State* luaState, int index) {
int idx;
@@ -171,8 +173,8 @@ STATIC json_object *LuaTableToJson (lua_State* luaState, int index) {
snprintf(number, sizeof(number),"%d", idx);
key=number;
}
-
- json_object_object_add(tableJ, key, PopOneArg(luaState, -1));
+ json_object *argJ= PopOneArg(luaState, -1);
+ json_object_object_add(tableJ, key, argJ);
lua_pop(luaState, 1); // removes 'value'; keeps 'key' for next iteration
}
@@ -189,9 +191,16 @@ STATIC json_object *PopOneArg (lua_State* luaState, int idx) {
int luaType = lua_type(luaState, idx);
switch(luaType) {
- case LUA_TNUMBER:
- value= json_object_new_double(lua_tonumber(luaState, idx));
+ case LUA_TNUMBER: {
+ lua_Number number= lua_tonumber(luaState, idx);;
+ int nombre = (int)number; // evil trick to determine wether n fits in an integer. (stolen from ltcl.c)
+ if (number == nombre) {
+ value= json_object_new_int((int)number);
+ } else {
+ value= json_object_new_double(number);
+ }
break;
+ }
case LUA_TBOOLEAN:
value= json_object_new_boolean(lua_toboolean(luaState, idx));
break;
@@ -199,15 +208,23 @@ STATIC json_object *PopOneArg (lua_State* luaState, int idx) {
value= json_object_new_string(lua_tostring(luaState, idx));
break;
case LUA_TTABLE: {
- value= LuaTableToJson(luaState, idx);
+ if (idx > 0) {
+ value= LuaTableToJson(luaState, idx);
+ } else {
+ value= json_object_new_string("UNSUPPORTED_Lua_Nested_Table");
+ }
break;
}
+ case LUA_TNIL:
+ value=json_object_new_string("nil") ;
+ break;
+
default:
AFB_NOTICE ("PopOneArg: script returned Unknown/Unsupported idx=%d type:%d/%s", idx, luaType, lua_typename(luaState, luaType));
value=NULL;
}
- return value;
+ return value;
}
static json_object *LuaPopArgs (lua_State* luaState, int start) {
@@ -223,24 +240,28 @@ static json_object *LuaPopArgs (lua_State* luaState, int start) {
// loop on remaining return arguments
responseJ= json_object_new_array();
for (int idx=start; idx <= stop; idx++) {
- json_object_array_add(responseJ, PopOneArg (luaState, idx));
+ json_object *argJ=PopOneArg (luaState, idx);
+ if (!argJ) goto OnErrorExit;
+ json_object_array_add(responseJ, argJ);
}
}
return responseJ;
-}
+
+ OnErrorExit:
+ return NULL;
+}
-STATIC void LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) {
+
+STATIC int LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) {
char *message;
json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG);
+
if (!responseJ) {
- message="-- Empty Message ???";
- goto PrintMessage;
+ luaL_error(luaState,"LuaFormatMessage empty message");
+ goto OnErrorExit;
}
-
- //AFB_NOTICE("**** responseJ=%s", json_object_get_string(responseJ));
-
// if we have only on argument just return the value.
if (json_object_get_type(responseJ)!=json_type_array || json_object_array_length(responseJ) <2) {
@@ -290,6 +311,7 @@ STATIC void LuaFormatMessage(lua_State* luaState, LuaAfbMessageT action) {
message[targetIdx++] = format[idx];
}
}
+ message[targetIdx]='\0';
PrintMessage:
switch (action) {
@@ -309,31 +331,35 @@ PrintMessage:
default:
AFB_ERROR (message);
}
+ return 0; // nothing return to lua
+
+ OnErrorExit: // on argument to return (the error message)
+ return 1;
}
STATIC int LuaPrintInfo(lua_State* luaState) {
- LuaFormatMessage (luaState, AFB_MSG_INFO);
- return 0; // no value return
+ int err=LuaFormatMessage (luaState, AFB_MSG_INFO);
+ return err;
}
STATIC int LuaPrintError(lua_State* luaState) {
- LuaFormatMessage (luaState, AFB_MSG_ERROR);
- return 0; // no value return
+ int err=LuaFormatMessage (luaState, AFB_MSG_ERROR);
+ return err; // no value return
}
STATIC int LuaPrintWarning(lua_State* luaState) {
- LuaFormatMessage (luaState, AFB_MSG_WARNING);
- return 0; // no value return
+ int err=LuaFormatMessage (luaState, AFB_MSG_WARNING);
+ return err;
}
STATIC int LuaPrintNotice(lua_State* luaState) {
- LuaFormatMessage (luaState, AFB_MSG_NOTICE);
- return 0; // no value return
+ int err=LuaFormatMessage (luaState, AFB_MSG_NOTICE);
+ return err;
}
STATIC int LuaPrintDebug(lua_State* luaState) {
- LuaFormatMessage (luaState, AFB_MSG_DEBUG);
- return 0; // no value return
+ int err=LuaFormatMessage (luaState, AFB_MSG_DEBUG);
+ return err;
}
STATIC int LuaAfbSuccess(lua_State* luaState) {
@@ -342,6 +368,7 @@ STATIC int LuaAfbSuccess(lua_State* luaState) {
// ignore context argument
json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG+1);
+ if (responseJ == JSON_ERROR) return 1;
afb_req_success(afbContext->request, responseJ, NULL);
@@ -358,6 +385,7 @@ STATIC int LuaAfbFail(lua_State* luaState) {
if (!afbContext) goto OnErrorExit;
json_object *responseJ= LuaPopArgs(luaState, LUA_FIST_ARG+1);
+ if (responseJ == JSON_ERROR) return 1;
afb_req_fail(afbContext->request, afbContext->info, json_object_get_string(responseJ));
@@ -400,6 +428,7 @@ STATIC int LuaAfbService(lua_State* luaState) {
const char *api = lua_tostring(luaState,2);
const char *verb= lua_tostring(luaState,3);
json_object *queryJ= LuaTableToJson(luaState, 4);
+ if (queryJ == JSON_ERROR) return 1;
LuaCallServiceT *contextCB = calloc (1, sizeof(LuaCallServiceT));
contextCB->callback= lua_tostring(luaState, 5);
@@ -597,7 +626,6 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
lua_pushnil(luaState);
count++;
} else {
- AFB_NOTICE("***** args=%s", json_object_get_string(argsJ));
count+= LuaPushArgument (argsJ);
}
@@ -606,15 +634,17 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
case LUA_DOSCRIPT: { // Fulup need to fix argument passing
const char *script;
+ char*func;
+ char *filename; char*fullpath;
char luaScriptPath[CONTROL_MAXPATH_LEN];
- json_object *args;
+ json_object *argsJ;
int index;
// scan luascript search path once
static json_object *luaScriptPathJ =NULL;
if (!luaScriptPathJ) luaScriptPathJ= ScanForConfig(CONTROL_LUA_PATH , CTL_SCAN_RECURSIVE, CONTROL_DOSCRIPT_PRE, "lua");
- err= wrap_json_unpack (queryJ, "{s:s, s?o s?o !}", "script", &script,"args", &args, "arg", &args);
+ err= wrap_json_unpack (queryJ, "{s:s, s?s s?o s?o !}", "script", &script,"func", &func, "arg", &argsJ);
if (err) {
AFB_ERROR ("LUA-DOSCRIPT-SYNTAX:missing script|(args,arg) query=%s", json_object_get_string(queryJ));
goto OnErrorExit;
@@ -623,7 +653,6 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
// search for filename=script in CONTROL_LUA_PATH
for (index=0; index < json_object_array_length(luaScriptPathJ); index++) {
json_object *entryJ=json_object_array_get_idx(luaScriptPathJ, index);
- char *filename; char*fullpath;
err= wrap_json_unpack (entryJ, "{s:s, s:s !}", "fullpath", &fullpath,"filename", &filename);
if (err) {
@@ -649,15 +678,27 @@ STATIC void LuaDoAction (LuaDoActionT action, afb_req request) {
goto OnErrorExit;
}
- // push query on the stack
- if (json_object_get_type(args) != json_type_array) {
- count= LuaPushArgument (args);
- } else {
- for (int idx=0; idx<json_object_array_length(args); idx++) {
- count += LuaPushArgument (json_object_array_get_idx(args, idx));
- if (err) break;
- }
- }
+ // if no func name given try to deduct from filename
+ if (!func) func= (char*)GetMidleName(filename);
+ if (!func) {
+ AFB_ERROR ("LUA-DOSCRIPT:FAIL to deduct funcname from %s", filename);
+ goto OnErrorExit;
+ }
+
+ // load function (should exist in CONTROL_PATH_LUA
+ lua_getglobal(luaState, func);
+
+ // Push AFB client context on the stack
+ LuaAfbContextT *afbContext= LuaCtxPush(luaState, request, func);
+ if (!afbContext) goto OnErrorExit;
+
+ // push function arguments
+ if (!argsJ) {
+ lua_pushnil(luaState);
+ count++;
+ } else {
+ count+= LuaPushArgument (argsJ);
+ }
break;
}
diff --git a/Controler-afb/ctl-misc.c b/Controler-afb/ctl-misc.c
deleted file mode 100644
index 773e8f9..0000000
--- a/Controler-afb/ctl-misc.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2016 "IoT.bzh"
- * Author Fulup Ar Foll <fulup@iot.bzh>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <sys/prctl.h>
-#include <dirent.h>
-
-#include "audio-common.h"
-#include "ctl-binding.h"
-
-
-
-// List Avaliable Configuration Files
-PUBLIC json_object* ScanForConfig (char* searchPath, CtlScanDirModeT mode, char *pre, char *ext) {
- json_object *responseJ;
- char *dirPath;
- char* dirList= strdup(searchPath);
- size_t extLen=0;
-
- void ScanDir (char *searchPath) {
- DIR *dirHandle;
- struct dirent *dirEnt;
- dirHandle = opendir (searchPath);
- if (!dirHandle) {
- AFB_DEBUG ("CONFIG-SCANNING dir=%s not readable", searchPath);
- return;
- }
-
- //AFB_NOTICE ("CONFIG-SCANNING:ctl_listconfig scanning: %s", searchPath);
- while ((dirEnt = readdir(dirHandle)) != NULL) {
-
- // recursively search embedded directories ignoring any directory starting by '.' or '_'
- if (dirEnt->d_type == DT_DIR && mode == CTL_SCAN_RECURSIVE) {
- char newpath[CONTROL_MAXPATH_LEN];
- if (dirEnt->d_name[0]=='.' || dirEnt->d_name[0]=='_') continue;
-
- strncpy(newpath, searchPath, sizeof(newpath));
- strncat(newpath, "/", sizeof(newpath));
- strncat(newpath, dirEnt->d_name, sizeof(newpath));
- ScanDir(newpath);
- continue;
- }
-
- // Unknown type is accepted to support dump filesystems
- if (dirEnt->d_type == DT_REG || dirEnt->d_type == DT_UNKNOWN) {
-
- // check prefix and extention
- size_t extIdx=strlen(dirEnt->d_name)-extLen;
- if (extIdx <= 0) continue;
- if (pre && !strcasestr (dirEnt->d_name, pre)) continue;
- if (ext && strcasecmp (ext, &dirEnt->d_name[extIdx])) continue;
-
- struct json_object *pathJ = json_object_new_object();
- json_object_object_add(pathJ, "fullpath", json_object_new_string(searchPath));
- json_object_object_add(pathJ, "filename", json_object_new_string(dirEnt->d_name));
- json_object_array_add(responseJ, pathJ);
- }
- }
- closedir(dirHandle);
- }
-
- if (ext) extLen=strlen(ext);
- responseJ = json_object_new_array();
-
- // loop recursively on dir
- for (dirPath= strtok(dirList, ":"); dirPath && *dirPath; dirPath=strtok(NULL,":")) {
- ScanDir (dirPath);
- }
-
- free (dirList);
- return (responseJ);
-}
-
-PUBLIC const char *GetMidleName(const char*name) {
- char *fullname = strdup(name);
-
- for (int idx = 0; fullname[idx] != '\0'; idx++) {
- int start;
- if (fullname[idx] == '-') {
- start = idx + 1;
- for (int jdx = start; fullname[jdx] != '\0'; jdx++) {
- if (fullname[jdx] == '-') {
- fullname[jdx] = '\0';
- return &fullname[start];
- break;
- }
- }
- break;
- }
- }
- return "";
-}
-
-PUBLIC const char *GetBinderName() {
- char psName[17];
- static char *binderName=NULL;
-
- if (binderName) return binderName;
-
- // retrieve binder name from process name afb-name-trailer
- prctl(PR_GET_NAME, psName,NULL,NULL,NULL);
- binderName=GetMidleName(psName);
-
- return binderName;
-} \ No newline at end of file