Add client utility library for application 63/88963/6
authorSangjung Woo <sangjung.woo@samsung.com>
Wed, 21 Sep 2016 05:01:41 +0000 (14:01 +0900)
committerSangjung Woo <sangjung.woo@samsung.com>
Thu, 29 Sep 2016 05:34:19 +0000 (14:34 +0900)
In order to easily communicate with automotive message broker daemon,
this library supports basic utility functions to application layer.

Change-Id: Ieacafd7931f1c63ccc1efd405f49eac214b9bc98
Signed-off-by: Sangjung Woo <sangjung.woo@samsung.com>
lib/CMakeLists.txt
lib/client/CMakeLists.txt [new file with mode: 0644]
lib/client/amb-client.pc.in [new file with mode: 0644]
lib/client/libamb-client.c [new file with mode: 0644]
lib/client/libamb-client.h [new file with mode: 0644]
lib/client/test/Makefile [new file with mode: 0644]
lib/client/test/test.c [new file with mode: 0644]
packaging/automotive-message-broker.spec

index f5f62a1..2fb87b8 100644 (file)
@@ -27,4 +27,4 @@ install (FILES ${amb_headers_install} DESTINATION ${INCLUDE_INSTALL_DIR}/amb COM
 
 install (TARGETS amb LIBRARY DESTINATION ${LIB_INSTALL_DIR})
 
-
+add_subdirectory(client)
diff --git a/lib/client/CMakeLists.txt b/lib/client/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d698746
--- /dev/null
@@ -0,0 +1,11 @@
+set (client_src libamb-client.c)
+set (client_headers libamb-client.h)
+
+add_library(amb-client SHARED ${client_src})
+set_target_properties(amb-client PROPERTIES SOVERSION ${PROJECT_VERSION} COMPILE_FLAGS "-fvisibility=hidden")
+target_link_libraries(amb-client ${glib_LIBRARIES} ${gio_LIBRARIES})
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/amb-client.pc.in ${CMAKE_CURRENT_BINARY_DIR}/amb-client.pc @ONLY)
+install (FILES ${CMAKE_CURRENT_BINARY_DIR}/amb-client.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
+install (FILES ${client_headers} DESTINATION ${INCLUDE_INSTALL_DIR}/amb-client COMPONENT Devel)
+install (TARGETS amb-client LIBRARY DESTINATION ${LIB_INSTALL_DIR})
diff --git a/lib/client/amb-client.pc.in b/lib/client/amb-client.pc.in
new file mode 100644 (file)
index 0000000..97c0e8d
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}
+libdir=@LIB_INSTALL_DIR@
+includedir=@INCLUDE_INSTALL_DIR@/amb-client
+
+Name: client utility library for application
+Description: client utility library to communicate automotive message broker daemon
+Version: @PROJECT_VERSION@
+Requires: gio-2.0 glib-2.0
+Libs: -L${libdir} -lamb-client
+Cflags: -I${includedir}
diff --git a/lib/client/libamb-client.c b/lib/client/libamb-client.c
new file mode 100644 (file)
index 0000000..38745e2
--- /dev/null
@@ -0,0 +1,476 @@
+/*
+ * Automotive Message Broker Client Library
+ *
+ * Copyright (C) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#include <stdio.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <errno.h>
+
+#include "libamb-client.h"
+
+#ifndef EXPORT
+#  define EXPORT __attribute__((visibility("default")))
+#endif
+
+#if defined DEBUG
+#  define DEBUGOUT(fmt, ...) do { fprintf(stderr, fmt, __VA_ARGS__); } while(0);
+#else
+#  define DEBUGOUT(fmt,...)
+#endif /* DEBUG */
+
+
+#define AMB_BUS_NAME        "org.automotive.message.broker"
+#define AMB_INTERFACE_NAME  "org.automotive.Manager"
+#define DBUS_INTERFACE_NAME "org.freedesktop.DBus.Properties"
+
+struct signal_item {
+       guint id;
+       GDBusProxy *obj;
+};
+
+/******************************************************************************
+ * internal
+ *****************************************************************************/
+static GDBusProxy *get_manager()
+{
+       static GDBusProxy *proxy = NULL;
+
+       if(!proxy) {
+               GError *err = NULL;
+               proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
+                               G_DBUS_PROXY_FLAGS_NONE,
+                               NULL,
+                               AMB_BUS_NAME,
+                               "/",
+                               AMB_INTERFACE_NAME,
+                               NULL,
+                               &err);
+               if (!proxy) {
+                       DEBUGOUT("%s: %s\n", __func__, err->message);
+                       g_clear_error(&err);
+                       return NULL;
+               }
+       }
+       return proxy;
+}
+
+static GDBusProxy *get_proxy_from_obj(const char *objpath)
+{
+       GError *err;
+       GDBusProxy *proxy;
+
+       err = NULL;
+       proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
+                       G_DBUS_PROXY_FLAGS_NONE,
+                       NULL,
+                       AMB_BUS_NAME,
+                       objpath,
+                       DBUS_INTERFACE_NAME,
+                       NULL,
+                       &err);
+       if (!proxy) {
+               DEBUGOUT("%s: %s\n", __func__, err->message);
+               g_clear_error(&err);
+               return NULL;
+       }
+
+       return proxy;
+}
+
+static GDBusProxy *find_objects_with_zone(GDBusProxy *proxy, const char *obj_name, ZoneType zone)
+{
+       GError *err;
+       GVariant *ret;
+       GDBusProxy *objproxy;
+       gchar *obj;
+
+       err = NULL;
+       ret = g_dbus_proxy_call_sync(proxy,
+                               "FindObjectForZone",
+                               g_variant_new("(si)", obj_name, zone),
+                               G_DBUS_CALL_FLAGS_NONE,
+                               -1,
+                               NULL,
+                               &err);
+       if (!ret) {
+               DEBUGOUT("%s: %s\n", __func__, err->message);
+               g_clear_error(&err);
+               return NULL;
+       }
+
+       g_variant_get(ret, "(&o)", &obj);
+       objproxy = get_proxy_from_obj(obj);
+
+       g_variant_unref(ret);
+
+       return objproxy;
+}
+
+static GList *find_objects(GDBusProxy *proxy, const char *obj_name)
+{
+       GError *err;
+       GVariant *ret;
+       GVariantIter *iter;
+       GList *list = NULL;
+       gchar *obj;
+
+       err = NULL;
+       ret = g_dbus_proxy_call_sync(proxy,
+                       "FindObject",
+                       g_variant_new("(s)", obj_name),
+                       G_DBUS_CALL_FLAGS_NONE,
+                       -1,
+                       NULL,
+                       &err);
+       if (!ret) {
+               DEBUGOUT("%s: %s\n", __func__, err->message);
+               g_clear_error(&err);
+               return NULL;
+       }
+
+       g_variant_get(ret, "(ao)", &iter);
+       while (g_variant_iter_loop(iter, "&o", &obj)) {
+               GDBusProxy *objproxy;
+
+               objproxy = get_proxy_from_obj(obj);
+               if (objproxy)
+                       list = g_list_append(list, objproxy);
+       }
+
+       g_variant_iter_free(iter);
+       g_variant_unref(ret);
+
+       return list;
+}
+
+static GVariant *get_all(GDBusProxy *proxy, const char *name)
+{
+       gchar *obj_name;
+       GError *err;
+       GVariant *ret;
+
+       obj_name = g_strdup_printf("org.automotive.%s", name);
+       if (!obj_name)
+               return NULL;
+
+       err = NULL;
+       ret = g_dbus_proxy_call_sync(proxy,
+                       "GetAll",
+                       g_variant_new("(s)", obj_name),
+                       G_DBUS_CALL_FLAGS_NONE,
+                       -1,
+                       NULL,
+                       &err);
+       g_free(obj_name);
+       if (!ret) {
+               DEBUGOUT("%s: %s\n", __func__, err->message);
+               g_clear_error(&err);
+               return NULL;
+       }
+
+       return ret;
+}
+
+static int set_prop(GDBusProxy *proxy, const char *name, const char *prop_name, GVariant *value)
+{
+       GError *err;
+       gchar *obj_name;
+       GVariant *ret;
+
+       obj_name = g_strdup_printf("org.automotive.%s", name);
+       if (!obj_name)
+               return -ENOMEM;
+
+       err = NULL;
+       ret = g_dbus_proxy_call_sync(proxy,
+                               "Set",
+                               g_variant_new("(ssv)", obj_name, prop_name, value),
+                               G_DBUS_CALL_FLAGS_NONE,
+                               -1,
+                               NULL,
+                               &err);
+       if (!ret) {
+               DEBUGOUT("%s: %s\n", __func__, err->message);
+               g_free(obj_name);
+               g_clear_error(&err);
+               return -EINVAL;
+       }
+
+       g_variant_unref(ret);
+       g_free(obj_name);
+       return 0;
+}
+
+static GHashTable *get_htable()
+{
+       static GHashTable *htable = NULL;
+       if (!htable) {
+               htable = g_hash_table_new(g_str_hash, g_str_equal);
+       }
+       return htable;
+}
+
+static void on_signal_handler(GDBusProxy *proxy,
+                       gchar *sender_name,
+                       gchar *signal_name,
+                       GVariant *parameters,
+                       gpointer user_callback)
+{
+       gchar *obj_name;
+       GVariant *value;
+       AMB_PROPERTY_CHANGED_CALLBACK callback = (AMB_PROPERTY_CHANGED_CALLBACK)user_callback;
+
+       if (g_strcmp0("PropertiesChanged", signal_name)) {
+               DEBUGOUT("Error: signal name: %s\n", signal_name);
+               return ;
+       }
+
+       g_variant_get(parameters, "(s@a{sv}as)", &obj_name, &value, NULL);
+       if (callback)
+               callback(obj_name, value);
+
+       g_free(obj_name);
+       g_variant_unref(value);
+
+       return ;
+}
+
+/******************************************************************************
+ * higher APIs
+ *****************************************************************************/
+EXPORT int amb_set_property(const char *obj_name, const char *prop_name, ZoneType zone, GVariant *value)
+{
+       int ret;
+       GDBusProxy *proxy;
+       GDBusProxy *objproxy;
+
+       proxy = get_manager();
+       if (!proxy)
+               return -ENETUNREACH;
+
+       objproxy = find_objects_with_zone(proxy, obj_name, zone);
+       if (!objproxy) {
+               return -EINVAL;
+       }
+
+       ret = set_prop(objproxy, obj_name, prop_name, value);
+       if (ret != 0) {
+               g_object_unref(objproxy);
+               return ret;
+       }
+
+       g_object_unref(objproxy);
+
+       return 0;
+}
+
+EXPORT int amb_get_property_all_with_zone(GVariant **proplist, const char *obj_name, ZoneType zone)
+{
+       GDBusProxy *proxy;
+       GDBusProxy *objproxy;
+
+       proxy = get_manager();
+       if (!proxy)
+               return -ENETUNREACH;
+
+       objproxy = find_objects_with_zone(proxy, obj_name, zone);
+       if (!objproxy) {
+               return -EINVAL;
+       }
+
+       *proplist = get_all(objproxy, obj_name);
+
+       g_object_unref(objproxy);
+
+       return 0;
+}
+
+EXPORT int amb_get_property_all(GList **proplist, const char *obj_name)
+{
+       GDBusProxy *proxy;
+       GVariant *ret;
+       GList *obj;
+       GList *objlist;
+
+       proxy = get_manager();
+       if (!proxy)
+               return -ENETUNREACH;
+
+       objlist = find_objects(proxy, obj_name);
+       if (!objlist) {
+               return -EINVAL;
+       }
+
+       *proplist = NULL;
+       for (obj = objlist; obj != NULL; obj = obj->next) {
+               ret = get_all(obj->data, obj_name);
+               *proplist = g_list_append(*proplist, ret);
+       }
+
+       amb_release_property_all(objlist);
+
+       return 0;
+}
+
+EXPORT int amb_get_object_list(GList **objlist)
+{
+       GDBusProxy *proxy;
+       GError *err;
+       GVariant *ret;
+       GVariantIter *iter;
+       gchar *objname;
+
+       proxy = get_manager();
+       if (!proxy)
+               return -ENETUNREACH;
+
+       err = NULL;
+       ret = g_dbus_proxy_call_sync(proxy,
+                       "List",
+                       NULL,
+                       G_DBUS_CALL_FLAGS_NONE,
+                       -1,
+                       NULL,
+                       &err);
+
+       if (!ret) {
+               DEBUGOUT("%s: %s\n", __func__, err->message);
+               g_clear_error(&err);
+               return -ENETUNREACH;
+       }
+
+       *objlist = NULL;
+       g_variant_get(ret, "(as)", &iter);
+       while (g_variant_iter_loop(iter, "&s", &objname)) {
+               *objlist = g_list_append(*objlist, g_strdup(objname));
+       }
+
+       g_variant_iter_free(iter);
+       g_variant_unref(ret);
+
+       return 0;
+}
+
+EXPORT void amb_release_property_all_with_zone(GVariant *proplist)
+{
+       g_variant_unref(proplist);
+}
+
+EXPORT void amb_release_object_list(GList *objlist)
+{
+       g_list_free_full(objlist, g_free);
+}
+
+EXPORT void amb_release_property_all(GList *proplist)
+{
+       g_list_free_full(proplist, (GDestroyNotify)g_variant_unref);
+}
+
+EXPORT int amb_register_property_changed_handler(gchar *objname,
+                               ZoneType zone,
+                               AMB_PROPERTY_CHANGED_CALLBACK callback)
+{
+       GDBusProxy *proxy;
+       GDBusProxy *objproxy;
+       guint id;
+       struct signal_item *item;
+       GHashTable *htable;
+
+       htable = get_htable();
+       if (!htable) {
+               DEBUGOUT("Error: get_htable() returns NULL\n");
+               return -ENOMEM;
+       }
+
+       proxy = get_manager();
+       if (!proxy)
+               return -ENETUNREACH;
+
+       objproxy = find_objects_with_zone(proxy, objname, zone);
+       if (!objproxy) {
+               DEBUGOUT("Error: find_objects_with_zone() Object Name: %s, ZoneType: %d\n",
+                               objname, zone);
+               return -EINVAL;
+       }
+
+       item = g_new0(struct signal_item, 1);
+       if (!item) {
+               DEBUGOUT("Error: fail to g_new0()\n");
+               g_object_unref(objproxy);
+               return -ENOMEM;
+       }
+
+       id = g_signal_connect(objproxy, "g-signal", G_CALLBACK(on_signal_handler), (gpointer)callback);
+       item->id = id;
+       item->obj = objproxy;
+
+       g_hash_table_insert(htable,
+                       g_strdup(g_dbus_proxy_get_object_path(objproxy)),
+                       item);
+
+       DEBUGOUT("instance: %s ID: %u\n", g_dbus_proxy_get_object_path(objproxy), id);
+
+       return 0;
+}
+
+EXPORT int amb_unregister_property_changed_handler(gchar *objname, ZoneType zone)
+{
+       GHashTable *htable;
+       GDBusProxy *proxy;
+       GDBusProxy *objproxy;
+       gpointer key;
+       struct signal_item *item;
+       gchar *objpath;
+
+       htable = get_htable();
+       if (!htable) {
+               DEBUGOUT("Error: get_htable() returns NULL\n");
+               return -ENOMEM;
+       }
+
+       proxy = get_manager();
+       if (!proxy)
+               return -ENETUNREACH;
+
+       objproxy = find_objects_with_zone(proxy, objname, zone);
+       if (!objproxy) {
+               DEBUGOUT("Error: find_objects_with_zone() Object Name: %s, ZoneType: %d\n",
+                               objname, zone);
+               return -EINVAL;
+       }
+
+       objpath = (gchar*)g_dbus_proxy_get_object_path(objproxy);
+
+       if (!g_hash_table_lookup_extended(htable, objpath, &key, (gpointer*)&item)) {
+               DEBUGOUT("Error: fail to find the object :%s\n", objpath);
+               g_object_unref(objproxy);
+               return -EINVAL;
+       }
+
+       DEBUGOUT("instance: %s ID: %u\n", objpath, item->id);
+
+       g_signal_handler_disconnect(item->obj, item->id);
+       if (!g_hash_table_remove(htable, objpath)) {
+               DEBUGOUT("Error: fail to g_hash_table_remove()\n");
+       }
+
+       g_free(key);
+       g_free(item);
+
+       return 0;
+}
diff --git a/lib/client/libamb-client.h b/lib/client/libamb-client.h
new file mode 100644 (file)
index 0000000..a4220ac
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Automotive Message Broker Client Library
+ *
+ * Copyright (C) 2016 Samsung Electronics Co., Ltd.
+ *
+ * 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.
+ */
+
+#ifndef __LIBAMB_CLIENT_H__
+#define __LIBAMB_CLIENT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <glib.h>
+
+/**
+ * Zone information in Vehicle
+ */
+enum Zone {
+       None = 0,
+       Front = 1,
+       Middle = 1 << 1,
+       Right = 1 << 2,
+       Left = 1 << 3,
+       Rear = 1 << 4,
+       Center = 1 << 5,
+       LeftSide = 1 << 6,
+       RightSide = 1 << 7,
+       FrontSide = 1 << 8,
+       BackSide = 1 << 9
+};
+typedef int ZoneType;
+
+/**
+ * Property status changed callback function. This function is invocked
+ * when the properties of registered object are changed.
+ *
+ * @param[in] registered object name
+ * @param[in] changed status
+ *
+ * @see amb_unregister_property_changed_handler(), amb_unregister_property_changed_handler()
+ */
+typedef void (*AMB_PROPERTY_CHANGED_CALLBACK)(const gchar *objname, GVariant *data);
+
+/**
+ * primitive APIs
+ */
+
+/**
+ * Get all properties from a specific object name
+ *
+ * @param[out] GList pointer that contains GVariant data
+ * @param[in] object name
+ * @return 0 on success, negative errno value on error
+ *
+ * @see amb_release_property_all()
+ */
+int amb_get_property_all(GList **proplist, const char *obj_name);
+
+/**
+ * Get all properties from a specific object name & zone number
+ *
+ * @param[out] GVariant pointer that contains all properties
+ * @param[in] object name
+ * @param[in] zone number
+ * @return 0 on success, negative errno value on error
+ *
+ * @see amb_release_property_all_with_zone()
+ */
+int amb_get_property_all_with_zone(GVariant **proplist, const char *obj_name, ZoneType zone);
+
+/**
+ * Set a property value for a specific object name, property name & zone number
+ *
+ * @param[in] object name to be set
+ * @param[in] property name to be set
+ * @param[in] zone number to be set
+ * @param[in] value to be set
+ * @return 0 on success, negative errno value on error
+ */
+int amb_set_property(const char *obj_name, const char *prop_name, ZoneType zone, GVariant *value);
+
+/**
+ * Release allocated memory space from amb_get_property_all() function
+ *
+ * @param[in] GList pointer from amb_get_property_all() function
+ *
+ * @see amb_get_property_all()
+ */
+void amb_release_property_all(GList *proplist);
+
+/**
+ * Release allocated memory space from amb_get_property_all_with_zone()
+ *
+ * @param[in] GVariant pointer from amb_get_property_all_with_zone()
+ */
+void amb_release_property_all_with_zone(GVariant *proplist);
+
+/**
+ * Register property changed handler.
+ *
+ * @param[in] Object name to be monitored
+ * @param[in] zone number to be set
+ * @param[in] Callback function when the properties of monitored object
+ * are changed.
+ * @return 0 on success, negative errno value on error
+ *
+ * @see amb_unregister_property_changed_handler(), AMB_PROPERTY_CHANGED_CALLBACK */
+int amb_register_property_changed_handler(gchar *objname,
+                                       ZoneType zone,
+                                       AMB_PROPERTY_CHANGED_CALLBACK callback);
+
+/**
+ * Unregister property changed handler.
+ *
+ * @param[in] Object name to be monitored
+ * @param[in] zone number to be set
+ * @return 0 on success, negative errno value on error
+ *
+ * @see amb_register_property_changed_handler(), AMB_PROPERTY_CHANGED_CALLBACK
+ */
+int amb_unregister_property_changed_handler(gchar *objname, ZoneType zone);
+
+/**
+ * higher APIs
+ */
+
+/**
+ * Get all object names that supported by Vehicle
+ *
+ * @param[out] GList pointer that contains supported object
+ * @return 0 on success, negative errno value on error
+ *
+ * @see amb_release_object_list()
+ */
+int amb_get_object_list(GList **objlist);
+
+/**
+ * Release allocated memory space from amb_get_object_list() function
+ *
+ * @param[in] GVariant pointer from amb_get_object_list() function
+ *
+ * @see amb_get_object_list()
+ */
+void amb_release_object_list(GList *objlist);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __LIBAMB_CLIENT_H__
+ */
diff --git a/lib/client/test/Makefile b/lib/client/test/Makefile
new file mode 100644 (file)
index 0000000..3ec5618
--- /dev/null
@@ -0,0 +1,14 @@
+# Makefile
+
+PKG_CFG=`pkg-config --cflags --libs amb-client`
+CFLAGS=-Wall -g
+
+TARGET=test
+
+all: $(TARGET)
+
+$(TARGET): % : %.c
+       $(CC) -o $@ $@.c $(PKG_CFG) $(CFLAGS)
+
+clean:
+       rm -rf ${TARGET}
diff --git a/lib/client/test/test.c b/lib/client/test/test.c
new file mode 100644 (file)
index 0000000..19b2f6d
--- /dev/null
@@ -0,0 +1,160 @@
+#include <stdio.h>
+
+#include <libamb-client.h>
+
+void test_get_object_list()
+{
+       GList *objlist;
+       GList *item;
+       int ret;
+
+       fprintf(stdout, "\n== %s ==\n", __func__);
+
+       ret = amb_get_object_list(&objlist);
+       if (ret < 0) {
+               printf("Fail to amb_get_object_list()\n");
+               return ;
+       }
+
+       fprintf(stdout, "  - count: %u\n", g_list_length(objlist));
+       for (item = objlist; item != NULL; item = item->next) {
+               gchar *obj = item->data;
+               fprintf(stdout, "%s ", obj);
+       }
+       printf("\n");
+
+       amb_release_object_list(objlist);
+}
+
+void test_get_property_all(const char *obj_name)
+{
+       GList *retlist;
+       GList *item;
+       int ret;
+
+       fprintf(stdout, "\n== %s ==\n", __func__);
+       ret = amb_get_property_all(&retlist, obj_name);
+       if (ret < 0) {
+               printf("Fail to get_property_all()\n");
+               return ;
+       }
+
+       fprintf(stdout, "  - count: %u\n", g_list_length(retlist));
+       for (item = retlist; item != NULL; item = item->next) {
+               GVariant *i = item->data;
+               gchar *s = g_variant_print(i, TRUE);
+               printf("%s\n", s);
+               g_free(s);
+       }
+
+       amb_release_property_all(retlist);
+}
+
+void test_get_property_all_with_zone(const char *obj_name, int zone)
+{
+       GVariant *ret;
+       int r;
+       gchar *s;
+
+       fprintf(stdout, "\n== %s ==\n", __func__);
+       r = amb_get_property_all_with_zone(&ret, obj_name, zone);
+       if (r < 0) {
+               fprintf(stderr, "Fail to get_property_all_with_zone(): %s, %d\n", obj_name, zone);
+               return ;
+       }
+
+       s = g_variant_print(ret, TRUE);
+       printf("%s\n", s);
+
+       g_free(s);
+
+       amb_release_property_all_with_zone(ret);
+}
+
+void test_set_property(const char *obj_name, const char *prop_name, int zone, GVariant *value)
+{
+       GVariant *ret;
+       gchar *s;
+       int r;
+
+       fprintf(stdout, "== %s ==\n", __func__);
+
+       if (amb_set_property(obj_name, prop_name, zone, value) != 0) {
+               fprintf(stderr, "Fail to set_property()\nn");
+               return ;
+       }
+
+       r = amb_get_property_all_with_zone(&ret, obj_name, zone);
+       if (r < 0) {
+               fprintf(stderr, "Fail to get_property_all_with_zone(): %s, %d\n", obj_name, zone);
+               return ;
+       }
+
+       s = g_variant_print(ret, TRUE);
+       printf("%s\n", s);
+
+       g_free(s);
+       amb_release_property_all_with_zone(ret);
+}
+
+static void signal_handler(const gchar *objname, GVariant *data)
+{
+       gchar *s;
+
+       if (!data)
+               return ;
+
+       s = g_variant_print(data, TRUE);
+       g_print("== signal_handler: %s\n", objname);
+       g_print("%s\n", s);
+
+       g_free(s);
+}
+
+static gboolean timer_callback(gpointer d)
+{
+       int rc;
+       gchar *objname = (gchar *)d;
+
+       rc = amb_unregister_property_changed_handler(objname, 0);
+       if (rc != 0) {
+                fprintf(stderr, "Fail to amb_unregister_property_changed_handler(): %s\n", objname);
+       }
+
+       return FALSE;
+}
+
+void test_signal_listen(gchar *objname, ZoneType zone)
+{
+       GMainLoop *loop;
+       int rc;
+
+       rc = amb_register_property_changed_handler(objname, zone, (AMB_PROPERTY_CHANGED_CALLBACK)signal_handler);
+       if (rc != 0) {
+                fprintf(stderr, "Fail to amb_register_property_changed_handler(): %s\n", objname);
+                return ;
+       }
+
+       g_timeout_add_seconds(10, timer_callback, objname);
+
+       loop = g_main_loop_new(NULL, FALSE);
+       g_main_loop_run(loop);
+
+       g_main_loop_unref(loop);
+}
+
+int main()
+{
+       test_get_object_list();
+
+       test_get_property_all("ClimateControl");
+       test_get_property_all("VehicleSpeed");
+
+       test_get_property_all_with_zone("ClimateControl", 5);
+
+       test_set_property("ClimateControl", "AirConditioning", 5, g_variant_new("b", TRUE));
+
+       test_signal_listen("VehicleSpeed", 0);
+
+       return 0;
+}
index 2b5db96..de573ba 100644 (file)
@@ -57,6 +57,25 @@ Requires:   boost-devel
 %description devel
 Development files for the automotive-message-broker
 
+%package libclient
+Summary:    Client library based on gdbus
+Group:      Automotive/Libraries
+Requires:   %{name} = %{version}-%{release}
+
+%description libclient
+Utility client library based on gdbus.
+It also supports various data structure for easy usage.
+
+%package libclient-devel
+Summary:    Client library based on gdbus
+Group:      Automotive/Libraries
+Requires:   %{name} = %{version}-%{release}
+
+%description libclient-devel
+Utility client library based on gdbus.
+It also supports various data structure for easy usage.
+
+
 %package doc
 Summary:    Documentation for the automotive-message-broker API
 Group:      Automotive/Documentation
@@ -309,6 +328,7 @@ cp packaging/config.tizen %{buildroot}%{_sysconfdir}/ambd/
 %{_includedir}/amb/*.h
 %{_includedir}/amb/*.hpp
 %{_libdir}/pkgconfig/*.pc
+%exclude %{_libdir}/pkgconfig/amb-client.pc
 
 %if %{with qt5}
 %files plugins-qtmainloop
@@ -440,3 +460,13 @@ cp packaging/config.tizen %{buildroot}%{_sysconfdir}/ambd/
 %manifest packaging.in/amb.manifest.plugins
 %{_libdir}/tizen-extensions-crosswalk/*
 %{_datadir}/%{name}/xwalk/examples/*
+
+%files libclient
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/libamb-client.so.*
+
+%files libclient-devel
+%manifest packaging.in/amb.manifest.plugins
+%{_libdir}/libamb-client.so
+%{_libdir}/pkgconfig/amb-client.pc
+%{_includedir}/amb-client/*.h