From 0a50e51916b1b37f8d46dcb92fbbdfd324418c59 Mon Sep 17 00:00:00 2001 From: Jan-Piet Mens Date: Tue, 6 Sep 2016 15:40:41 +0200 Subject: [PATCH] NEW: otr_publish() from Lua reuses Recorder's authenticated, TLS-enabled MQTT connection closes #140 --- doc/HOOKS.md | 10 ++++++++++ hooks.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ hooks.h | 8 ++++++++ recorder.c | 2 ++ 4 files changed, 65 insertions(+) diff --git a/doc/HOOKS.md b/doc/HOOKS.md index 9e589cd..c8383f4 100644 --- a/doc/HOOKS.md +++ b/doc/HOOKS.md @@ -91,3 +91,13 @@ An optional function you provide is called `otr_httpobject(u, d, t, data)` where After running `otr_hook()`, the Recorder attempts to invoke a Lua function for each of the elements in the extended JSON. If, say, your Lua script contains a function called `hooklet_lat`, it will be invoked every time a `lat` is received as part of the JSON payload. Similarly with `hooklet_addr`, `hooklet_cc`, `hooklet_tst`, etc. These _hooklets_ are invoked with the same parameters as `otr_hook()`. You define a hooklet function only if you're interested in expressly triggering on a particular JSON element. + +In addition to compiling with Lua support, if Recorder is built with MQTT support, a function `otr_publish()` is surfaced into your Lua script. + +``` +otr_publish(topic, payload, qos, retain) +``` + +`topic` and `payload` are mandatory and must be strings. `qos` and `retain` are optional and specify the QoS for publishing as well as a retain flag; `qos` must be specified if `retain` is to be. + +This function allows your code to publish via MQTT from the Recorder, using the same MQTT connection (including TLS, authentication, etc) as the Recorder uses. diff --git a/hooks.c b/hooks.c index 86b6184..bbc36a0 100644 --- a/hooks.c +++ b/hooks.c @@ -40,6 +40,11 @@ static int otr_log(lua_State *lua); static int otr_strftime(lua_State *lua); static int otr_putdb(lua_State *lua); static int otr_getdb(lua_State *lua); +#ifdef WITH_MQTT +# include +static int otr_publish(lua_State *lua); +static struct mosquitto *MQTTconn = NULL; +#endif static struct gcache *LuaDB = NULL; @@ -102,6 +107,9 @@ struct luadata *hooks_init(struct udata *ud, char *script) lua_pushcfunction(ld->L, otr_getdb); lua_setfield(ld->L, -2, "getdb"); + lua_pushcfunction(ld->L, otr_publish); + lua_setfield(ld->L, -2, "publish"); + lua_setglobal(ld->L, "otr"); LuaDB = ud->luadb; @@ -130,6 +138,13 @@ struct luadata *hooks_init(struct udata *ud, char *script) return (ld); } +#ifdef WITH_MQTT +void hooks_setmosq(struct mosquitto *mosq) +{ + MQTTconn = mosq; +} +#endif + void hooks_exit(struct luadata *ld, char *reason) { if (ld && ld->script) { @@ -448,4 +463,34 @@ static int otr_getdb(lua_State *lua) } return (rc); } + +#ifdef WITH_MQTT + +/* + * Requires two string arguments: topic, payload + * and two numeric args: qos and retain + * Will be published via MQTT to the Recorder's + * open connection. + */ + +int otr_publish(lua_State *lua) +{ + const char *topic, *payload; + int qos = 0, retain = 0; + int rc = 0; + + if (lua_gettop(lua) >= 1) { + topic = lua_tostring(lua, 1); + payload = lua_tostring(lua, 2); + qos = lua_tonumber(lua, 3); + retain = lua_tonumber(lua, 4); + + rc = mosquitto_publish(MQTTconn, NULL, topic, + strlen(payload), payload, qos, retain); + olog(LOG_DEBUG, "LUA_PUBLISH (%s, %s, %d, %d) == %d\n", topic, payload, qos, retain, rc); + } + return (rc); +} +#endif + #endif /* WITH_LUA */ diff --git a/hooks.h b/hooks.h index 285334a..f760676 100644 --- a/hooks.h +++ b/hooks.h @@ -3,6 +3,9 @@ #ifdef WITH_LUA # include +# ifdef WITH_MQTT +# include +# endif struct luadata { @@ -16,6 +19,11 @@ void hooks_hook(struct udata *ud, char *topic, JsonNode *obj); int hooks_norec(struct udata *ud, char *user, char *device, char *payload); JsonNode *hooks_http(struct udata *ud, char *user, char *device, char *payload); +#ifdef WITH_MQTT +# include +void hooks_setmosq(struct mosquitto *); +#endif + #endif /* WITH_LUA */ #endif diff --git a/recorder.c b/recorder.c index 92fc941..4865d1a 100644 --- a/recorder.c +++ b/recorder.c @@ -1621,6 +1621,8 @@ int main(int argc, char **argv) mosquitto_lib_cleanup(); return rc; } + /* Explicitly set MQTT connection for Lua's otr_publish() */ + hooks_setmosq(mosq); } else { olog(LOG_INFO, "Not using MQTT: disabled by port=0"); }