2 * Copyright (c) 2012, Intel Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of Intel Corporation nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include <murphy/common.h>
31 #include <murphy/core.h>
32 #include <murphy/common/dbus.h>
34 #include <murphy-db/mdb.h>
35 #include <murphy-db/mqi.h>
36 #include <murphy-db/mql.h>
38 #include <murphy/core/lua-bindings/murphy.h>
39 #include <murphy/core/lua-utils/object.h>
40 #include <murphy/core/lua-utils/funcbridge.h>
41 #include <murphy/core/lua-decision/mdb.h>
48 #define AMB_NAME "name"
49 #define AMB_HANDLER "handler"
50 #define AMB_DBUS_DATA "dbus_data"
51 #define AMB_OBJECT "obj"
52 #define AMB_INTERFACE "interface"
53 #define AMB_MEMBER "property"
54 #define AMB_SIGNATURE "signature"
55 #define AMB_BASIC_TABLE_NAME "basic_table_name"
56 #define AMB_OUTPUTS "outputs"
61 signal sender=:1.117 -> dest=(null destination) serial=961
62 path=/org/automotive/runningstatus/vehicleSpeed;
63 interface=org.automotive.vehicleSpeed;
68 dbus-send --system --print-reply --dest=org.automotive.message.broker \
69 /org/automotive/runningstatus/vehicleSpeed \
70 org.freedesktop.DBus.Properties.Get \
71 string:'org.automotive.vehicleSpeed' string:'VehicleSpeed'
73 method return sender=:1.69 -> dest=:1.91 reply_serial=2
87 } dbus_basic_property_t;
89 typedef void (*property_updated_cb_t)(dbus_basic_property_t *property,
100 const char *basic_table_name;
103 } lua_amb_property_t;
107 const char *amb_addr;
108 const char *config_file;
110 mrp_list_hook_t lua_properties;
114 mqi_column_def_t defs[4];
116 mql_statement_t *update_operation;
117 mqi_data_type_t type;
119 } basic_table_data_t;
122 dbus_basic_property_t prop;
124 property_updated_cb_t cb;
127 lua_amb_property_t *lua_prop;
129 /* for basic tables that we manage ourselves */
130 basic_table_data_t *tdata;
132 mrp_list_hook_t hook;
134 } dbus_property_watch_t;
136 static data_t *global_ctx = NULL;
138 static basic_table_data_t *create_basic_property_table(const char *table_name,
139 const char *member, int type);
141 static int subscribe_property(data_t *ctx, dbus_property_watch_t *w);
143 static void basic_property_updated(dbus_basic_property_t *prop, void *userdata);
148 static int amb_constructor(lua_State *L);
149 static int amb_setfield(lua_State *L);
150 static int amb_getfield(lua_State *L);
151 static void lua_amb_destroy(void *data);
153 #define PROPERTY_CLASS MRP_LUA_CLASS(amb, property)
155 MRP_LUA_METHOD_LIST_TABLE (
156 amb_methods, /* methodlist name */
157 MRP_LUA_METHOD_CONSTRUCTOR (amb_constructor)
160 MRP_LUA_METHOD_LIST_TABLE (
161 amb_overrides, /* methodlist name */
162 MRP_LUA_OVERRIDE_CALL (amb_constructor)
163 MRP_LUA_OVERRIDE_GETFIELD (amb_getfield)
164 MRP_LUA_OVERRIDE_SETFIELD (amb_setfield)
168 amb, /* main class name */
169 property, /* constructor name */
170 lua_amb_property_t, /* userdata type */
171 lua_amb_destroy, /* userdata destructor */
172 amb_methods, /* class methods */
173 amb_overrides /* class overrides */
178 static void lua_amb_destroy(void *data)
180 lua_amb_property_t *prop = (lua_amb_property_t *)data;
184 mrp_log_info("> lua_amb_destroy");
192 static void destroy_prop(data_t *ctx, dbus_property_watch_t *w)
201 static int amb_constructor(lua_State *L)
203 lua_amb_property_t *prop;
204 size_t field_name_len;
205 const char *field_name;
206 data_t *ctx = global_ctx;
207 dbus_property_watch_t *w;
211 mrp_log_info("> amb_constructor, stack size: %d", lua_gettop(L));
213 prop = mrp_lua_create_object(L, PROPERTY_CLASS, NULL);
215 prop->handler_ref = LUA_NOREF;
216 prop->outputs_ref = LUA_NOREF;
218 MRP_LUA_FOREACH_FIELD(L, 2, field_name, field_name_len) {
219 char buf[field_name_len+1];
221 strncpy(buf, field_name, field_name_len);
222 buf[field_name_len] = '\0';
224 mrp_log_info("field name: %s", buf);
226 if (strncmp(field_name, "dbus_data", field_name_len) == 0) {
228 luaL_checktype(L, -1, LUA_TTABLE);
232 while (lua_next(L, -2)) {
237 luaL_checktype(L, -2, LUA_TSTRING);
238 luaL_checktype(L, -1, LUA_TSTRING);
240 key = lua_tostring(L, -2);
241 value = lua_tostring(L, -1);
243 mrp_log_info("%s -> %s", key, value);
248 if (strcmp(key, "signature") == 0) {
249 prop->dbus_data.sig = mrp_strdup(value);
251 else if (strcmp(key, "property") == 0) {
252 prop->dbus_data.name = mrp_strdup(value);
254 else if (strcmp(key, "obj") == 0) {
255 prop->dbus_data.obj = mrp_strdup(value);
257 else if (strcmp(key, "interface") == 0) {
258 prop->dbus_data.iface = mrp_strdup(value);
267 /* check that we have all necessary data */
268 if (prop->dbus_data.sig == NULL ||
269 prop->dbus_data.iface == NULL ||
270 prop->dbus_data.obj == NULL ||
271 prop->dbus_data.name == NULL) {
275 else if (strncmp(field_name, "handler", field_name_len) == 0) {
276 luaL_checktype(L, -1, LUA_TFUNCTION);
277 prop->handler_ref = luaL_ref(L, LUA_REGISTRYINDEX);
278 lua_pushnil(L); /* need two items on the stack */
280 else if (strncmp(field_name, AMB_NAME, field_name_len) == 0) {
281 luaL_checktype(L, -1, LUA_TSTRING);
282 prop->name = mrp_strdup(lua_tostring(L, -1));
283 mrp_lua_set_object_name(L, PROPERTY_CLASS, prop->name);
285 else if (strncmp(field_name, "basic_table_name", field_name_len) == 0) {
286 luaL_checktype(L, -1, LUA_TSTRING);
287 prop->basic_table_name = mrp_strdup(lua_tostring(L, -1));
289 else if (strncmp(field_name, AMB_OUTPUTS, field_name_len) == 0) {
290 prop->outputs_ref = luaL_ref(L, LUA_REGISTRYINDEX);
291 lua_pushnil(L); /* need two items on the stack */
298 if (prop->handler_ref == LUA_NOREF && !prop->basic_table_name)
301 w = mrp_allocz(sizeof(dbus_property_watch_t));
305 w->prop.initialized = FALSE;
306 w->prop.name = mrp_strdup(w->lua_prop->dbus_data.name);
307 w->prop.type = DBUS_TYPE_INVALID;
309 if (prop->handler_ref == LUA_NOREF) {
310 basic_table_data_t *tdata;
312 w->prop.type = w->lua_prop->dbus_data.sig[0]; /* FIXME */
314 tdata = create_basic_property_table(prop->basic_table_name,
315 prop->dbus_data.name, w->prop.type);
323 w->cb = basic_property_updated;
326 /* add_table_data(tdata, ctx); */
327 if (subscribe_property(ctx, w)) {
328 mrp_log_error("Failed to subscribe to basic property");
333 /* we now have the callback function reference */
335 /* TODO: refactor to decouple updating the property (calling the
336 * lua handler) from parsing the D-Bus message. Is this possible? */
337 if (subscribe_property(ctx, w)) {
338 mrp_log_error("Failed to subscribe to basic property");
344 mrp_list_init(&w->hook);
346 mrp_list_append(&ctx->lua_properties, &w->hook);
348 /* TODO: need some mapping? or custom property_watch? */
350 /* TODO: put the object to a global table or not? maybe better to just
351 * unload them when the plugin is unloaded. */
353 mrp_lua_push_object(L, prop);
358 /* TODO: delete the allocated data */
359 destroy_prop(global_ctx, w);
361 mrp_log_error("< amb_constructor ERROR");
365 static int amb_getfield(lua_State *L)
367 lua_amb_property_t *prop = mrp_lua_check_object(L, PROPERTY_CLASS, 1);
368 size_t field_name_len;
369 const char *field_name = lua_tolstring(L, 2, &field_name_len);
376 mrp_log_info("> amb_getfield");
378 if (strncmp(field_name, AMB_NAME, field_name_len) == 0) {
380 lua_pushstring(L, prop->name);
384 else if (strncmp(field_name, AMB_HANDLER, field_name_len) == 0) {
385 if (prop->handler_ref != LUA_NOREF)
386 lua_rawgeti(L, LUA_REGISTRYINDEX, prop->handler_ref);
390 else if (strncmp(field_name, AMB_DBUS_DATA, field_name_len) == 0) {
393 lua_pushstring(L, AMB_OBJECT);
394 lua_pushstring(L, prop->dbus_data.obj);
397 lua_pushstring(L, AMB_INTERFACE);
398 lua_pushstring(L, prop->dbus_data.iface);
401 lua_pushstring(L, AMB_MEMBER);
402 lua_pushstring(L, prop->dbus_data.name);
405 lua_pushstring(L, "signature");
406 lua_pushstring(L, prop->dbus_data.sig);
409 else if (strncmp(field_name, "basic_table_name", field_name_len) == 0) {
410 if (prop->basic_table_name)
411 lua_pushstring(L, prop->basic_table_name);
415 else if (strncmp(field_name, AMB_OUTPUTS, field_name_len) == 0) {
416 if (prop->outputs_ref != LUA_NOREF)
417 lua_rawgeti(L, LUA_REGISTRYINDEX, prop->outputs_ref);
432 static int amb_setfield(lua_State *L)
438 mrp_log_info("> amb_setfield");
444 bool really_create_basic_handler(lua_State *L, void *data,
445 const char *signature, mrp_funcbridge_value_t *args,
446 char *ret_type, mrp_funcbridge_value_t *ret_val)
448 mrp_log_info("> really_create_basic_handler");
458 static bool parse_elementary_value(lua_State *L,
459 DBusMessageIter *iter, dbus_property_watch_t *w)
461 dbus_int32_t i32_val;
462 dbus_int32_t i16_val;
463 dbus_uint32_t u32_val;
464 dbus_uint16_t u16_val;
477 sig = dbus_message_iter_get_arg_type(iter);
480 case DBUS_TYPE_INT32:
481 dbus_message_iter_get_basic(iter, &i32_val);
482 lua_pushinteger(L, i32_val);
484 case DBUS_TYPE_INT16:
485 dbus_message_iter_get_basic(iter, &i16_val);
486 lua_pushinteger(L, i16_val);
488 case DBUS_TYPE_UINT32:
489 dbus_message_iter_get_basic(iter, &u32_val);
490 lua_pushinteger(L, u32_val);
492 case DBUS_TYPE_UINT16:
493 dbus_message_iter_get_basic(iter, &u16_val);
494 lua_pushinteger(L, u16_val);
496 case DBUS_TYPE_BOOLEAN:
497 dbus_message_iter_get_basic(iter, &b_val);
498 lua_pushboolean(L, b_val == TRUE);
501 dbus_message_iter_get_basic(iter, &byte_val);
502 lua_pushinteger(L, byte_val);
504 case DBUS_TYPE_DOUBLE:
505 dbus_message_iter_get_basic(iter, &d_val);
506 lua_pushnumber(L, d_val);
508 case DBUS_TYPE_STRING:
509 dbus_message_iter_get_basic(iter, &s_val);
510 lua_pushstring(L, s_val);
513 mrp_log_info("> parse_elementary_value: unknown type");
523 static bool parse_value(lua_State *L, DBusMessageIter *iter,
524 dbus_property_watch_t *w);
526 static bool parse_struct(lua_State *L,
527 DBusMessageIter *iter, dbus_property_watch_t *w)
530 DBusMessageIter new_iter;
535 /* initialize the table */
538 dbus_message_iter_recurse(iter, &new_iter);
540 while (dbus_message_iter_get_arg_type(&new_iter) != DBUS_TYPE_INVALID) {
543 lua_pushinteger(L, i++);
545 parse_value(L, &new_iter, w);
546 dbus_message_iter_next(&new_iter);
548 /* put the values to the table */
556 static bool parse_dict_entry(lua_State *L,
557 DBusMessageIter *iter, dbus_property_watch_t *w)
559 DBusMessageIter new_iter;
564 dbus_message_iter_recurse(iter, &new_iter);
566 while (dbus_message_iter_get_arg_type(&new_iter) != DBUS_TYPE_INVALID) {
568 /* key must be elementary, value can be anything */
570 parse_elementary_value(L, &new_iter, w);
571 dbus_message_iter_next(&new_iter);
573 parse_value(L, &new_iter, w);
574 dbus_message_iter_next(&new_iter);
576 /* put the values to the table */
583 static bool parse_array(lua_State *L,
584 DBusMessageIter *iter, dbus_property_watch_t *w)
586 DBusMessageIter new_iter;
595 element_type = dbus_message_iter_get_element_type(iter);
597 dbus_message_iter_recurse(iter, &new_iter);
599 /* the problem: if the value inside array is a dict entry, the
600 * indexing of elements need to be done with dict keys instead
603 if (element_type == DBUS_TYPE_DICT_ENTRY) {
604 while (dbus_message_iter_get_arg_type(&new_iter)
605 != DBUS_TYPE_INVALID) {
607 parse_dict_entry(L, &new_iter, w);
608 dbus_message_iter_next(&new_iter);
615 while (dbus_message_iter_get_arg_type(&new_iter)
616 != DBUS_TYPE_INVALID) {
619 lua_pushinteger(L, i++);
621 parse_value(L, &new_iter, w);
622 dbus_message_iter_next(&new_iter);
624 /* put the values to the table */
632 static bool parse_value(lua_State *L, DBusMessageIter *iter,
633 dbus_property_watch_t *w)
640 curr = dbus_message_iter_get_arg_type(iter);
644 case DBUS_TYPE_BOOLEAN:
645 case DBUS_TYPE_INT16:
646 case DBUS_TYPE_INT32:
647 case DBUS_TYPE_UINT16:
648 case DBUS_TYPE_UINT32:
649 case DBUS_TYPE_DOUBLE:
650 case DBUS_TYPE_STRING:
651 return parse_elementary_value(L, iter, w);
652 case DBUS_TYPE_ARRAY:
653 return parse_array(L, iter, w);
654 case DBUS_TYPE_STRUCT:
655 return parse_struct(L, iter, w);
656 case DBUS_TYPE_DICT_ENTRY:
657 goto error; /* these are handled from parse_array */
658 case DBUS_TYPE_INVALID:
665 mrp_log_error("failed to parse D-Bus property (sig[i] %c)", curr);
669 static void lua_property_handler(DBusMessage *msg, dbus_property_watch_t *w)
671 DBusMessageIter msg_iter;
672 DBusMessageIter variant_iter;
673 char *variant_sig = NULL;
678 if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_ERROR)
681 dbus_message_iter_init(msg, &msg_iter);
683 if (dbus_message_iter_get_arg_type(&msg_iter) != DBUS_TYPE_VARIANT)
686 dbus_message_iter_recurse(&msg_iter, &variant_iter);
688 variant_sig = dbus_message_iter_get_signature(&variant_iter);
694 mrp_log_info("iter sig: %s, expected: %s",
695 variant_sig, w->lua_prop->dbus_data.sig);
698 /* check if we got what we were expecting */
699 if (strcmp(variant_sig, w->lua_prop->dbus_data.sig) != 0)
702 if (w->lua_prop->handler_ref == LUA_NOREF)
705 /* load the function pointer to the stack */
706 lua_rawgeti(w->ctx->L, LUA_REGISTRYINDEX, w->lua_prop->handler_ref);
708 /* "self" parameter */
709 mrp_lua_push_object(w->ctx->L, w->lua_prop);
711 /* parse values to the stack */
712 parse_value(w->ctx->L, &variant_iter, w);
714 /* call the handler function */
715 lua_pcall(w->ctx->L, 2, 0, 0);
717 dbus_free(variant_sig);
723 dbus_free(variant_sig);
724 mrp_log_error("amb: failed to process an incoming D-Bus message");
728 static void basic_property_handler(DBusMessage *msg, dbus_property_watch_t *w)
730 DBusMessageIter msg_iter;
731 DBusMessageIter variant_iter;
733 dbus_int32_t i32_val;
734 dbus_int32_t i16_val;
735 dbus_uint32_t u32_val;
736 dbus_uint16_t u16_val;
745 dbus_message_iter_init(msg, &msg_iter);
747 if (dbus_message_iter_get_arg_type(&msg_iter) != DBUS_TYPE_VARIANT)
750 dbus_message_iter_recurse(&msg_iter, &variant_iter);
752 if (dbus_message_iter_get_arg_type(&variant_iter)
756 switch (w->prop.type) {
757 case DBUS_TYPE_INT32:
758 dbus_message_iter_get_basic(&variant_iter, &i32_val);
759 w->prop.value.i = i32_val;
761 case DBUS_TYPE_INT16:
762 dbus_message_iter_get_basic(&variant_iter, &i16_val);
763 w->prop.value.i = i16_val;
765 case DBUS_TYPE_UINT32:
766 dbus_message_iter_get_basic(&variant_iter, &u32_val);
767 w->prop.value.u = u32_val;
769 case DBUS_TYPE_UINT16:
770 dbus_message_iter_get_basic(&variant_iter, &u16_val);
771 w->prop.value.u = u16_val;
773 case DBUS_TYPE_BOOLEAN:
774 dbus_message_iter_get_basic(&variant_iter, &b_val);
775 w->prop.value.u = b_val;
778 dbus_message_iter_get_basic(&variant_iter, &byte_val);
779 w->prop.value.u = byte_val;
781 case DBUS_TYPE_DOUBLE:
782 dbus_message_iter_get_basic(&variant_iter, &d_val);
783 w->prop.value.f = d_val;
785 case DBUS_TYPE_STRING:
786 dbus_message_iter_get_basic(&variant_iter, &s_val);
787 w->prop.value.s = mrp_strdup(s_val);
794 w->cb(&w->prop, w->user_data);
799 mrp_log_error("amb: failed to parse property value");
803 static int property_signal_handler(mrp_dbus_t *dbus, DBusMessage *msg,
806 dbus_property_watch_t *w = data;
810 mrp_log_info("amb: received property signal");
813 basic_property_handler(msg, w);
816 lua_property_handler(msg, w);
822 static void property_reply_handler(mrp_dbus_t *dbus, DBusMessage *msg,
825 dbus_property_watch_t *w = data;
829 mrp_log_info("amb: received property method reply");
832 basic_property_handler(msg, w);
835 lua_property_handler(msg, w);
839 static int subscribe_property(data_t *ctx, dbus_property_watch_t *w)
841 const char *obj = w->lua_prop->dbus_data.obj;
842 const char *iface = w->lua_prop->dbus_data.iface;
843 const char *name = w->lua_prop->dbus_data.name;
845 mrp_log_info("subscribing to signal '%s.%s' at '%s'",
848 mrp_dbus_subscribe_signal(ctx->dbus, property_signal_handler, w, NULL,
849 obj, iface, name, NULL);
851 /* Ok, now we are listening to property changes. Let's get the initial
854 mrp_dbus_call(ctx->dbus,
856 "org.freedesktop.DBus.Properties",
857 "Get", 3000, property_reply_handler, w,
858 DBUS_TYPE_STRING, &iface,
859 DBUS_TYPE_STRING, &name,
866 static void print_basic_property(dbus_basic_property_t *prop)
868 switch (prop->type) {
869 case DBUS_TYPE_INT32:
870 case DBUS_TYPE_INT16:
871 mrp_log_info("Property %s : %i", prop->name, prop->value.i);
873 case DBUS_TYPE_UINT32:
874 case DBUS_TYPE_UINT16:
875 case DBUS_TYPE_BOOLEAN:
877 mrp_log_info("Property %s : %u", prop->name, prop->value.u);
879 case DBUS_TYPE_DOUBLE:
880 mrp_log_info("Property %s : %f", prop->name, prop->value.f);
882 case DBUS_TYPE_STRING:
883 mrp_log_info("Property %s : %s", prop->name, prop->value.s);
886 mrp_log_error("Unknown value in property");
890 static void basic_property_updated(dbus_basic_property_t *prop, void *userdata)
895 dbus_property_watch_t *w = userdata;
896 basic_table_data_t *tdata = w->tdata;
899 mrp_log_info("> basic_property_updated");
901 print_basic_property(prop);
903 tx = mqi_begin_transaction();
905 if (!prop->initialized) {
907 switch (tdata->type) {
909 buflen = snprintf(buf, 512, "INSERT INTO %s VALUES (1, '%s', %s)",
910 w->lua_prop->basic_table_name, prop->name, prop->value.s);
913 buflen = snprintf(buf, 512, "INSERT INTO %s VALUES (1, '%s', %d)",
914 w->lua_prop->basic_table_name, prop->name, prop->value.i);
917 buflen = snprintf(buf, 512, "INSERT INTO %s VALUES (1, '%s', %u)",
918 w->lua_prop->basic_table_name, prop->name, prop->value.u);
921 buflen = snprintf(buf, 512, "INSERT INTO %s VALUES (1, '%s', %f)",
922 w->lua_prop->basic_table_name, prop->name, prop->value.f);
928 if (buflen <= 0 || buflen == 512) {
932 r = mql_exec_string(mql_result_string, buf);
934 prop->initialized = TRUE;
939 switch (tdata->type) {
941 ret = mql_bind_value(tdata->update_operation, 1, tdata->type,
945 ret = mql_bind_value(tdata->update_operation, 1, tdata->type,
949 ret = mql_bind_value(tdata->update_operation, 1, tdata->type,
953 ret = mql_bind_value(tdata->update_operation, 1, tdata->type,
961 mrp_log_error("failed to bind value to update operation");
965 r = mql_exec_statement(mql_result_string, tdata->update_operation);
968 mrp_log_info("amb: %s", mql_result_is_success(r) ? "updated database" :
969 mql_result_error_get_message(r));
974 mqi_commit_transaction(tx);
977 static void delete_basic_table_data(basic_table_data_t *tdata)
982 if (tdata->update_operation)
983 mql_statement_free(tdata->update_operation);
986 mqi_drop_table(tdata->table);
991 static basic_table_data_t *create_basic_property_table(const char *table_name,
992 const char *member, int type)
996 /* char *insert_format; */
997 basic_table_data_t *tdata = NULL;
1000 if (strlen(member) > 64)
1003 tdata = mrp_allocz(sizeof(basic_table_data_t));
1009 case DBUS_TYPE_INT32:
1010 case DBUS_TYPE_INT16:
1011 tdata->type = mqi_integer;
1012 update_format = "%d";
1013 /* insert_format = "%d"; */
1015 case DBUS_TYPE_UINT32:
1016 case DBUS_TYPE_UINT16:
1017 case DBUS_TYPE_BOOLEAN:
1018 case DBUS_TYPE_BYTE:
1019 tdata->type = mqi_unsignd;
1020 update_format = "%u";
1021 /* insert_format = "%u"; */
1023 case DBUS_TYPE_DOUBLE:
1024 tdata->type = mqi_floating;
1025 update_format = "%f";
1026 /* insert_format = "%f"; */
1028 case DBUS_TYPE_STRING:
1029 tdata->type = mqi_varchar;
1030 update_format = "%s";
1031 /* insert_format = "'%s'"; */
1034 mrp_log_error("unknown type %d", type);
1038 tdata->defs[0].name = "id";
1039 tdata->defs[0].type = mqi_unsignd;
1040 tdata->defs[0].length = 0;
1041 tdata->defs[0].flags = 0;
1043 tdata->defs[1].name = "key";
1044 tdata->defs[1].type = mqi_varchar;
1045 tdata->defs[1].length = 64;
1046 tdata->defs[1].flags = 0;
1048 tdata->defs[2].name = "value";
1049 tdata->defs[2].type = tdata->type;
1050 tdata->defs[2].length = (tdata->type == mqi_varchar) ? 128 : 0;
1051 tdata->defs[2].flags = 0;
1053 memset(&tdata->defs[3], 0, sizeof(tdata->defs[3]));
1055 tdata->table = MQI_CREATE_TABLE((char *) table_name, MQI_TEMPORARY,
1058 if (!tdata->table) {
1059 mrp_log_error("creating table '%s' failed", table_name);
1063 ret = snprintf(buf, 512, "UPDATE %s SET value = %s where id = 1",
1064 table_name, update_format);
1066 if (ret <= 0 || ret == 512) {
1070 tdata->update_operation = mql_precompile(buf);
1072 if (!tdata->update_operation) {
1073 mrp_log_error("buggy buf: '%s'", buf);
1077 mrp_log_info("amb: compiled update statement '%s'", buf);
1082 mrp_log_error("amb: failed to create table %s", table_name);
1083 delete_basic_table_data(tdata);
1087 static int load_config(lua_State *L, const char *path)
1089 if (!luaL_loadfile(L, path) && !lua_pcall(L, 0, 0, 0))
1092 mrp_log_error("plugin-lua: failed to load config file %s.", path);
1093 mrp_log_error("%s", lua_tostring(L, -1));
1100 static int amb_init(mrp_plugin_t *plugin)
1103 mrp_plugin_arg_t *args = plugin->args;
1105 ctx = mrp_allocz(sizeof(data_t));
1112 ctx->amb_addr = args[ARG_AMB_DBUS_ADDRESS].str;
1113 ctx->config_file = args[ARG_AMB_CONFIG_FILE].str;
1115 mrp_log_info("amb dbus address: %s", ctx->amb_addr);
1116 mrp_log_info("amb config file: %s", ctx->config_file);
1118 ctx->dbus = mrp_dbus_connect(plugin->ctx->ml, "system", NULL);
1123 /* initialize lua support */
1125 mrp_list_init(&ctx->lua_properties);
1129 ctx->L = mrp_lua_get_lua_state();
1134 mrp_lua_create_object_class(ctx->L, MRP_LUA_CLASS(amb, property));
1136 /* TODO: create here a "manager" lua object and put that to the global
1137 * lua table? This one then has a pointer to the C context. */
1140 mrp_funcbridge_create_cfunc(L, "create_basic_handler", "amb",
1141 really_create_basic_handler, (void *)0x1234);
1144 /* 1. read the configuration file. The configuration must tell
1145 - target object (/org/automotive/runningstatus/vehicleSpeed)
1146 - target interface (org.automotive.vehicleSpeed)
1147 - target member (VehicleSpeed)
1148 - target type (int32_t)
1152 load_config(ctx->L, ctx->config_file);
1162 static void amb_exit(mrp_plugin_t *plugin)
1164 data_t *ctx = plugin->data;
1165 mrp_list_hook_t *p, *n;
1167 /* for all subscribed properties, unsubscribe and free memory */
1169 mrp_list_foreach(&ctx->lua_properties, p, n) {
1170 dbus_property_watch_t *w =
1171 mrp_list_entry(p, dbus_property_watch_t, hook);
1173 destroy_prop(ctx, w);
1179 #define AMB_DESCRIPTION "A plugin for Automotive Message Broker D-Bus API."
1180 #define AMB_HELP "Access Automotive Message Broker."
1181 #define AMB_VERSION MRP_VERSION_INT(0, 0, 1)
1182 #define AMB_AUTHORS "Ismo Puustinen <ismo.puustinen@intel.com>"
1184 static mrp_plugin_arg_t args[] = {
1185 MRP_PLUGIN_ARGIDX(ARG_AMB_DBUS_ADDRESS, STRING, "amb_address",
1186 "org.automotive.message.broker"),
1187 MRP_PLUGIN_ARGIDX(ARG_AMB_CONFIG_FILE, STRING, "config_file",
1188 "/etc/murphy/plugins/amb/config.lua"),
1192 MURPHY_REGISTER_PLUGIN("amb",
1193 AMB_VERSION, AMB_DESCRIPTION,
1194 AMB_AUTHORS, AMB_HELP,
1195 MRP_SINGLETON, amb_init, amb_exit,
1196 args, MRP_ARRAY_SIZE(args),
1197 NULL, 0, NULL, 0, NULL);