b27fa3dda9c31a791edd43c0de653971cfc4c65d
[platform/core/context/context-provider.git] / src / sensor / pedometer / PedometerLogger.cpp
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <inttypes.h>
18 #include <sqlite3.h>
19 #include <SensorRecorderTypes.h>
20 #include "../TypesInternal.h"
21 #include "../ClientInfo.h"
22 #include "../TimeUtil.h"
23 #include "PedometerLogger.h"
24
25 #define MIN_INTERVAL    60000
26
27 using namespace ctx;
28
29 PedometerLogger::PedometerLogger() :
30         __firstEvent(true)
31 {
32         setSensor(HUMAN_PEDOMETER_SENSOR);
33         setPowerSave(false);
34
35         /* Create the log table */
36         executeQuery(
37                         "CREATE TABLE IF NOT EXISTS " PEDOMETER_RECORD " (" \
38                                 KEY_START_TIME " INTEGER NOT NULL, " \
39                                 KEY_END_TIME " INTEGER NOT NULL PRIMARY KEY, " \
40                                 KEY_WALK_STEPS " INTEGER NOT NULL, " \
41                                 KEY_RUN_STEPS " INTEGER NOT NULL, " \
42                                 KEY_DISTANCE " REAL NOT NULL, " \
43                                 KEY_CALORIES " REAL NOT NULL" \
44                         ")");
45
46         ClientInfo clientInfo;
47         if (clientInfo.exist(SUBJ_SENSOR_PEDOMETER))
48                 start();
49 }
50
51 PedometerLogger::~PedometerLogger()
52 {
53         stop();
54 }
55
56 bool PedometerLogger::start()
57 {
58         IF_FAIL_RETURN_TAG(!isRunning(), true, _D, "Started already");
59         _I(GREEN("Start to record"));
60
61         if (listen()) {
62                 flush();
63                 return true;
64         }
65
66         return false;
67 }
68
69 void PedometerLogger::stop()
70 {
71         IF_FAIL_VOID_TAG(isRunning(), _D, "Stopped already");
72         _I(GREEN("Stop recording"));
73
74         unlisten();
75         __firstEvent = true;
76 }
77
78 void PedometerLogger::flushCache(bool force)
79 {
80         DataRecord record;
81         record.walkSteps = __lastRecord.walkSteps - __baseline.walkSteps;
82         record.runSteps  = __lastRecord.runSteps - __baseline.runSteps;
83         record.distance  = __lastRecord.distance - __baseline.distance;
84         record.calories  = __lastRecord.calories - __baseline.calories;
85
86         if (record.walkSteps + record.runSteps > 0) {
87                 char *query = sqlite3_mprintf(
88                                 "INSERT INTO " PEDOMETER_RECORD " (" \
89                                         KEY_START_TIME ", " \
90                                         KEY_END_TIME ", " \
91                                         KEY_WALK_STEPS ", " \
92                                         KEY_RUN_STEPS ", " \
93                                         KEY_DISTANCE ", " \
94                                         KEY_CALORIES ") " \
95                                         "VALUES (%llu, %llu, %u, %u, %.3f, %.3f)",
96                                 __baseline.timestamp, __lastRecord.timestamp, record.walkSteps, record.runSteps, record.distance, record.calories);
97                 executeQuery(query);
98                 sqlite3_free(query);
99         }
100
101         __baseline = __lastRecord;
102 }
103
104 void PedometerLogger::onEvent(sensor_data_t *eventData)
105 {
106         sensor_pedometer_data_t *pedometerData = reinterpret_cast<sensor_pedometer_data_t*>(eventData);
107         uint64_t timestamp = TimeUtil::getTime();
108
109         if (__firstEvent) {
110                 __firstEvent = false;
111                 __setRecord(__lastRecord, timestamp, pedometerData);
112                 __baseline = __lastRecord;
113
114                 _SD("Baseline: %u, %u, %.3f, %.3f",
115                                 __baseline.walkSteps, __baseline.runSteps, __baseline.distance, __baseline.calories);
116
117         } else if (pedometerData->diffs_count == 0) {
118                 _SD("Single: %.0f, %.0f, %.3f, %.3f",
119                                 eventData->values[1], eventData->values[2], eventData->values[3], eventData->values[4]);
120                 __recordSingle(pedometerData, timestamp);
121
122         } else {
123                 _SD("Batch [%d]: %.0f, %.0f, %.3f, %.3f",
124                                 pedometerData->diffs_count,
125                                 eventData->values[1], eventData->values[2], eventData->values[3], eventData->values[4]);
126                 __recordBatch(pedometerData, timestamp);
127         }
128
129         removeExpired(SUBJ_SENSOR_PEDOMETER, PEDOMETER_RECORD, KEY_END_TIME);
130 }
131
132 void PedometerLogger::__recordSingle(sensor_pedometer_data_t *eventData, uint64_t timestamp)
133 {
134         if (timestamp - __baseline.timestamp >= MIN_INTERVAL)
135                 flushCache();
136
137         __setRecord(__lastRecord, timestamp, eventData);
138 }
139
140 void PedometerLogger::__recordBatch(sensor_pedometer_data_t *eventData, uint64_t timestamp)
141 {
142         flushCache();
143
144         std::string query("INSERT INTO " PEDOMETER_RECORD " (" \
145                                 KEY_START_TIME ", " \
146                                 KEY_END_TIME ", " \
147                                 KEY_WALK_STEPS ", " \
148                                 KEY_RUN_STEPS ", " \
149                                 KEY_DISTANCE ", " \
150                                 KEY_CALORIES ") VALUES ");
151         char buffer[256];
152
153         for (int i = 0; i < eventData->diffs_count; ++i) {
154                 if (eventData->diffs[i].walk_steps + eventData->diffs[i].run_steps == 0) {
155                         _D("Skipping zero-count event");
156                         continue;
157                 }
158
159                 /* TODO: check the timestamps.. they look strange.. */
160                 g_snprintf(buffer, sizeof(buffer), "(%" PRIu64 ", %" PRIu64 ", %d, %d, %.3f, %.3f),",
161                                 i == 0 ? __baseline.timestamp : SEC_TO_MS(static_cast<uint64_t>(eventData->diffs[i-1].timestamp)),
162                                 SEC_TO_MS(static_cast<uint64_t>(eventData->diffs[i].timestamp)),
163                                 eventData->diffs[i].walk_steps,
164                                 eventData->diffs[i].run_steps,
165                                 eventData->diffs[i].distance,
166                                 eventData->diffs[i].calories);
167                 query += buffer;
168         }
169
170         query.resize(query.size() - 1);
171         IF_FAIL_VOID_TAG(query.at(query.size() - 1) == ')', _D, "No records");
172
173         executeQuery(query.c_str());
174
175         __setRecord(__lastRecord, timestamp, eventData);
176         __baseline = __lastRecord;
177 }
178
179 void PedometerLogger::__setRecord(DataRecord &record, uint64_t timestamp, sensor_pedometer_data_t *eventData)
180 {
181         record.timestamp = timestamp;
182         record.walkSteps = static_cast<unsigned int>(eventData->values[1]);
183         record.runSteps  = static_cast<unsigned int>(eventData->values[2]);
184         record.distance  = eventData->values[3];
185         record.calories  = eventData->values[4];
186 }