From b988f7a78ace4696d92067bedae4a4b0cf8e5098 Mon Sep 17 00:00:00 2001 From: Mu-Woong Lee Date: Mon, 27 Jun 2016 13:33:19 +0900 Subject: [PATCH] Add sensor recorder provides (pedometer & pressure supported) Change-Id: Ib1177eb9b595b9b1bdc3b10f3b010b984c2cb6fc Signed-off-by: Mu-Woong Lee --- include/ProviderList.h | 2 + packaging/context-provider.spec | 3 +- src/CMakeLists.txt | 3 +- src/sensor/CMakeLists.txt | 19 ++++ src/sensor/ClientInfo.cpp | 159 ++++++++++++++++++++++++++++++++ src/sensor/ClientInfo.h | 45 +++++++++ src/sensor/CreateProvider.cpp | 30 ++++++ src/sensor/Pedometer.cpp | 54 +++++++++++ src/sensor/Pedometer.h | 37 ++++++++ src/sensor/PedometerLogger.cpp | 158 +++++++++++++++++++++++++++++++ src/sensor/PedometerLogger.h | 53 +++++++++++ src/sensor/PedometerQuerier.cpp | 71 ++++++++++++++ src/sensor/PedometerQuerier.h | 34 +++++++ src/sensor/Pressure.cpp | 49 ++++++++++ src/sensor/Pressure.h | 36 ++++++++ src/sensor/PressureLogger.cpp | 104 +++++++++++++++++++++ src/sensor/PressureLogger.h | 45 +++++++++ src/sensor/PressureQuerier.cpp | 92 ++++++++++++++++++ src/sensor/PressureQuerier.h | 35 +++++++ src/sensor/Querier.cpp | 84 +++++++++++++++++ src/sensor/Querier.h | 49 ++++++++++ src/sensor/SensorLogger.cpp | 82 ++++++++++++++++ src/sensor/SensorLogger.h | 45 +++++++++ src/sensor/SensorProvider.cpp | 154 +++++++++++++++++++++++++++++++ src/sensor/SensorProvider.h | 50 ++++++++++ src/sensor/SensorProxy.cpp | 124 +++++++++++++++++++++++++ src/sensor/SensorProxy.h | 60 ++++++++++++ src/sensor/TypesInternal.h | 40 ++++++++ 28 files changed, 1715 insertions(+), 2 deletions(-) create mode 100644 src/sensor/CMakeLists.txt create mode 100644 src/sensor/ClientInfo.cpp create mode 100644 src/sensor/ClientInfo.h create mode 100644 src/sensor/CreateProvider.cpp create mode 100644 src/sensor/Pedometer.cpp create mode 100644 src/sensor/Pedometer.h create mode 100644 src/sensor/PedometerLogger.cpp create mode 100644 src/sensor/PedometerLogger.h create mode 100644 src/sensor/PedometerQuerier.cpp create mode 100644 src/sensor/PedometerQuerier.h create mode 100644 src/sensor/Pressure.cpp create mode 100644 src/sensor/Pressure.h create mode 100644 src/sensor/PressureLogger.cpp create mode 100644 src/sensor/PressureLogger.h create mode 100644 src/sensor/PressureQuerier.cpp create mode 100644 src/sensor/PressureQuerier.h create mode 100644 src/sensor/Querier.cpp create mode 100644 src/sensor/Querier.h create mode 100644 src/sensor/SensorLogger.cpp create mode 100644 src/sensor/SensorLogger.h create mode 100644 src/sensor/SensorProvider.cpp create mode 100644 src/sensor/SensorProvider.h create mode 100644 src/sensor/SensorProxy.cpp create mode 100644 src/sensor/SensorProxy.h create mode 100644 src/sensor/TypesInternal.h diff --git a/include/ProviderList.h b/include/ProviderList.h index 7218956..a159c44 100644 --- a/include/ProviderList.h +++ b/include/ProviderList.h @@ -20,6 +20,7 @@ #include #include #include +#include #define LIB_DIRECTORY "/usr/lib/context-service/" #define LIB_PREFIX "libctx-prvd-" @@ -42,6 +43,7 @@ const struct { {SUBJ_VIDEO_STATS, "media-stats"}, {SUBJ_STATE_MESSAGE, "message"}, {SUBJ_PLACE_DETECTION, "my-place"}, + {SUBJ_SENSOR, "sensor"}, {SUBJ_SOCIAL_STATS, "social-stats"}, {SUBJ_STATE_BATTERY, "system"}, {SUBJ_STATE_CHARGER, "system"}, diff --git a/packaging/context-provider.spec b/packaging/context-provider.spec index 4af42f5..36421d4 100644 --- a/packaging/context-provider.spec +++ b/packaging/context-provider.spec @@ -28,7 +28,8 @@ BuildRequires: pkgconfig(pkgmgr-info) BuildRequires: pkgconfig(capi-media-sound-manager) BuildRequires: pkgconfig(capi-network-bluetooth) BuildRequires: pkgconfig(capi-network-wifi) -BuildRequires: pkgconfig(libcore-context-manager) +BuildRequires: pkgconfig(sensor) +BuildRequires: pkgconfig(motion) %if "%{?BUILD_PROFILE}" == "mobile" BuildRequires: pkgconfig(msg-service) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 967c384..3dfad81 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,6 +8,7 @@ ADD_SUBDIRECTORY(activity) ADD_SUBDIRECTORY(app-stats) ADD_SUBDIRECTORY(custom) ADD_SUBDIRECTORY(headphone) +ADD_SUBDIRECTORY(sensor) ADD_SUBDIRECTORY(system) ADD_SUBDIRECTORY(time) ADD_SUBDIRECTORY(wifi) @@ -21,4 +22,4 @@ ADD_SUBDIRECTORY(media-stats) ADD_SUBDIRECTORY(message) #ADD_SUBDIRECTORY(my-place) ADD_SUBDIRECTORY(social-stats) -ENDIF("${PROFILE}" STREQUAL "mobile") +ENDIF("${PROFILE}" STREQUAL "mobile") \ No newline at end of file diff --git a/src/sensor/CMakeLists.txt b/src/sensor/CMakeLists.txt new file mode 100644 index 0000000..c00256a --- /dev/null +++ b/src/sensor/CMakeLists.txt @@ -0,0 +1,19 @@ +SET(target "${target_prefix}-sensor") + +SET(DEPS ${DEPS} + sensor +) + +FILE(GLOB SRCS *.cpp) + +INCLUDE(FindPkgConfig) +PKG_CHECK_MODULES(PKG_SENSOR REQUIRED ${DEPS}) + +FOREACH(flag ${PKG_SENSOR_CFLAGS}) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}") +ENDFOREACH(flag) + +ADD_LIBRARY(${target} SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${target} ${PKG_SENSOR_LDFLAGS} ${target_shared}) + +INSTALL(TARGETS ${target} DESTINATION ${CMAKE_INSTALL_LIBDIR}/${target_dir}) diff --git a/src/sensor/ClientInfo.cpp b/src/sensor/ClientInfo.cpp new file mode 100644 index 0000000..6a94f01 --- /dev/null +++ b/src/sensor/ClientInfo.cpp @@ -0,0 +1,159 @@ +/* + * 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 +#include +#include +#include "TypesInternal.h" +#include "ClientInfo.h" + +using namespace ctx; + +unsigned int ClientInfo::__refCnt = 0; +DatabaseManager *ClientInfo::__dbMgr = NULL; + +ClientInfo::ClientInfo() +{ + ++__refCnt; + + if (__dbMgr) + return; + + __dbMgr = new(std::nothrow) DatabaseManager(); + IF_FAIL_VOID_TAG(__dbMgr, _E, "Memory allocation failed"); + + bool ret = __dbMgr->executeSync( + "CREATE TABLE IF NOT EXISTS " CLIENT_INFO " (" \ + KEY_SUBJECT " TEXT NOT NULL," \ + KEY_PKG_ID " TEXT NOT NULL," \ + KEY_OPTION " TEXT NOT NULL," \ + KEY_RETENTION " INTEGER NOT NULL," \ + "PRIMARY KEY (" KEY_SUBJECT "," KEY_PKG_ID ")" \ + ")", NULL); + + IF_FAIL_VOID_TAG(ret, _E, "Table creation failed"); +} + +ClientInfo::~ClientInfo() +{ + if (--__refCnt != 0) + return; + + delete __dbMgr; + __dbMgr = NULL; +} + +int ClientInfo::get(std::string subject, std::string pkgId, Json& option) +{ + IF_FAIL_RETURN_TAG(__dbMgr, ERR_OPERATION_FAILED, _W, "DB not initialized"); + + bool ret; + std::string optStr; + std::vector records; + char *query = sqlite3_mprintf( + "SELECT " KEY_OPTION " FROM " CLIENT_INFO " WHERE " \ + KEY_SUBJECT "='%q' AND " KEY_PKG_ID "='%q'", + subject.c_str(), pkgId.c_str()); + + ret = __dbMgr->executeSync(query, &records); + sqlite3_free(query); + + IF_FAIL_RETURN(ret, ERR_OPERATION_FAILED); + IF_FAIL_RETURN(!records.empty(), ERR_NO_DATA); + IF_FAIL_RETURN(records[0].get(NULL, KEY_OPTION, &optStr), ERR_OPERATION_FAILED); + + option = optStr; + + return ERR_NONE; +} + +int ClientInfo::get(std::string subject, std::vector& options) +{ + IF_FAIL_RETURN_TAG(__dbMgr, ERR_OPERATION_FAILED, _W, "DB not initialized"); + + bool ret; + std::string optStr; + std::vector records; + char *query = sqlite3_mprintf( + "SELECT " KEY_OPTION " FROM " CLIENT_INFO " WHERE " \ + KEY_SUBJECT "='%q'", + subject.c_str()); + + ret = __dbMgr->executeSync(query, &records); + sqlite3_free(query); + + IF_FAIL_RETURN(ret, ERR_OPERATION_FAILED); + IF_FAIL_RETURN(!records.empty(), ERR_NO_DATA); + + for (auto jObj : records) { + if (!jObj.get(NULL, KEY_OPTION, &optStr)) + continue; + options.push_back(Json(optStr)); + } + + return ERR_NONE; +} + +bool ClientInfo::exist(std::string subject) +{ + IF_FAIL_RETURN_TAG(__dbMgr, ERR_OPERATION_FAILED, _W, "DB not initialized"); + + bool ret; + std::vector records; + char *query = sqlite3_mprintf( + "SELECT " KEY_PKG_ID " FROM " CLIENT_INFO " WHERE " \ + KEY_SUBJECT "='%q' LIMIT 1", + subject.c_str()); + + ret = __dbMgr->executeSync(query, &records); + sqlite3_free(query); + + IF_FAIL_RETURN(ret, false); + IF_FAIL_RETURN(!records.empty(), false); + + return true; +} + +bool ClientInfo::set(std::string subject, std::string pkgId, Json option, int retentionPeriod) +{ + IF_FAIL_RETURN_TAG(__dbMgr, false, _W, "DB not initialized"); + + bool ret; + char *query = sqlite3_mprintf( + "INSERT INTO " CLIENT_INFO " VALUES ('%q', '%q', '%q', %d)", + subject.c_str(), pkgId.c_str(), option.str().c_str(), retentionPeriod); + + ret = __dbMgr->executeSync(query, NULL); + sqlite3_free(query); + + return ret; +} + +bool ClientInfo::remove(std::string subject, std::string pkgId) +{ + IF_FAIL_RETURN_TAG(__dbMgr, false, _W, "DB not initialized"); + + bool ret; + char *query = sqlite3_mprintf( + "DELETE FROM " CLIENT_INFO " WHERE " \ + KEY_SUBJECT "='%q' AND " KEY_PKG_ID "='%q'", + subject.c_str(), pkgId.c_str()); + + ret = __dbMgr->executeSync(query, NULL); + sqlite3_free(query); + + return ret; +} diff --git a/src/sensor/ClientInfo.h b/src/sensor/ClientInfo.h new file mode 100644 index 0000000..a52cd27 --- /dev/null +++ b/src/sensor/ClientInfo.h @@ -0,0 +1,45 @@ +/* + * 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 __CONTEXT_CLIENT_INFO_H__ +#define __CONTEXT_CLIENT_INFO_H__ + +#include +#include +#include +#include + +namespace ctx { + + class ClientInfo { + public: + ClientInfo(); + ~ClientInfo(); + + int get(std::string subject, std::string pkgId, Json& option); + int get(std::string subject, std::vector& options); + bool exist(std::string subject); + + bool set(std::string subject, std::string pkgId, Json option, int retentionPeriod); + bool remove(std::string subject, std::string pkgId); + + private: + static unsigned int __refCnt; + static DatabaseManager *__dbMgr; + }; +} + +#endif /* _CONTEXT_CLIENT_INFO_H_ */ diff --git a/src/sensor/CreateProvider.cpp b/src/sensor/CreateProvider.cpp new file mode 100644 index 0000000..47d5ee9 --- /dev/null +++ b/src/sensor/CreateProvider.cpp @@ -0,0 +1,30 @@ +/* + * 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 +#include +#include "Pedometer.h" +#include "Pressure.h" + +using namespace ctx; + +extern "C" SO_EXPORT ContextProvider* CreateProvider(const char *subject) +{ + ADD_PROVIDER(SUBJ_SENSOR_PEDOMETER, PedometerProvider); + ADD_PROVIDER(SUBJ_SENSOR_PRESSURE, PressureProvider); + + return NULL; +} diff --git a/src/sensor/Pedometer.cpp b/src/sensor/Pedometer.cpp new file mode 100644 index 0000000..cac1e89 --- /dev/null +++ b/src/sensor/Pedometer.cpp @@ -0,0 +1,54 @@ +/* + * 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 +#include +#include "TypesInternal.h" +#include "PedometerLogger.h" +#include "PedometerQuerier.h" +#include "Pedometer.h" + +using namespace ctx; + +PedometerProvider::PedometerProvider() : + SensorProvider(SUBJ_SENSOR_PEDOMETER) +{ + IF_FAIL_VOID(isSupported()); + + sensorLogger = new(std::nothrow) PedometerLogger(); + IF_FAIL_VOID_TAG(sensorLogger, _E, "Memory allocation failed"); +} + +PedometerProvider::~PedometerProvider() +{ +} + +void PedometerProvider::getPrivilege(std::vector &privilege) +{ + privilege.push_back(PRIV_HEALTHINFO); +} + +bool PedometerProvider::isSupported() +{ + return util::getSystemInfoBool("tizen.org/feature/sensor.pedometer"); +} + +Querier* PedometerProvider::getQuerier(Json option) +{ + PedometerQuerier *querier = new(std::nothrow) PedometerQuerier(this, option); + IF_FAIL_RETURN_TAG(querier, NULL, _E, "Memory allocation failed"); + return querier; +} diff --git a/src/sensor/Pedometer.h b/src/sensor/Pedometer.h new file mode 100644 index 0000000..d4773fe --- /dev/null +++ b/src/sensor/Pedometer.h @@ -0,0 +1,37 @@ +/* + * 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 __CONTEXT_PEDOMETER_PROVIDER_H__ +#define __CONTEXT_PEDOMETER_PROVIDER_H__ + +#include "SensorProvider.h" + +namespace ctx { + + class PedometerProvider : public SensorProvider { + public: + PedometerProvider(); + ~PedometerProvider(); + + bool isSupported(); + void getPrivilege(std::vector &privilege); + + protected: + Querier* getQuerier(Json option); + }; +} + +#endif /* _CONTEXT_PEDOMETER_PROVIDER_H_ */ diff --git a/src/sensor/PedometerLogger.cpp b/src/sensor/PedometerLogger.cpp new file mode 100644 index 0000000..b091e58 --- /dev/null +++ b/src/sensor/PedometerLogger.cpp @@ -0,0 +1,158 @@ +/* + * 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 +#include +#include "TypesInternal.h" +#include "ClientInfo.h" +#include "PedometerLogger.h" + +using namespace ctx; + +PedometerLogger::PedometerLogger() : + __firstEvent(true) +{ + setSensor(HUMAN_PEDOMETER_SENSOR); + setPowerSave(false); + + /* Create the log table */ + executeQuery( + "CREATE TABLE IF NOT EXISTS " PEDOMETER_RECORD " (" \ + KEY_START_TIME " INTEGER NOT NULL, " \ + KEY_END_TIME " INTEGER NOT NULL PRIMARY KEY, " \ + KEY_WALK_STEPS " INTEGER NOT NULL, " \ + KEY_RUN_STEPS " INTEGER NOT NULL, " \ + KEY_DISTANCE " REAL NOT NULL, " \ + KEY_CALORIES " REAL NOT NULL" \ + ")"); + + ClientInfo clientInfo; + if (clientInfo.exist(SUBJ_SENSOR_PEDOMETER)) + start(); +} + +PedometerLogger::~PedometerLogger() +{ +} + +bool PedometerLogger::start() +{ + if (SensorProxy::isRunning()) + return true; + + _I(GREEN("Start to record")); + + if (SensorProxy::start()) { + flush(); + return true; + } + + return false; +} + +void PedometerLogger::stop() +{ + _I(GREEN("Stop recording")); + + SensorProxy::stop(); + __firstEvent = true; +} + +void PedometerLogger::onEvent(sensor_data_t *eventData) +{ + sensor_pedometer_data_t *pedometerData = reinterpret_cast(eventData); + uint64_t timestamp = getTime(); + + if (__firstEvent) { + _D("Baseline event"); + __firstEvent = false; + } else if (pedometerData->diffs_count == 0) { + _D("Single event"); + __recordSingle(pedometerData, timestamp); + } else { + _D("Batch event"); + __recordBatch(pedometerData, timestamp); + } + + __baseline.timestamp = timestamp; + __baseline.walkSteps = eventData->values[1]; + __baseline.runSteps = eventData->values[2]; + __baseline.distance = eventData->values[3]; + __baseline.calories = eventData->values[4]; + + _D("Baseline: %u, %u, %.3f, %.3f", + __baseline.walkSteps, __baseline.runSteps, __baseline.distance, __baseline.calories); + + removeExpired(SUBJ_SENSOR_PEDOMETER, PEDOMETER_RECORD, KEY_END_TIME); +} + +void PedometerLogger::__recordSingle(sensor_pedometer_data_t *eventData, uint64_t timestamp) +{ + DataRecord record; + record.walkSteps = static_cast(eventData->values[1]) - __baseline.walkSteps; + record.runSteps = static_cast(eventData->values[2]) - __baseline.runSteps; + record.distance = eventData->values[3] - __baseline.distance; + record.calories = eventData->values[4] - __baseline.calories; + + IF_FAIL_VOID_TAG(record.walkSteps + record.runSteps > 0, _D, "Skipping zero-count event"); + + char *query = sqlite3_mprintf( + "INSERT INTO " PEDOMETER_RECORD "(" \ + KEY_START_TIME ", " \ + KEY_END_TIME ", " \ + KEY_WALK_STEPS ", " \ + KEY_RUN_STEPS ", " \ + KEY_DISTANCE ", " \ + KEY_CALORIES ") " \ + "VALUES (%llu, %llu, %u, %u, %.3f, %.3f)", + __baseline.timestamp, timestamp, record.walkSteps, record.runSteps, record.distance, record.calories); + executeQuery(query); + sqlite3_free(query); +} + +void PedometerLogger::__recordBatch(sensor_pedometer_data_t *eventData, uint64_t timestamp) +{ + std::string query("INSERT INTO " PEDOMETER_RECORD "(" \ + KEY_START_TIME ", " \ + KEY_END_TIME ", " \ + KEY_WALK_STEPS ", " \ + KEY_RUN_STEPS ", " \ + KEY_DISTANCE ", " \ + KEY_CALORIES ") VALUES "); + char buffer[256]; + + for (int i = 0; i < eventData->diffs_count; ++i) { + if (eventData->diffs[i].walk_steps + eventData->diffs[i].run_steps == 0) { + _D("Skipping zero-count event"); + continue; + } + + /* TODO: check the timestamps.. they look strange.. */ + g_snprintf(buffer, sizeof(buffer), "(%llu, %llu, %d, %d, %.3f, %.3f),", + i == 0 ? __baseline.timestamp : SEC_TO_MS(static_cast(eventData->diffs[i-1].timestamp)), + SEC_TO_MS(static_cast(eventData->diffs[i].timestamp)), + eventData->diffs[i].walk_steps, + eventData->diffs[i].run_steps, + eventData->diffs[i].distance, + eventData->diffs[i].calories); + query += buffer; + } + + query.resize(query.size() - 1); + IF_FAIL_VOID_TAG(query.at(query.size() - 1) == ')', _D, "No records"); + + executeQuery(query.c_str()); +} diff --git a/src/sensor/PedometerLogger.h b/src/sensor/PedometerLogger.h new file mode 100644 index 0000000..e1d021b --- /dev/null +++ b/src/sensor/PedometerLogger.h @@ -0,0 +1,53 @@ +/* + * 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 __CONTEXT_PEDOMETER_LOGGER_H__ +#define __CONTEXT_PEDOMETER_LOGGER_H__ + +#include "SensorLogger.h" +#include "SensorProxy.h" + +namespace ctx { + + class PedometerLogger : public SensorLogger, public SensorProxy { + public: + PedometerLogger(); + ~PedometerLogger(); + + bool start(); + void stop(); + + protected: + void onEvent(sensor_data_t *eventData); + + private: + struct DataRecord { + uint64_t timestamp; + unsigned int walkSteps; + unsigned int runSteps; + float distance; + float calories; + }; + + void __recordSingle(sensor_pedometer_data_t *eventData, uint64_t timestamp); + void __recordBatch(sensor_pedometer_data_t *eventData, uint64_t timestamp); + + bool __firstEvent; + DataRecord __baseline; + }; +} + +#endif /* __CONTEXT_PEDOMETER_LOGGER_H__ */ diff --git a/src/sensor/PedometerQuerier.cpp b/src/sensor/PedometerQuerier.cpp new file mode 100644 index 0000000..37fa7de --- /dev/null +++ b/src/sensor/PedometerQuerier.cpp @@ -0,0 +1,71 @@ +/* + * 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 +#include +#include "TypesInternal.h" +#include "PedometerQuerier.h" + +#define PROJECTION \ + "SUM(" KEY_WALK_STEPS " + " KEY_RUN_STEPS ") AS " KEY_STEPS ", " \ + "SUM(" KEY_WALK_STEPS ") AS " KEY_WALK_STEPS ", " \ + "SUM(" KEY_RUN_STEPS ") AS " KEY_RUN_STEPS ", " \ + "SUM(" KEY_DISTANCE ") AS " KEY_DISTANCE ", " \ + "SUM(" KEY_CALORIES ") AS " KEY_CALORIES ", " \ + "MIN(" KEY_START_TIME ") AS " KEY_START_TIME ", " \ + "MAX(" KEY_END_TIME ") AS " KEY_END_TIME + +using namespace ctx; + +PedometerQuerier::PedometerQuerier(ContextProvider *provider, Json option) : + Querier(provider, option) +{ +} + +PedometerQuerier::~PedometerQuerier() +{ +} + +int PedometerQuerier::query(int startTime, int endTime) +{ + char *sql = sqlite3_mprintf( + "SELECT " PROJECTION \ + " FROM " PEDOMETER_RECORD \ + " WHERE " KEY_END_TIME " > %llu AND " KEY_END_TIME " <= %llu", + SEC_TO_MS(static_cast(startTime)), SEC_TO_MS(static_cast(endTime))); + + int ret = Querier::query(sql); + sqlite3_free(sql); + + return ret; +} + +int PedometerQuerier::query(int startTime, int endTime, int anchor, int interval) +{ + char *sql = sqlite3_mprintf( + "SELECT " PROJECTION \ + " FROM " PEDOMETER_RECORD \ + " WHERE " KEY_END_TIME " > %llu AND " KEY_END_TIME " <= %llu" \ + " GROUP BY ROUND((" KEY_END_TIME " - %llu) / %llu + 0.5)" \ + " ORDER BY " KEY_END_TIME " ASC", + SEC_TO_MS(static_cast(startTime)), SEC_TO_MS(static_cast(endTime)), + SEC_TO_MS(static_cast(anchor)), SEC_TO_MS(static_cast(interval))); + + int ret = Querier::query(sql); + sqlite3_free(sql); + + return ret; +} diff --git a/src/sensor/PedometerQuerier.h b/src/sensor/PedometerQuerier.h new file mode 100644 index 0000000..5cdc506 --- /dev/null +++ b/src/sensor/PedometerQuerier.h @@ -0,0 +1,34 @@ +/* + * 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 __CONTEXT_PEDOMETER_QUERIER_H__ +#define __CONTEXT_PEDOMETER_QUERIER_H__ + +#include "Querier.h" + +namespace ctx { + + class PedometerQuerier : public Querier { + public: + PedometerQuerier(ContextProvider *provider, Json option); + ~PedometerQuerier(); + + int query(int startTime, int endTime); + int query(int startTime, int endTime, int anchor, int interval); + }; +} + +#endif /* __CONTEXT_PEDOMETER_QUERIER_H__ */ diff --git a/src/sensor/Pressure.cpp b/src/sensor/Pressure.cpp new file mode 100644 index 0000000..b50caa2 --- /dev/null +++ b/src/sensor/Pressure.cpp @@ -0,0 +1,49 @@ +/* + * 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 +#include +#include "TypesInternal.h" +#include "PressureLogger.h" +#include "PressureQuerier.h" +#include "Pressure.h" + +using namespace ctx; + +PressureProvider::PressureProvider() : + SensorProvider(SUBJ_SENSOR_PRESSURE) +{ + IF_FAIL_VOID(isSupported()); + + sensorLogger = new(std::nothrow) PressureLogger(); + IF_FAIL_VOID_TAG(sensorLogger, _E, "Memory allocation failed"); +} + +PressureProvider::~PressureProvider() +{ +} + +bool PressureProvider::isSupported() +{ + return util::getSystemInfoBool("tizen.org/feature/sensor.barometer"); +} + +Querier* PressureProvider::getQuerier(Json option) +{ + PressureQuerier *querier = new(std::nothrow) PressureQuerier(this, option); + IF_FAIL_RETURN_TAG(querier, NULL, _E, "Memory allocation failed"); + return querier; +} diff --git a/src/sensor/Pressure.h b/src/sensor/Pressure.h new file mode 100644 index 0000000..d12efac --- /dev/null +++ b/src/sensor/Pressure.h @@ -0,0 +1,36 @@ +/* + * 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 __CONTEXT_PRESSURE_PROVIDER_H__ +#define __CONTEXT_PRESSURE_PROVIDER_H__ + +#include "SensorProvider.h" + +namespace ctx { + + class PressureProvider : public SensorProvider { + public: + PressureProvider(); + ~PressureProvider(); + + bool isSupported(); + + protected: + Querier* getQuerier(Json option); + }; +} + +#endif /* _CONTEXT_PRESSURE_PROVIDER_H_ */ diff --git a/src/sensor/PressureLogger.cpp b/src/sensor/PressureLogger.cpp new file mode 100644 index 0000000..0dcaca9 --- /dev/null +++ b/src/sensor/PressureLogger.cpp @@ -0,0 +1,104 @@ +/* + * 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 +#include +#include "TypesInternal.h" +#include "ClientInfo.h" +#include "PressureLogger.h" + +#define INSERTION_THRESHOLD 20000 +#define SAMPLING_INTERVAL 60000 +#define BATCH_LATENCY INT_MAX +#define MAX_QUERY_LENGTH 1000 + +using namespace ctx; + +PressureLogger::PressureLogger() +{ + setSensor(PRESSURE_SENSOR); + setPowerSave(false); + setSamplingInterval(SAMPLING_INTERVAL); + setBatchLatency(BATCH_LATENCY); + + /* Create the log table */ + executeQuery( + "CREATE TABLE IF NOT EXISTS " PRESSURE_RECORD " (" \ + KEY_UNIV_TIME " INTEGER NOT NULL PRIMARY KEY, " \ + KEY_PRESSURE " REAL NOT NULL" \ + ")"); + + ClientInfo clientInfo; + if (clientInfo.exist(SUBJ_SENSOR_PRESSURE)) + start(); +} + +PressureLogger::~PressureLogger() +{ +} + +bool PressureLogger::start() +{ + if (SensorProxy::isRunning()) + return true; + + _I(GREEN("Start to record")); + + __lastInsertionTime = getTime(); + __resetInsertionQuery(); + + return SensorProxy::start(); +} + +void PressureLogger::stop() +{ + _I(GREEN("Stop recording")); + + SensorProxy::stop(); +} + +void PressureLogger::onEvent(sensor_data_t *eventData) +{ + uint64_t receivedTime = getTime(); + __record(eventData, receivedTime); + removeExpired(SUBJ_SENSOR_PRESSURE, PRESSURE_RECORD, KEY_UNIV_TIME); +} + +void PressureLogger::__record(sensor_data_t *eventData, uint64_t receivedTime) +{ + char buffer[64]; + g_snprintf(buffer, sizeof(buffer), "(%llu, %.5f),", + getTime(eventData->timestamp), eventData->values[0]); + + __insertionQuery += buffer; + + if (receivedTime - __lastInsertionTime < INSERTION_THRESHOLD && __insertionQuery.size() < MAX_QUERY_LENGTH) + return; + + __insertionQuery.resize(__insertionQuery.size() - 1); + if (__insertionQuery.at(__insertionQuery.size() - 1) == ')') + executeQuery(__insertionQuery.c_str()); + + __lastInsertionTime = receivedTime; + __resetInsertionQuery(); +} + +void PressureLogger::__resetInsertionQuery() +{ + __insertionQuery = + "INSERT INTO " PRESSURE_RECORD \ + " (" KEY_UNIV_TIME ", " KEY_PRESSURE ") VALUES "; +} diff --git a/src/sensor/PressureLogger.h b/src/sensor/PressureLogger.h new file mode 100644 index 0000000..45d0c68 --- /dev/null +++ b/src/sensor/PressureLogger.h @@ -0,0 +1,45 @@ +/* + * 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 __CONTEXT_PRESSURE_LOGGER_H__ +#define __CONTEXT_PRESSURE_LOGGER_H__ + +#include "SensorLogger.h" +#include "SensorProxy.h" + +namespace ctx { + + class PressureLogger : public SensorLogger, public SensorProxy { + public: + PressureLogger(); + ~PressureLogger(); + + bool start(); + void stop(); + + protected: + void onEvent(sensor_data_t *eventData); + + private: + void __record(sensor_data_t *eventData, uint64_t receivedTime); + void __resetInsertionQuery(); + + uint64_t __lastInsertionTime; + std::string __insertionQuery; + }; +} + +#endif /* __CONTEXT_PRESSURE_LOGGER_H__ */ diff --git a/src/sensor/PressureQuerier.cpp b/src/sensor/PressureQuerier.cpp new file mode 100644 index 0000000..5e01662 --- /dev/null +++ b/src/sensor/PressureQuerier.cpp @@ -0,0 +1,92 @@ +/* + * 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 +#include +#include "TypesInternal.h" +#include "PressureQuerier.h" + +#define PROJECTION \ + "AVG(" KEY_PRESSURE ") AS " KEY_PRESSURE ", " \ + "MIN(" KEY_PRESSURE ") AS " KEY_MIN_PRESSURE ", " \ + "MAX(" KEY_PRESSURE ") AS " KEY_MAX_PRESSURE ", " \ + "AVG(" KEY_PRESSURE ") AS " KEY_AVG_PRESSURE ", " \ + "MIN(" KEY_UNIV_TIME ") AS " KEY_START_TIME ", " \ + "MAX(" KEY_UNIV_TIME ") AS " KEY_END_TIME + +#define PROJECTION_RAW \ + KEY_PRESSURE ", " \ + KEY_PRESSURE " AS " KEY_MIN_PRESSURE ", " \ + KEY_PRESSURE " AS " KEY_MAX_PRESSURE ", " \ + KEY_PRESSURE " AS " KEY_AVG_PRESSURE ", " \ + KEY_UNIV_TIME " AS " KEY_START_TIME ", " \ + KEY_UNIV_TIME " AS " KEY_END_TIME + +using namespace ctx; + +PressureQuerier::PressureQuerier(ContextProvider *provider, Json option) : + Querier(provider, option) +{ +} + +PressureQuerier::~PressureQuerier() +{ +} + +int PressureQuerier::queryRaw(int startTime, int endTime) +{ + char *sql = sqlite3_mprintf( + "SELECT " PROJECTION_RAW \ + " FROM " PRESSURE_RECORD \ + " WHERE " KEY_UNIV_TIME " > %llu AND " KEY_UNIV_TIME " <= %llu", + SEC_TO_MS(static_cast(startTime)), SEC_TO_MS(static_cast(endTime))); + + int ret = Querier::query(sql); + sqlite3_free(sql); + + return ret; +} + +int PressureQuerier::query(int startTime, int endTime) +{ + char *sql = sqlite3_mprintf( + "SELECT " PROJECTION \ + " FROM " PRESSURE_RECORD \ + " WHERE " KEY_UNIV_TIME " > %llu AND " KEY_UNIV_TIME " <= %llu", + SEC_TO_MS(static_cast(startTime)), SEC_TO_MS(static_cast(endTime))); + + int ret = Querier::query(sql); + sqlite3_free(sql); + + return ret; +} + +int PressureQuerier::query(int startTime, int endTime, int anchor, int interval) +{ + char *sql = sqlite3_mprintf( + "SELECT " PROJECTION \ + " FROM " PRESSURE_RECORD \ + " WHERE " KEY_UNIV_TIME " > %llu AND " KEY_UNIV_TIME " <= %llu" \ + " GROUP BY ROUND((" KEY_UNIV_TIME " - %llu) / %llu + 0.5)" \ + " ORDER BY " KEY_END_TIME " ASC", + SEC_TO_MS(static_cast(startTime)), SEC_TO_MS(static_cast(endTime)), + SEC_TO_MS(static_cast(anchor)), SEC_TO_MS(static_cast(interval))); + + int ret = Querier::query(sql); + sqlite3_free(sql); + + return ret; +} diff --git a/src/sensor/PressureQuerier.h b/src/sensor/PressureQuerier.h new file mode 100644 index 0000000..be1788c --- /dev/null +++ b/src/sensor/PressureQuerier.h @@ -0,0 +1,35 @@ +/* + * 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 __CONTEXT_PRESSURE_QUERIER_H__ +#define __CONTEXT_PRESSURE_QUERIER_H__ + +#include "Querier.h" + +namespace ctx { + + class PressureQuerier : public Querier { + public: + PressureQuerier(ContextProvider *provider, Json option); + ~PressureQuerier(); + + int queryRaw(int startTime, int endTime); + int query(int startTime, int endTime); + int query(int startTime, int endTime, int anchor, int interval); + }; +} + +#endif /* __CONTEXT_PRESSURE_QUERIER_H__ */ diff --git a/src/sensor/Querier.cpp b/src/sensor/Querier.cpp new file mode 100644 index 0000000..7cc0b9b --- /dev/null +++ b/src/sensor/Querier.cpp @@ -0,0 +1,84 @@ +/* + * 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 +#include +#include "Querier.h" + +using namespace ctx; + +Querier::Querier(ContextProvider *provider, Json option) : + __provider(provider), + __option(option) +{ +} + +Querier::~Querier() +{ +} + +int Querier::query(const char *sql) +{ + return __dbMgr.execute(0, sql, this) ? ERR_NONE : ERR_OPERATION_FAILED; +} + +int Querier::queryRaw(int startTime, int endTime) +{ + return ERR_INVALID_PARAMETER; +} + +int Querier::query(int startTime, int endTime) +{ + return ERR_INVALID_PARAMETER; +} + +int Querier::query(int startTime, int endTime, int anchor, int interval) +{ + return ERR_INVALID_PARAMETER; +} + +void Querier::onTableCreated(unsigned int queryId, int error) +{ +} + +void Querier::onInserted(unsigned int queryId, int error, int64_t rowId) +{ +} + +void Querier::onExecuted(unsigned int queryId, int error, std::vector& records) +{ + Json response; + __convertToResponse(records, response); + __provider->replyToRead(__option, error, response); + delete this; +} + +void Querier::__convertToResponse(std::vector &sqlResult, Json &response) +{ + std::list keys; + std::string val; + + response.set(NULL, KEY_RESULT_SIZE, static_cast(sqlResult.size())); + + for (Json &tuple : sqlResult) { + tuple.getKeys(&keys); + for (std::string &key : keys) { + tuple.get(NULL, key.c_str(), &val); + response.append(NULL, key.c_str(), val); + } + keys.clear(); + } +} diff --git a/src/sensor/Querier.h b/src/sensor/Querier.h new file mode 100644 index 0000000..0eed203 --- /dev/null +++ b/src/sensor/Querier.h @@ -0,0 +1,49 @@ +/* + * 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 __CONTEXT_QUERIER_H__ +#define __CONTEXT_QUERIER_H__ + +#include +#include + +namespace ctx { + + class Querier : public IDatabaseListener { + public: + Querier(ContextProvider *provider, Json option); + virtual ~Querier(); + + virtual int queryRaw(int startTime, int endTime); + virtual int query(int startTime, int endTime); + virtual int query(int startTime, int endTime, int anchor, int interval); + + protected: + int query(const char *sql); + void onTableCreated(unsigned int queryId, int error); + void onInserted(unsigned int queryId, int error, int64_t rowId); + void onExecuted(unsigned int queryId, int error, std::vector& records); + + private: + void __convertToResponse(std::vector &sqlResult, Json &response); + + DatabaseManager __dbMgr; + ContextProvider *__provider; + Json __option; + }; +} + +#endif /* __CONTEXT_QUERIER_H__ */ diff --git a/src/sensor/SensorLogger.cpp b/src/sensor/SensorLogger.cpp new file mode 100644 index 0000000..e2462ab --- /dev/null +++ b/src/sensor/SensorLogger.cpp @@ -0,0 +1,82 @@ +/* + * 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 +#include +#include +#include +#include +#include "TypesInternal.h" +#include "SensorLogger.h" + +using namespace ctx; + +SensorLogger::SensorLogger() : + __lastRemovalTime(0) +{ +} + +SensorLogger::~SensorLogger() +{ +} + +uint64_t SensorLogger::getTime() +{ + struct timeval tv; + double timestamp; + + gettimeofday(&tv, NULL); + timestamp = tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0; + return static_cast(round(timestamp)); +} + +uint64_t SensorLogger::getTime(unsigned long long monotonic) +{ + struct timespec ts; + double timestamp; + uint64_t currentTime = getTime(); + + if (abs(currentTime / 1000 - monotonic / 1000000) < SECONDS_PER_DAY) + return static_cast(round(monotonic / 1000.0)); + + clock_gettime(CLOCK_MONOTONIC, &ts); + timestamp = static_cast(currentTime) - (ts.tv_sec * 1000000000.0 + ts.tv_nsec) / 1000000.0 + monotonic / 1000.0; + return static_cast(round(timestamp)); +} + +bool SensorLogger::executeQuery(const char *query) +{ + return __dbMgr.execute(0, query, NULL); +} + +void SensorLogger::removeExpired(const char *subject, const char *tableName, const char *timeKey) +{ + uint64_t timestamp = getTime(); + + if (timestamp - __lastRemovalTime < SEC_TO_MS(SECONDS_PER_HOUR)) + return; + + char *query = sqlite3_mprintf( + "DELETE FROM %s WHERE %s < " \ + "%llu - (SELECT MAX(" KEY_RETENTION ") * 1000 FROM " CLIENT_INFO \ + " WHERE " KEY_SUBJECT "='%s')", + tableName, timeKey, timestamp, subject); + + __dbMgr.execute(0, query, NULL); + sqlite3_free(query); + + __lastRemovalTime = timestamp; +} diff --git a/src/sensor/SensorLogger.h b/src/sensor/SensorLogger.h new file mode 100644 index 0000000..eef4df3 --- /dev/null +++ b/src/sensor/SensorLogger.h @@ -0,0 +1,45 @@ +/* + * 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 __CONTEXT_SENSOR_LOGGER_H__ +#define __CONTEXT_SENSOR_LOGGER_H__ + +#include + +namespace ctx { + + class SensorLogger { + public: + SensorLogger(); + virtual ~SensorLogger(); + + virtual bool start() = 0; + virtual void stop() = 0; + + protected: + uint64_t getTime(); + uint64_t getTime(unsigned long long monotonic); + bool executeQuery(const char *query); + + virtual void removeExpired(const char *subject, const char *tableName, const char *timeKey); + + private: + uint64_t __lastRemovalTime; + DatabaseManager __dbMgr; + }; +} + +#endif /* __CONTEXT_SENSOR_LOGGER_H__ */ diff --git a/src/sensor/SensorProvider.cpp b/src/sensor/SensorProvider.cpp new file mode 100644 index 0000000..e205246 --- /dev/null +++ b/src/sensor/SensorProvider.cpp @@ -0,0 +1,154 @@ +/* + * 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 +#include +#include +#include "TypesInternal.h" +#include "SensorProvider.h" + +using namespace ctx; + +SensorProvider::SensorProvider(const char *subject) : + ContextProvider(subject), + sensorLogger(NULL) +{ +} + +SensorProvider::~SensorProvider() +{ + delete sensorLogger; +} + +int SensorProvider::subscribe(Json option, Json *requestResult) +{ + return ERR_NONE; +} + +int SensorProvider::unsubscribe(Json option) +{ + return ERR_NONE; +} + +int SensorProvider::read(Json option, Json *requestResult) +{ + int endTime = static_cast(time(NULL)) + 1; + int startTime = endTime - DEFAULT_QUERY_PERIOD - 1; + int anchor = -1; + int interval = -1; + + if (option.get(NULL, KEY_START_TIME, &startTime)) + IF_FAIL_RETURN(startTime >= 0, ERR_INVALID_PARAMETER); + + if (option.get(NULL, KEY_END_TIME, &endTime)) + IF_FAIL_RETURN(endTime >= 0, ERR_INVALID_PARAMETER); + + if (option.get(NULL, KEY_ANCHOR, &anchor)) + IF_FAIL_RETURN(anchor >= 0, ERR_INVALID_PARAMETER); + + if (option.get(NULL, KEY_INTERVAL, &interval)) + IF_FAIL_RETURN(interval >= 0, ERR_INVALID_PARAMETER); + + if (endTime >= 0 && startTime >= endTime) + return ERR_INVALID_PARAMETER; + + if (interval > 0 && anchor < 0) + anchor = endTime; + + if (anchor >= 0 && interval < 0) + interval = static_cast(ceil(static_cast(endTime - startTime) / SECONDS_PER_MINUTE)); + + int ret; + Querier *querier = getQuerier(option); + IF_FAIL_RETURN(querier, ERR_OPERATION_FAILED); + + if (interval == 0) + ret = querier->queryRaw(startTime, endTime); + else if (interval > 0) + ret = querier->query(startTime, endTime, anchor, interval * SECONDS_PER_MINUTE); + else + ret = querier->query(startTime, endTime); + + if (ret != ERR_NONE) + delete querier; + + return ret; +} + +int SensorProvider::write(Json data, Json *requestResult) +{ + IF_FAIL_RETURN(sensorLogger, ERR_OPERATION_FAILED); + + std::string operation; + std::string pkgId; + int retentionPeriod = DEFAULT_RETENTION; + + _J("Data", data); + + IF_FAIL_RETURN(data.get(NULL, KEY_OPERATION, &operation), ERR_INVALID_PARAMETER); + IF_FAIL_RETURN(data.get(NULL, KEY_CLIENT_PKG_ID, &pkgId), ERR_INVALID_PARAMETER); + + if (data.get(NULL, KEY_RETENTION, &retentionPeriod)) + retentionPeriod *= SECONDS_PER_HOUR; + + /* TODO: remove the operation & pkg id from the json */ + + if (operation == VAL_START) + return __addClient(pkgId, retentionPeriod, data); + else if (operation == VAL_STOP) + return __removeClient(pkgId); + + return ERR_NOT_SUPPORTED; +} + +int SensorProvider::__addClient(std::string pkgId, int retentionPeriod, Json option) +{ + Json tmp; + int ret; + + /* Check if the app already started Sensor recording */ + ret = __clientInfo.get(getSubject(), pkgId, tmp); + IF_FAIL_RETURN(ret != ERR_NONE, ERR_ALREADY_STARTED); + IF_FAIL_RETURN(ret == ERR_NO_DATA, ERR_OPERATION_FAILED); + + /* Store the app's request */ + if (!__clientInfo.set(getSubject(), pkgId, option, retentionPeriod)) + return ERR_OPERATION_FAILED; + + /* If not listening the sensor yet, start */ + sensorLogger->start(); + + return ERR_NONE; +} + +int SensorProvider::__removeClient(std::string pkgId) +{ + std::vector options; + int ret; + + /* Remove the app's request first */ + IF_FAIL_RETURN(__clientInfo.remove(getSubject(), pkgId), ERR_OPERATION_FAILED); + + /* Check if there is no client anymore */ + ret = __clientInfo.get(getSubject(), options); + IF_FAIL_RETURN(ret != ERR_NONE, ERR_NONE); + IF_FAIL_RETURN(ret == ERR_NO_DATA, ERR_OPERATION_FAILED); + + /* Stop listening */ + sensorLogger->stop(); + + return ERR_NONE; +} diff --git a/src/sensor/SensorProvider.h b/src/sensor/SensorProvider.h new file mode 100644 index 0000000..4a1cf5b --- /dev/null +++ b/src/sensor/SensorProvider.h @@ -0,0 +1,50 @@ +/* + * 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 __CONTEXT_SENSOR_PROVIDER_H__ +#define __CONTEXT_SENSOR_PROVIDER_H__ + +#include +#include "ClientInfo.h" +#include "SensorLogger.h" +#include "Querier.h" + +namespace ctx { + + class SensorProvider : public ContextProvider { + public: + SensorProvider(const char *subject); + virtual ~SensorProvider(); + + virtual int subscribe(Json option, Json *requestResult); + virtual int unsubscribe(Json option); + virtual int read(Json option, Json *requestResult); + virtual int write(Json data, Json *requestResult); + + protected: + virtual Querier* getQuerier(Json option) = 0; + + SensorLogger *sensorLogger; + + private: + int __addClient(std::string pkgId, int retentionPeriod, Json option); + int __removeClient(std::string pkgId); + + ClientInfo __clientInfo; + }; +} + +#endif /* _CONTEXT_SENSOR_PROVIDER_H_ */ diff --git a/src/sensor/SensorProxy.cpp b/src/sensor/SensorProxy.cpp new file mode 100644 index 0000000..f927ec1 --- /dev/null +++ b/src/sensor/SensorProxy.cpp @@ -0,0 +1,124 @@ +/* + * 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 +#include "SensorProxy.h" + +#define SENSOR_EVENT(X) (((int)(X) << 16) | 0x01) + +using namespace ctx; + +SensorProxy::SensorProxy() : + sensorHandle(-1), + sensorType(UNKNOWN_SENSOR), + powerSave(true), + samplingInterval(0), + batchLatency(0), + userData(NULL) +{ +} + +SensorProxy::~SensorProxy() +{ + stop(); +} + +void SensorProxy::setSensor(sensor_type_t type) +{ + sensorType = type; +} + +void SensorProxy::setPowerSave(bool ps) +{ + powerSave = ps; +} + +void SensorProxy::setSamplingInterval(unsigned int interval) +{ + samplingInterval = interval; +} + +void SensorProxy::setBatchLatency(unsigned int latency) +{ + batchLatency = latency; +} + +void SensorProxy::setUserData(void *data) +{ + userData = data; +} + +bool SensorProxy::start() +{ + _D("#Sensor = %#x", sensorType); + + sensor_t sensor = sensord_get_sensor(sensorType); + IF_FAIL_RETURN_TAG(sensor, false, _E, "Getting sensor failed"); + + sensorHandle = sensord_connect(sensor); + IF_FAIL_RETURN_TAG(sensorHandle >= 0, false, _E, "Connection failed"); + + if (!sensord_register_event(sensorHandle, SENSOR_EVENT(sensorType), samplingInterval, batchLatency, __eventCb, this)) { + _E("Event registration failed"); + sensord_disconnect(sensorHandle); + sensorHandle = -1; + return false; + } + + if (!sensord_start(sensorHandle, powerSave ? SENSOR_OPTION_DEFAULT : SENSOR_OPTION_ALWAYS_ON)) { + _E("Starting failed"); + sensord_unregister_event(sensorHandle, SENSOR_EVENT(sensorType)); + sensord_disconnect(sensorHandle); + sensorHandle = -1; + return false; + } + + return true; +} + +void SensorProxy::stop() +{ + IF_FAIL_VOID(sensorHandle >= 0); + + sensord_stop(sensorHandle); + sensord_unregister_event(sensorHandle, SENSOR_EVENT(sensorType)); + sensord_disconnect(sensorHandle); + sensorHandle = -1; +} + +void SensorProxy::flush() +{ + IF_FAIL_VOID(sensorHandle >= 0); + sensord_flush(sensorHandle); +} + +bool SensorProxy::isRunning() +{ + return sensorHandle >= 0; +} + +bool SensorProxy::isSupported(sensor_type_t type) +{ + sensor_t sensor = sensord_get_sensor(type); + return (sensor != NULL); +} + +void SensorProxy::__eventCb(sensor_t sensor, unsigned int eventType, sensor_data_t *eventData, void *cbData) +{ + SensorProxy *instance = static_cast(cbData); + instance->onEvent(eventData); +} diff --git a/src/sensor/SensorProxy.h b/src/sensor/SensorProxy.h new file mode 100644 index 0000000..d264668 --- /dev/null +++ b/src/sensor/SensorProxy.h @@ -0,0 +1,60 @@ +/* + * 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 __CONTEXT_SENSOR_PROXY_H__ +#define __CONTEXT_SENSOR_PROXY_H__ + +#include + +namespace ctx { + + class SensorProxy { + public: + SensorProxy(); + virtual ~SensorProxy(); + + void setSensor(sensor_type_t type); + void setPowerSave(bool ps); + void setSamplingInterval(unsigned int interval); + void setBatchLatency(unsigned int latency); + void setUserData(void *data); + + virtual bool start(); + virtual void stop(); + void flush(); + + protected: + int sensorHandle; + sensor_type_t sensorType; + bool powerSave; + unsigned int samplingInterval; + unsigned int batchLatency; + void *userData; + + static bool isSupported(sensor_type_t type); + + bool isRunning(); + + virtual void onEvent(sensor_data_t *eventData) = 0; + + private: + static void __eventCb(sensor_t sensor, unsigned int eventType, sensor_data_t *eventData, void *cbData); + }; + +} + +#endif /* __CONTEXT_SENSOR_PROXY_H__ */ diff --git a/src/sensor/TypesInternal.h b/src/sensor/TypesInternal.h new file mode 100644 index 0000000..a39a452 --- /dev/null +++ b/src/sensor/TypesInternal.h @@ -0,0 +1,40 @@ +/* + * 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 __CONTEXT_SENSOR_RECORDER_TYPES_INTERNAL_H__ +#define __CONTEXT_SENSOR_RECORDER_TYPES_INTERNAL_H__ + +/* Tables */ +#define PEDOMETER_RECORD "SensorPedometerRecord" +#define PRESSURE_RECORD "SensorPressureRecord" +#define CLIENT_INFO "SensorClientInfo" + +/* Privileges */ +#define PRIV_HEALTHINFO "healthinfo" + +/* Constants */ +#define SECONDS_PER_MINUTE 60 +#define SECONDS_PER_HOUR 3600 +#define SECONDS_PER_DAY 86400 + +/* Default Parameters */ +#define DEFAULT_RETENTION SECONDS_PER_HOUR /* 1 hour */ +#define DEFAULT_QUERY_PERIOD SECONDS_PER_DAY /* 1 day */ + +/* Time Conversions */ +#define SEC_TO_MS(X) ((X) * 1000) + +#endif /* __CONTEXT_SENSOR_RECORDER_TYPES_INTERNAL_H__ */ -- 2.34.1