2 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 #include "UserPlaces.h"
22 #include <MyPlaceTypes.h>
24 #include <DatabaseManager.h>
27 #define SO_PATH _LIBDIR_ "/context-service/libctx-prvd-my-place-places-detector.so"
29 typedef void (*places_detector_t)();
31 #define __GET_PLACES_QUERY "SELECT "\
32 PLACE_COLUMN_CATEG_ID ", "\
33 PLACE_COLUMN_CATEG_CONFIDENCE ", "\
34 PLACE_COLUMN_NAME ", "\
35 PLACE_COLUMN_LOCATION_VALID ", "\
36 PLACE_COLUMN_LOCATION_LATITUDE ", "\
37 PLACE_COLUMN_LOCATION_LONGITUDE ", "\
38 PLACE_COLUMN_LOCATION_ACCURACY ", "\
39 PLACE_COLUMN_WIFI_APS ", "\
40 PLACE_COLUMN_CREATE_DATE \
43 #define __GET_WIFI_APS_MAP_QUERY "SELECT "\
44 WIFI_APS_MAP_COLUMN_MAC ", "\
45 WIFI_APS_MAP_COLUMN_NETWORK_NAME \
46 " FROM " WIFI_APS_MAP_TABLE
48 #define __MYPLACE_SETTINGS_TABLE_COLUMNS \
49 MYPLACE_SETTINGS_COLUMN_KEY " TEXT NOT NULL UNIQUE, "\
50 MYPLACE_SETTINGS_COLUMN_VALUE " TEXT NOT NULL"\
52 #define __GET_USER_CONSENT_QUERY "SELECT "\
53 MYPLACE_SETTINGS_COLUMN_VALUE \
54 " FROM " MYPLACE_SETTINGS_TABLE \
55 " WHERE " MYPLACE_SETTINGS_COLUMN_KEY \
56 "='" MYPLACE_SETTING_KEY_USER_CONSENT "';"
58 ctx::UserPlaces::UserPlaces(PlaceRecogMode energyMode):
59 __visitDetector(nullptr),
62 __energyMode(energyMode)
65 __dbCreateMyPlaceSettingsTable();
70 ctx::UserPlaces::~UserPlaces()
75 ctx::Json ctx::UserPlaces::getPlaces()
77 std::vector<Json> records = __dbGetPlaces();
78 std::map<std::string, std::string> wifiAPsMap = __dbGetWifiAPsMap();
79 std::vector<std::shared_ptr<Place>> places = __placesFromJsons(records, wifiAPsMap);
80 return UserPlaces::__composeJson(places);
83 ctx::Json ctx::UserPlaces::__composeJson(std::vector<std::shared_ptr<Place>> places)
86 for (std::shared_ptr<ctx::Place> place : places) {
88 placeJson.set(NULL, PLACE_CATEG_ID, static_cast<int>(place->categId));
89 placeJson.set(NULL, PLACE_CATEG_CONFIDENCE, static_cast<double>(place->categConfidence));
90 placeJson.set(NULL, PLACE_NAME, place->name);
91 if (place->locationValid) {
92 ctx::Json locationJson;
93 locationJson.set(NULL, PLACE_LOCATION_LATITUDE, static_cast<double>(place->location.latitude));
94 locationJson.set(NULL, PLACE_LOCATION_LONGITUDE, static_cast<double>(place->location.longitude));
95 locationJson.set(NULL, PLACE_LOCATION_ACCURACY, static_cast<double>(place->location.accuracy));
96 placeJson.set(NULL, PLACE_LOCATION, locationJson);
98 if (place->wifiAps.size()) {
99 ctx::Json wifiApsListJson;
100 for (std::pair<std::string, std::string> ap : place->wifiAps) {
101 ctx::Json wifiApJson;
102 wifiApJson.set(NULL, PLACE_WIFI_AP_MAC, ap.first);
103 wifiApJson.set(NULL, PLACE_WIFI_AP_NETWORK_NAME, ap.second);
104 wifiApsListJson.append(NULL, PLACE_WIFI_APS, wifiApJson);
106 placeJson.set(NULL, PLACE_WIFI_APS, wifiApsListJson);
108 placeJson.set(NULL, PLACE_CREATE_DATE, static_cast<int64_t>(place->createDate));
109 data.append(NULL, PLACE_DATA_READ, placeJson);
111 _J("returns ", data);
115 void ctx::UserPlaces::setMode(PlaceRecogMode energyMode)
117 __energyMode = energyMode;
119 __visitDetector->setMode(energyMode);
122 bool ctx::UserPlaces::onTimerExpired(int timerId)
124 _D("Try to detect places from user visits");
125 GModule *soHandle = g_module_open(SO_PATH, G_MODULE_BIND_LAZY);
126 IF_FAIL_RETURN_TAG(soHandle, true, _E, "%s", g_module_error());
129 if (!g_module_symbol(soHandle, "detectPlaces", &symbol) || symbol == NULL) {
130 _E("%s", g_module_error());
131 g_module_close(soHandle);
135 places_detector_t detectPlaces = reinterpret_cast<places_detector_t>(symbol);
138 g_module_close(soHandle);
142 std::vector<ctx::Json> ctx::UserPlaces::__dbGetPlaces()
144 std::vector<Json> records;
145 DatabaseManager dbManager;
146 bool ret = dbManager.executeSync(__GET_PLACES_QUERY, &records);
147 _D("load places execute query result: %s", ret ? "SUCCESS" : "FAIL");
151 std::map<std::string, std::string> ctx::UserPlaces::__dbGetWifiAPsMap()
153 std::vector<Json> records;
154 std::map<std::string, std::string> wifiAPsMap;
155 DatabaseManager dbManager;
156 bool ret = dbManager.executeSync(__GET_WIFI_APS_MAP_QUERY, &records);
157 // TODO: add return statements if db fail
158 _D("load Wifi APs map (size = %d), result: %s", records.size(), ret ? "SUCCESS" : "FAIL");
159 std::string mac = "";
160 std::string networkName = "";
161 for (Json record : records) {
162 record.get(NULL, WIFI_APS_MAP_COLUMN_MAC, &mac);
163 record.get(NULL, WIFI_APS_MAP_COLUMN_NETWORK_NAME, &networkName);
164 wifiAPsMap.insert(std::pair<std::string, std::string>(mac, networkName));
169 std::shared_ptr<ctx::Place> ctx::UserPlaces::__placeFromJson(Json &row, std::map<std::string, std::string> &wifiAPsMap)
171 std::shared_ptr<Place> place = std::make_shared<Place>();
172 __placeCategoryFromJson(row, *place);
173 row.get(NULL, PLACE_COLUMN_NAME, &(place->name));
174 __placeLocationFromJson(row, *place);
175 __placeWifiAPsFromJson(row, wifiAPsMap, *place);
176 __placeCreateDateFromJson(row, *place);
177 _D("db_result: categId: %d; place: name: %s; locationValid: %d; latitude: %lf, longitude: %lf, createDate: %d", place->categId, place->name.c_str(), place->locationValid, place->location.latitude, place->location.longitude, place->createDate);
181 void ctx::UserPlaces::__placeCategoryFromJson(Json &row, ctx::Place &place)
184 row.get(NULL, PLACE_COLUMN_CATEG_ID, &categId);
185 // This is due to the fact the JSON module API interface doesn't handle enum
186 place.categId = static_cast<PlaceCategId>(categId);
189 void ctx::UserPlaces::__placeLocationFromJson(Json &row, ctx::Place &place)
191 int locationValidInt;
192 row.get(NULL, PLACE_COLUMN_LOCATION_VALID, &locationValidInt);
193 place.locationValid = (bool) locationValidInt;
194 row.get(NULL, PLACE_COLUMN_LOCATION_LATITUDE, &(place.location.latitude));
195 row.get(NULL, PLACE_COLUMN_LOCATION_LONGITUDE, &(place.location.longitude));
196 row.get(NULL, PLACE_COLUMN_LOCATION_ACCURACY, &(place.location.accuracy));
199 void ctx::UserPlaces::__placeWifiAPsFromJson(Json &row, std::map<std::string, std::string> &wifiAPsMap, ctx::Place &place)
202 row.get(NULL, PLACE_COLUMN_WIFI_APS, &wifiAps);
203 std::stringstream ss;
205 std::shared_ptr<MacSet> macSet = std::make_shared<MacSet>();
207 for (ctx::Mac mac : *macSet) {
208 place.wifiAps.insert(std::pair<std::string, std::string>(mac, wifiAPsMap[mac]));
212 void ctx::UserPlaces::__placeCreateDateFromJson(Json &row, ctx::Place &place)
215 row.get(NULL, PLACE_COLUMN_CREATE_DATE, &(createDate));
216 // This is due to the fact the JSON module API interface doesn't handle time_t
217 place.createDate = static_cast<time_t>(createDate);
220 std::vector<std::shared_ptr<ctx::Place>> ctx::UserPlaces::__placesFromJsons(std::vector<Json>& records, std::map<std::string, std::string> &wifiAPsMap)
222 std::vector<std::shared_ptr<Place>> places;
223 _D("db_result: number of all places: %d", records.size());
225 for (Json &row : records) {
226 std::shared_ptr<Place> place = __placeFromJson(row, wifiAPsMap);
227 places.push_back(place);
229 _D("number of all places in vector: %d", places.size());
233 void ctx::UserPlaces::__dbCreateMyPlaceSettingsTable()
235 DatabaseManager dbManager;
236 bool ret = dbManager.createTable(0, MYPLACE_SETTINGS_TABLE, __MYPLACE_SETTINGS_TABLE_COLUMNS);
237 _D("db: Myplace setting Table Creation Result: %s", ret ? "SUCCESS" : "FAIL");
240 void ctx::UserPlaces::setConsent(bool consent)
243 DatabaseManager dbManager;
244 std::vector<Json> records;
245 std::stringstream query;
246 query << "REPLACE INTO " MYPLACE_SETTINGS_TABLE \
247 " ( " MYPLACE_SETTINGS_COLUMN_KEY ", " MYPLACE_SETTINGS_COLUMN_VALUE " )" \
248 " VALUES ( '" MYPLACE_SETTING_KEY_USER_CONSENT "', '";
250 query << MYPLACE_SETTING_VALUE_TRUE;
254 query << MYPLACE_SETTING_VALUE_FALSE;
260 bool ret = dbManager.executeSync(query.str().c_str(), &records);
261 IF_FAIL_VOID_TAG(ret, _E, "Setting user consent (value = %d) to database failed", consent);
264 bool ctx::UserPlaces::getConsent()
267 DatabaseManager dbManager;
268 std::vector<Json> records;
269 bool ret = dbManager.executeSync(__GET_USER_CONSENT_QUERY, &records);
270 IF_FAIL_RETURN_TAG(ret, MYPLACE_SETTING_USER_CONSENT_DEFAULT, _E, "Getting user consent from database failed");
271 if (records.size()) {
272 std::string consentStr;
273 records[0].get(NULL, MYPLACE_SETTINGS_COLUMN_VALUE, &consentStr);
274 if (consentStr == MYPLACE_SETTING_VALUE_TRUE) {
275 _D("User consent value from db: TRUE");
277 } else if (consentStr == MYPLACE_SETTING_VALUE_FALSE) {
278 _D("User consent value from db: FALSE");
281 _E("Unknown user consent value \"%s\" from db, it should be \"%s\" or \"%s\"",
283 MYPLACE_SETTING_VALUE_TRUE,
284 MYPLACE_SETTING_VALUE_FALSE);
287 // consent record empty or unknown value
288 setConsent(MYPLACE_SETTING_USER_CONSENT_DEFAULT);
289 return MYPLACE_SETTING_USER_CONSENT_DEFAULT;
292 void ctx::UserPlaces::__start()
295 time_t now = std::time(nullptr);
296 __visitDetector = new(std::nothrow) VisitDetector(now, __energyMode);
297 if (__visitDetector == nullptr) {
298 _E("Cannot initialize VisitDetector");
301 __timerId = __timerManager.setAt( // execute once every night
302 PLACES_DETECTOR_TASK_START_HOUR,
303 PLACES_DETECTOR_TASK_START_MINUTE,
307 _E("timer set FAIL");
310 _D("timer set SUCCESS");
315 void ctx::UserPlaces::__stop()
318 if (__timerId >= 0) {
319 __timerManager.remove(__timerId);
322 if (__visitDetector) {
323 delete __visitDetector;
324 __visitDetector = nullptr;