From: kibak.yoon Date: Thu, 23 Jun 2016 10:50:33 +0000 (+0900) Subject: capi-sensor: implements sensor_recorder APIs X-Git-Tag: submit/tizen/20160705.060431~1^2~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4a303694d9c4c55b65033dee0b260473f1e36f3f;p=platform%2Fcore%2Fapi%2Fsensor.git capi-sensor: implements sensor_recorder APIs Change-Id: Ic588754f1aa722276d6f11fedb74aa46c45aa5f5 Signed-off-by: kibak.yoon --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e3c504..9b6a809 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) PROJECT(capi-system-sensor) INCLUDE(GNUInstallDirs) -SET(DEPENDENTS "dlog sensor capi-base-common") +SET(DEPENDENTS "dlog sensor capi-base-common context-common") SET(VERSION ${FULLVER}) SET(PREFIX ${CMAKE_INSTALL_PREFIX}) diff --git a/packaging/capi-system-sensor.spec b/packaging/capi-system-sensor.spec index 3720474..d8976dd 100644 --- a/packaging/capi-system-sensor.spec +++ b/packaging/capi-system-sensor.spec @@ -10,6 +10,7 @@ BuildRequires: cmake BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(sensor) BuildRequires: pkgconfig(capi-base-common) +BuildRequires: pkgconfig(context-common) Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig diff --git a/src/sensor_recorder.cpp b/src/sensor_recorder.cpp index 09cbb2c..db642d9 100644 --- a/src/sensor_recorder.cpp +++ b/src/sensor_recorder.cpp @@ -16,176 +16,462 @@ #include #include -#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "include/sensor_log.h" + +static ctx::DBusClient dbusClient; +static GMutex info_mutex; + +static std::map sensor_keys = { + {SENSOR_HRM, SUBJ_SENSOR_HEART_RATE}, + {SENSOR_HUMAN_PEDOMETER, SUBJ_SENSOR_PEDOMETER}, + {SENSOR_HUMAN_SLEEP_MONITOR, SUBJ_SENSOR_SLEEP_MONITOR}, + {SENSOR_PRESSURE, SUBJ_SENSOR_PRESSURE}, +}; + +static std::map option_keys = { + {SENSOR_RECORDER_OPTION_RETENTION_PERIOD, KEY_RETENTION}, + {SENSOR_RECORDER_OPTION_INTERVAL, KEY_INTERVAL} +}; + +static std::map query_keys = { + {SENSOR_RECORDER_QUERY_START_TIME, KEY_START_TIME}, + {SENSOR_RECORDER_QUERY_END_TIME, KEY_END_TIME}, + {SENSOR_RECORDER_QUERY_ANCHOR_TIME, KEY_ANCHOR}, + {SENSOR_RECORDER_QUERY_TIME_INTERVAL, KEY_INTERVAL}, +}; + +static std::map data_keys = { + {SENSOR_RECORDER_DATA_STEPS, KEY_STEPS}, + {SENSOR_RECORDER_DATA_WALK_STEPS, KEY_WALK_STEPS}, + {SENSOR_RECORDER_DATA_RUN_STEPS, KEY_RUN_STEPS}, + {SENSOR_RECORDER_DATA_DISTANCE, KEY_DISTANCE}, + {SENSOR_RECORDER_DATA_CALORIE, KEY_CALORIES}, + {SENSOR_RECORDER_DATA_HEART_RATE, ""}, + {SENSOR_RECORDER_DATA_SLEEP_STATE, ""}, + {SENSOR_RECORDER_DATA_PRESSURE, KEY_PRESSURE}, + {SENSOR_RECORDER_DATA_MAX_PRESSURE, KEY_MAX_PRESSURE}, + {SENSOR_RECORDER_DATA_MIN_PRESSURE, KEY_MIN_PRESSURE}, + {SENSOR_RECORDER_DATA_AVERAGE_PRESSURE, KEY_AVG_PRESSURE} +}; + +static sensor_error_e convert_error(int error) +{ + switch (error) { + case ERR_NONE: + case ERR_INVALID_PARAMETER: + case ERR_OUT_OF_MEMORY: + case ERR_PERMISSION_DENIED: + case ERR_NOT_SUPPORTED: + case ERR_NO_DATA: + return (sensor_error_e)error; + case ERR_ALREADY_STARTED: + return SENSOR_ERROR_NOT_AVAILABLE; + default: + break; + } + return SENSOR_ERROR_OPERATION_FAILED; +} + +typedef struct { + ctx::Json *json; + int index; +} tuple_info; + +typedef struct { + sensor_type_e type; + sensor_recorder_data_cb cb; + void *user_data; +} callback_info; + +class DBusListener : public ctx::IDBusClientListener { +public: + void onPublish(std::string subject, int reqId, int error, ctx::Json event); + void setCallbackInfo(int reqid, callback_info *info); + +private: + std::map> infos; +}; + +void DBusListener::onPublish(std::string subject, int reqId, int error, ctx::Json event) +{ + bool ret = false; + int size = 0; + tuple_info data; + + { + ctx::ScopeMutex sm(&info_mutex); + if (infos.find(reqId) == infos.end()) + return; + } + + ret = event.get(NULL, KEY_RESULT_SIZE, &size); + + if (!ret) + return; + + if (size == 0) { + infos[reqId]->cb(infos[reqId]->type, (sensor_recorder_data_h)&data, 0, SENSOR_ERROR_NO_DATA, infos[reqId]->user_data); + goto CLEAN; + } + + data.json = &event; + + for (int i = 0; i < size; ++i) { + data.index = i; + ret = infos[reqId]->cb(infos[reqId]->type, (sensor_recorder_data_h)&data, (size - (i + 1)), convert_error(error), infos[reqId]->user_data); + + if (!ret) + break; + } + +CLEAN: + _D("Succeeded to call DBusListener::onPublish() with reqId[%d]", reqId); + + infos.erase(reqId); +} + +void DBusListener::setCallbackInfo(int reqId, callback_info *info) +{ + infos[reqId] = std::shared_ptr(info); +} int sensor_recorder_is_supported(sensor_type_e type, bool *supported) { - _D("Called : sensor[%#x]", type); + int ret = SENSOR_ERROR_NONE; if (type <= SENSOR_ALL) return SENSOR_ERROR_INVALID_PARAMETER; if (!supported) return SENSOR_ERROR_INVALID_PARAMETER; - *supported = false; + ret = dbusClient.isSupported(sensor_keys[type]); + + if (ret == ERR_NONE) + *supported = true; + else if (ret == ERR_NOT_SUPPORTED) + *supported = false; + else + return convert_error(ret); + + _D("sensor[%#x] is %s", type, (*supported ? "supported" : "not supported")); return SENSOR_ERROR_NONE; } int sensor_recorder_start(sensor_type_e type, sensor_recorder_option_h option) { - _D("Called : sensor[%#x] with option[%d]", type, option); + int ret = SENSOR_ERROR_NONE; + ctx::Json operation; if (type <= SENSOR_ALL) return SENSOR_ERROR_INVALID_PARAMETER; - return SENSOR_ERROR_NOT_SUPPORTED; + operation.set(NULL, KEY_OPERATION, VAL_START); + + if (option) + operation.set(NULL, KEY_OPTION, *static_cast(option)); + + ret = dbusClient.write(sensor_keys[type], operation.str(), NULL); + + _D("Started to record sensor[%#x] data with operation : %s", type, operation.str().c_str()); + + return convert_error(ret); } int sensor_recorder_stop(sensor_type_e type) { - _D("Called : sensor[%#x]", type); + int ret = SENSOR_ERROR_NONE; + ctx::Json operation; if (type <= SENSOR_ALL) return SENSOR_ERROR_INVALID_PARAMETER; - return SENSOR_ERROR_NOT_SUPPORTED; + operation.set(NULL, KEY_OPERATION, VAL_STOP); + + ret = dbusClient.write(sensor_keys[type], operation.str(), NULL); + + _D("Stopped to record sensor[%#x] data with operation : %s", type, operation.str().c_str()); + + return convert_error(ret); } int sensor_recorder_create_option(sensor_recorder_option_h *option) { - _D("Called : option[%#x]", *option); - if (!option) return SENSOR_ERROR_INVALID_PARAMETER; - *option = (sensor_recorder_option_h)malloc(sizeof(sensor_recorder_option_h)); + *option = static_cast(new(std::nothrow) ctx::Json()); + + if (!*option) { + _D("Failed to create option handle"); + return SENSOR_ERROR_OUT_OF_MEMORY; + } + + _D("Created option handle[%p]", *option); return SENSOR_ERROR_NONE; } int sensor_recorder_destroy_option(sensor_recorder_option_h option) { - _D("Called : option[%#x]", option); - if (!option) return SENSOR_ERROR_INVALID_PARAMETER; + delete static_cast(option); + option = NULL; + + _D("Destroyed option handle"); + return SENSOR_ERROR_NONE; } int sensor_recorder_option_set_int(sensor_recorder_option_h option, sensor_recorder_option_e attribute, int value) { - _D("Called : attribute[%d] with value[%d] to option[%#x]", attribute, value, option); - if (!option) return SENSOR_ERROR_INVALID_PARAMETER; if (attribute < 0) return SENSOR_ERROR_INVALID_PARAMETER; + if (option_keys.find(attribute) == option_keys.end()) + return SENSOR_ERROR_INVALID_PARAMETER; + + static_cast(option)->set(NULL, option_keys[attribute].c_str(), value); + + _D("Set attribute[%d] with value[%d] to option[%p]", attribute, value, option); return SENSOR_ERROR_NONE; } int sensor_recorder_create_query(sensor_recorder_query_h *query) { - _D("Called : query[%#x]", *query); - if (!query) return SENSOR_ERROR_INVALID_PARAMETER; - *query = (sensor_recorder_query_h)malloc(sizeof(sensor_recorder_query_h)); + *query = static_cast(new(std::nothrow) ctx::Json()); + + if (!*query) { + _D("Failed to create query handle"); + return SENSOR_ERROR_OUT_OF_MEMORY; + } + + _D("Created query handle[%p]", *query); return SENSOR_ERROR_NONE; } int sensor_recorder_destroy_query(sensor_recorder_query_h query) { - _D("Called : query[%#x]", query); - if (!query) return SENSOR_ERROR_INVALID_PARAMETER; + delete static_cast(query); + query = NULL; + + _D("Destroyed query handle"); + return SENSOR_ERROR_NONE; } int sensor_recorder_query_set_int(sensor_recorder_query_h query, sensor_recorder_query_e attribute, int value) { - _D("Called : attribute[%d] with value[%d] to query[%#x]", attribute, value, query); - if (!query) return SENSOR_ERROR_INVALID_PARAMETER; if (attribute < 0) return SENSOR_ERROR_INVALID_PARAMETER; + if (query_keys.find(attribute) == query_keys.end()) + return SENSOR_ERROR_INVALID_PARAMETER; + + static_cast(query)->set(NULL, query_keys[attribute].c_str(), (int)value); + + _D("Set attribute[%d] with value[%d] to query[%p]", attribute, value, query); return SENSOR_ERROR_NONE; } int sensor_recorder_query_set_time(sensor_recorder_query_h query, sensor_recorder_query_e attribute, time_t t) { - _D("Called : attribute[%d] with time[%d] to query[%#x]", attribute, time(&t), query); - if (!query) return SENSOR_ERROR_INVALID_PARAMETER; if (attribute < 0) return SENSOR_ERROR_INVALID_PARAMETER; + if (query_keys.find(attribute) == query_keys.end()) + return SENSOR_ERROR_INVALID_PARAMETER; + + static_cast(query)->set(NULL, query_keys[attribute].c_str(), (int64_t)t); + + _D("Set attribute[%d] with value[%ld] to query[%p]", attribute, t, query); return SENSOR_ERROR_NONE; } int sensor_recorder_read(sensor_type_e type, sensor_recorder_query_h query, sensor_recorder_data_cb cb, void *user_data) { - _D("Called : query[%#x]", query); + int ret = SENSOR_ERROR_NONE; + int reqId = 0; + callback_info *info = NULL; if (type <= SENSOR_ALL) return SENSOR_ERROR_INVALID_PARAMETER; if (!query || !cb) return SENSOR_ERROR_INVALID_PARAMETER; + /* Lazy creating listener */ + static DBusListener listener; + + dbusClient.addListener(sensor_keys[type], &listener); + + { + ctx::ScopeMutex sm(&info_mutex); + + ret = dbusClient.read(sensor_keys[type], *static_cast(query), &reqId, NULL); + + if (ret != SENSOR_ERROR_NONE) + return convert_error(ret); + + info = new(std::nothrow) callback_info(); + if (!info) { + _D("Failed to create callback info"); + return SENSOR_ERROR_OUT_OF_MEMORY; + } + + info->type = type; + info->cb = cb; + info->user_data = user_data; + + listener.setCallbackInfo(reqId, info); + } + + _D("succeeded to read sensor[%#x] data with query : %s", type, static_cast(query)->str().c_str()); + return SENSOR_ERROR_NONE; } int sensor_recorder_read_sync(sensor_type_e type, sensor_recorder_query_h query, sensor_recorder_data_cb cb, void *user_data) { - _D("Called : query[%#x]", query); + int ret = SENSOR_ERROR_NONE; + int reqId = 0; + int size = 0; + ctx::Json output; + tuple_info data; if (type <= SENSOR_ALL) return SENSOR_ERROR_INVALID_PARAMETER; if (!query || !cb) return SENSOR_ERROR_INVALID_PARAMETER; + ret = dbusClient.readSync(sensor_keys[type], *static_cast(query), &reqId, &output); + + if (ret != ERR_NONE) + return convert_error(ret); + + ret = output.get(NULL, KEY_RESULT_SIZE, &size); + + if (!ret) + return SENSOR_ERROR_INVALID_PARAMETER; + if (size == 0) + return SENSOR_ERROR_NO_DATA; + + data.json = &output; + + for (int i = 0; i < size; ++i) { + data.index = i; + ret = cb(type, (sensor_recorder_data_h)&data, (size - (i + 1)), SENSOR_ERROR_NONE, user_data); + + if (!ret) + break; + } + + _D("succeeded to read sensor[%#x] data with query : %s", type, static_cast(query)->str().c_str()); + return SENSOR_ERROR_NONE; } int sensor_recorder_data_get_time(sensor_recorder_data_h data, time_t *start_time, time_t *end_time) { - _D("Called : data[%#x]", data); + int64_t start = 0, end = 0; + tuple_info *tuple = NULL; + ctx::Json *json = NULL; if (!data || !start_time || !end_time) return SENSOR_ERROR_INVALID_PARAMETER; + tuple = static_cast(data); + json = tuple->json; + + if (!json) + return SENSOR_ERROR_INVALID_PARAMETER; + + if (!json->getAt(NULL, KEY_START_TIME, tuple->index, &start)) + return SENSOR_ERROR_INVALID_PARAMETER; + + if (!json->getAt(NULL, KEY_END_TIME, tuple->index, &end)) + return SENSOR_ERROR_INVALID_PARAMETER; + + *start_time = static_cast(start / 1000); + *end_time = static_cast(end / 1000); + + _D("Get start_time[%ld] and end_time[%ld] from data[%p]", *start_time, *end_time, data); + return SENSOR_ERROR_NONE; } int sensor_recorder_data_get_int(sensor_recorder_data_h data, sensor_recorder_data_e key, int *value) { - _D("Called : key[%d], data[%#x]", key, data); + tuple_info *tuple = NULL; + ctx::Json *json = NULL; if (!data || !value) return SENSOR_ERROR_INVALID_PARAMETER; if (key < 0) return SENSOR_ERROR_INVALID_PARAMETER; + if (data_keys.find(key) == data_keys.end()) + return SENSOR_ERROR_INVALID_PARAMETER; + + tuple = static_cast(data); + json = tuple->json; + + if (!json) + return SENSOR_ERROR_INVALID_PARAMETER; + + if (!json->getAt(NULL, data_keys[key].c_str(), tuple->index, value)) + return SENSOR_ERROR_INVALID_PARAMETER; + + _D("Get value[%d] from data[%p]", *value, data); return SENSOR_ERROR_NONE; } int sensor_recorder_data_get_double(sensor_recorder_data_h data, sensor_recorder_data_e key, double *value) { - _D("Called : key[%d], data[%#x]", key, data); + tuple_info *tuple = NULL; + ctx::Json *json = NULL; if (!data || !value) return SENSOR_ERROR_INVALID_PARAMETER; if (key < 0) return SENSOR_ERROR_INVALID_PARAMETER; + if (data_keys.find(key) == data_keys.end()) + return SENSOR_ERROR_INVALID_PARAMETER; + + tuple = static_cast(data); + json = tuple->json; + + if (!json) + return SENSOR_ERROR_INVALID_PARAMETER; + + if (!json->getAt(NULL, data_keys[key].c_str(), tuple->index, value)) + return SENSOR_ERROR_INVALID_PARAMETER; + + _D("Get value[%f] from data[%p]", *value, data); return SENSOR_ERROR_NONE; }