fefb0e875ceb6996436b4adaaaeb4cbb8269382b
[platform/core/api/webapi-plugins.git] / src / humanactivitymonitor / humanactivitymonitor_manager.cc
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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 "humanactivitymonitor/humanactivitymonitor_manager.h"
18
19 #include <gesture_recognition.h>
20
21 #include "common/logger.h"
22
23 namespace extension {
24 namespace humanactivitymonitor {
25
26 using common::PlatformResult;
27 using common::ErrorCode;
28
29 HumanActivityMonitorManager::HumanActivityMonitorManager() {
30   LoggerD("Enter");
31 }
32
33 HumanActivityMonitorManager::~HumanActivityMonitorManager() {
34   LoggerD("Enter");
35   UnsetWristUpListener();
36   UnsetHrmListener();
37   UnsetGpsListener();
38 }
39
40 PlatformResult HumanActivityMonitorManager::Init() {
41   LoggerD("Enter");
42   return PlatformResult(ErrorCode::NO_ERROR);
43 }
44
45 PlatformResult HumanActivityMonitorManager::IsSupported(
46     const std::string& type) {
47
48   // check cache first
49   if (supported_.count(type)) {
50     return LogAndCreateResult(supported_[type]
51         ? ErrorCode::NO_ERROR
52         : ErrorCode::NOT_SUPPORTED_ERR);
53   }
54
55   int ret;
56   bool supported = false;
57   if (type == kActivityTypePedometer) {
58     // TODO(r.galka) no native api for pedometer
59     // so just pass it for not supported.
60   } else if (type == kActivityTypeWristUp) {
61     ret = gesture_is_supported(GESTURE_WRIST_UP, &supported);
62     if (ret != SENSOR_ERROR_NONE) {
63       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
64                             "WRIST_UP gesture check failed",
65                             ("gesture_is_supported(GESTURE_WRIST_UP), error: %d",ret));
66     }
67   } else if (type == kActivityTypeHrm) {
68     ret = sensor_is_supported(SENSOR_HRM, &supported);
69     if (ret != SENSOR_ERROR_NONE) {
70       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
71                             "HRM sensor check failed",
72                             ("sensor_is_supported(HRM), error: %d",ret));
73     }
74   } else if (type == kActivityTypeGps) {
75     supported = location_manager_is_supported_method(LOCATIONS_METHOD_GPS);
76   } else {
77     return LogAndCreateResult(ErrorCode::TYPE_MISMATCH_ERR);
78   }
79
80   supported_[type] = supported;
81
82   return LogAndCreateResult(supported_[type]
83       ? ErrorCode::NO_ERROR
84       : ErrorCode::NOT_SUPPORTED_ERR);
85 }
86
87 PlatformResult HumanActivityMonitorManager::SetListener(
88     const std::string& type, JsonCallback callback) {
89
90   PlatformResult result = IsSupported(type);
91   if (!result) {
92     return result;
93   }
94
95   if (type == kActivityTypePedometer) {
96     // TODO(r.galka) Not Supported in current implementation.
97   }
98
99   if (type == kActivityTypeWristUp) {
100     return SetWristUpListener(callback);
101   }
102
103   if (type == kActivityTypeHrm) {
104     return SetHrmListener(callback);
105   }
106
107   if (type == kActivityTypeGps) {
108     return SetGpsListener(callback);
109   }
110
111   return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Undefined activity type");
112 }
113
114 PlatformResult HumanActivityMonitorManager::UnsetListener(
115     const std::string& type) {
116
117   PlatformResult result = IsSupported(type);
118   if (!result) {
119     return result;
120   }
121
122   if (type == kActivityTypePedometer) {
123     // TODO(r.galka) Not Supported in current implementation.
124   }
125
126   if (type == kActivityTypeWristUp) {
127     return UnsetWristUpListener();
128   }
129
130   if (type == kActivityTypeHrm) {
131     return UnsetHrmListener();
132   }
133
134   if (type == kActivityTypeGps) {
135     return UnsetGpsListener();
136   }
137
138   return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Undefined activity type");
139 }
140
141 PlatformResult HumanActivityMonitorManager::GetHumanActivityData(
142     const std::string& type,
143     picojson::value* data) {
144
145   LoggerD("Enter");
146   if (type == kActivityTypePedometer) {
147     // TODO(r.galka) Not Supported in current implementation.
148   }
149
150   if (type == kActivityTypeWristUp) {
151     return LogAndCreateResult(ErrorCode::NOT_SUPPORTED_ERR);
152   }
153
154   if (type == kActivityTypeHrm) {
155     return GetHrmData(data);
156   }
157
158   if (type == kActivityTypeGps) {
159     return GetGpsData(data);
160   }
161
162   return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Undefined activity type");
163 }
164
165 // WRIST_UP
166 PlatformResult HumanActivityMonitorManager::SetWristUpListener(
167     JsonCallback callback) {
168   LoggerD("Enter");
169   int ret;
170
171   ret = gesture_create(&gesture_handle_);
172   if (ret != GESTURE_ERROR_NONE) {
173     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
174                           "Failed to create WRIST_UP listener",
175                           ("Failed to create WRIST_UP handle, error: %d",ret));
176   }
177
178   ret = gesture_start_recognition(gesture_handle_,
179                                   GESTURE_WRIST_UP,
180                                   GESTURE_OPTION_DEFAULT,
181                                   OnWristUpEvent,
182                                   this);
183   if (ret != GESTURE_ERROR_NONE) {
184     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
185                           "Failed to start WRIST_UP listener",
186                           ("Failed to start WRIST_UP listener, error: %d",ret));
187   }
188
189   wrist_up_event_callback_ = callback;
190
191   return PlatformResult(ErrorCode::NO_ERROR);
192 }
193
194 PlatformResult HumanActivityMonitorManager::UnsetWristUpListener() {
195   LoggerD("Enter");
196
197   if (gesture_handle_) {
198     int ret = gesture_stop_recognition(gesture_handle_);
199     if (ret != GESTURE_ERROR_NONE) {
200       LOGGER(ERROR) << "Failed to stop WRIST_UP detection, error: " << ret;
201     }
202
203     ret = gesture_release(gesture_handle_);
204     if (ret != GESTURE_ERROR_NONE) {
205       LOGGER(ERROR) << "Failed to release WRIST_UP handle, error: " << ret;
206     }
207   }
208
209   wrist_up_event_callback_ = nullptr;
210
211   return PlatformResult(ErrorCode::NO_ERROR);
212 }
213
214 void HumanActivityMonitorManager::OnWristUpEvent(gesture_type_e gesture,
215                                                  const gesture_data_h data,
216                                                  double timestamp,
217                                                  gesture_error_e error,
218                                                  void* user_data) {
219   LoggerD("Enter");
220   HumanActivityMonitorManager* manager =
221       static_cast<HumanActivityMonitorManager*>(user_data);
222
223   if (!manager->wrist_up_event_callback_) {
224     LOGGER(ERROR) << "No WRIST_UP event callback registered, skipping.";
225     return;
226   }
227
228   picojson::value v = picojson::value(); // null value
229   manager->wrist_up_event_callback_(&v);
230 }
231
232 // HRM
233 PlatformResult HumanActivityMonitorManager::SetHrmListener(
234     JsonCallback callback) {
235   LoggerD("Enter");
236   sensor_h hrm_sensor;
237   int ret;
238
239   ret = sensor_get_default_sensor(SENSOR_HRM, &hrm_sensor);
240   if (ret != SENSOR_ERROR_NONE) {
241     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
242                           "Failed to get HRM sensor",
243                           ("Failed to get HRM sensor, error: %d",ret));
244   }
245
246   ret = sensor_create_listener(hrm_sensor, &hrm_sensor_listener_);
247   if (ret != SENSOR_ERROR_NONE) {
248     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
249                           "Failed to create HRM sensor listener",
250                           ("Failed to create HRM sensor listener, error: %d",ret));
251   }
252
253   ret = sensor_listener_set_event_cb(hrm_sensor_listener_,
254                                      0,
255                                      OnHrmSensorEvent,
256                                      this);
257   if (ret != SENSOR_ERROR_NONE) {
258     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
259                           "Failed to set HRM sensor listener",
260                           ("Failed to set HRM sensor listener, error: %d",ret));
261   }
262
263   ret = sensor_listener_start(hrm_sensor_listener_);
264   if (ret != SENSOR_ERROR_NONE) {
265     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
266                           "Failed to start HRM sensor listener",
267                           ("Failed to start HRM sensor listener, error: %d",ret));
268   }
269
270   hrm_event_callback_ = callback;
271
272   return PlatformResult(ErrorCode::NO_ERROR);
273 }
274
275 PlatformResult HumanActivityMonitorManager::UnsetHrmListener() {
276   LoggerD("Enter");
277
278   if (hrm_sensor_listener_) {
279     int ret = sensor_listener_stop(hrm_sensor_listener_);
280     if (ret != SENSOR_ERROR_NONE) {
281       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
282                             "Failed to stop HRM sensor",
283                             ("Failed to stop HRM sensor, error: "%d,ret));
284     }
285
286     ret = sensor_listener_unset_event_cb(hrm_sensor_listener_);
287     if (ret != SENSOR_ERROR_NONE) {
288       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
289                             "Failed to unset HRM sensor listener",
290                             ("Failed to unset HRM sensor listener, error: %d",ret));
291     }
292
293     ret = sensor_destroy_listener(hrm_sensor_listener_);
294     if (ret != SENSOR_ERROR_NONE) {
295       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
296                             "Failed to destroy HRM sensor listener",
297                             ("Failed to destroy HRM sensor listener, error: %d",ret));
298     }
299   }
300
301   hrm_event_callback_ = nullptr;
302
303   return PlatformResult(ErrorCode::NO_ERROR);
304 }
305
306 static PlatformResult ConvertHrmEvent(sensor_event_s* event,
307                                       picojson::object* data) {
308   LOGGER(DEBUG) << "Sensor event:";
309   LOGGER(DEBUG) << "  |- accuracy: " << event->accuracy;
310   LOGGER(DEBUG) << "  |- timestamp: " << event->timestamp;
311   LOGGER(DEBUG) << "  |- value_count: " << event->value_count;
312
313   if (event->value_count < 2) {
314     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "To few values of HRM event");
315   }
316
317   LOGGER(DEBUG) << "  |- values[0]: " << event->values[0];
318   LOGGER(DEBUG) << "  |- values[1]: " << event->values[1];
319
320   float hr = floor( event->values[0] + 0.5); // heart beat rate 0 ~ 220 integer (bpm)
321
322   // there are no public native api for peak to peak interval.
323   // but RRI = (60 / HR) * 1000
324   // or unofficially values[1] is rri (0 ~ 5000 ms)
325   float rri = floor(event->values[1] + 0.5);
326
327
328   (*data)["heartRate"] = picojson::value(static_cast<double>(hr));
329   (*data)["rRInterval"] = picojson::value(static_cast<double>(rri));
330
331   return PlatformResult(ErrorCode::NO_ERROR);
332 }
333
334 void HumanActivityMonitorManager::OnHrmSensorEvent(
335     sensor_h /*sensor*/, sensor_event_s *event, void *user_data) {
336
337   LoggerD("Enter");
338   HumanActivityMonitorManager* manager =
339       static_cast<HumanActivityMonitorManager*>(user_data);
340
341   if (!manager->hrm_event_callback_) {
342     LOGGER(ERROR) << "No HRM event callback registered, skipping.";
343     return;
344   }
345
346   picojson::value hrm_data = picojson::value(picojson::object());
347   PlatformResult result = ConvertHrmEvent(event,
348                                           &hrm_data.get<picojson::object>());
349   if (!result) {
350     LOGGER(ERROR) << "Failed to convert HRM data: " << result.message();
351     return;
352   }
353
354   manager->hrm_event_callback_(&hrm_data);
355 }
356
357 PlatformResult HumanActivityMonitorManager::GetHrmData(picojson::value* data) {
358   LoggerD("Enter");
359   if (!hrm_sensor_listener_) {
360     return LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR);
361   }
362
363   int ret;
364
365   sensor_event_s event;
366   ret = sensor_listener_read_data(hrm_sensor_listener_, &event);
367   if (ret != SENSOR_ERROR_NONE) {
368     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
369                           "Failed to get HRM sensor data",
370                           ("Failed to get HRM sensor data, error: %d",ret));
371   }
372
373   *data = picojson::value(picojson::object());
374   PlatformResult result = ConvertHrmEvent(&event,
375                                           &data->get<picojson::object>());
376   if (!result) {
377     return result;
378   }
379
380   return PlatformResult(ErrorCode::NO_ERROR);
381 }
382
383 // GPS
384 PlatformResult HumanActivityMonitorManager::SetGpsListener(
385     JsonCallback callback) {
386   LoggerD("Enter");
387   int ret;
388
389   ret = location_manager_create(LOCATIONS_METHOD_GPS, &location_handle_);
390   if (ret != LOCATIONS_ERROR_NONE) {
391     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
392                           "Failed to create location manager",
393                           ("Failed to create location manager, error: %d",ret));
394   }
395
396   ret = location_manager_set_location_batch_cb(location_handle_,
397                                                OnGpsEvent,
398                                                1, // batch_interval
399                                                120, // batch_period
400                                                this);
401   if (ret != LOCATIONS_ERROR_NONE) {
402     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
403                           "Failed to set location listener",
404                           ("Failed to set location listener, error: %d",ret));
405   }
406
407   ret = location_manager_start_batch(location_handle_);
408   if (ret != LOCATIONS_ERROR_NONE) {
409     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
410                           "Failed to start location manager",
411                           ("Failed to start location manager, error: %d",ret));
412   }
413
414   gps_event_callback_ = callback;
415
416   return PlatformResult(ErrorCode::NO_ERROR);
417 }
418
419 PlatformResult HumanActivityMonitorManager::UnsetGpsListener() {
420   LoggerD("Enter");
421
422   if (location_handle_) {
423     int ret = location_manager_stop_batch(location_handle_);
424     if (ret != LOCATIONS_ERROR_NONE) {
425       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
426                             "Failed to stop location manager",
427                             ("Failed to stop location manager, error: %d",ret));
428     }
429
430     ret = location_manager_unset_location_batch_cb(location_handle_);
431     if (ret != LOCATIONS_ERROR_NONE) {
432       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
433                             "Failed to unset location listener",
434                             ("Failed to unset location listener, error: %d",ret));
435     }
436
437     ret = location_manager_destroy(location_handle_);
438     if (ret != LOCATIONS_ERROR_NONE) {
439       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
440                             "Failed to destroy location manager",
441                             ("Failed to destroy location manager, error: %d",ret));
442     }
443   }
444
445   gps_event_callback_ = nullptr;
446
447   return PlatformResult(ErrorCode::NO_ERROR);
448 }
449
450 static bool ConvertGpsEvent(double latitude, double longitude, double altitude,
451                             double speed, double direction, double horizontal,
452                             double vertical, time_t timestamp,
453                             void* user_data) {
454   LoggerD("Enter");
455   picojson::array* gps_info_array = static_cast<picojson::array*>(user_data);
456
457   picojson::value gps_info = picojson::value(picojson::object());
458   picojson::object& gps_info_o = gps_info.get<picojson::object>();
459
460   gps_info_o["latitude"] = picojson::value(latitude);
461   gps_info_o["longitude"] = picojson::value(longitude);
462   gps_info_o["altitude"] = picojson::value(altitude);
463   gps_info_o["speed"] = picojson::value(speed);
464   // TODO(r.galka) errorRange not available in CAPI
465   gps_info_o["errorRange"] = picojson::value(static_cast<double>(0));
466   gps_info_o["timestamp"] = picojson::value(static_cast<double>(timestamp));
467
468   gps_info_array->push_back(gps_info);
469
470   return true;
471 }
472
473 void HumanActivityMonitorManager::OnGpsEvent(int num_of_location,
474                                              void *user_data) {
475   LoggerD("Enter");
476   HumanActivityMonitorManager* manager =
477       static_cast<HumanActivityMonitorManager*>(user_data);
478
479   if (!manager->gps_event_callback_) {
480     LOGGER(ERROR) << "No GPS event callback registered, skipping.";
481     return;
482   }
483
484   if (0 == num_of_location) {
485     LOGGER(ERROR) << "No GPS locations available, skipping.";
486     return;
487   }
488
489   picojson::value gps_info = picojson::value(picojson::array());
490   int ret = location_manager_foreach_location_batch(
491       manager->location_handle_,
492       ConvertGpsEvent,
493       &gps_info.get<picojson::array>());
494   if (ret != LOCATIONS_ERROR_NONE) {
495     LOGGER(ERROR) << "Failed to convert location, error: " << ret;
496     return;
497   }
498
499   manager->gps_event_callback_(&gps_info);
500 }
501
502 PlatformResult HumanActivityMonitorManager::GetGpsData(picojson::value* data) {
503   LoggerD("Enter");
504   if (!location_handle_) {
505     return LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR);
506   }
507
508   int ret;
509   double altitude, latitude, longitude, climb,
510       direction, speed, horizontal, vertical;
511   location_accuracy_level_e level;
512   time_t timestamp;
513   ret = location_manager_get_location(location_handle_, &altitude, &latitude,
514                                       &longitude, &climb, &direction, &speed,
515                                       &level, &horizontal, &vertical,
516                                       &timestamp);
517   if (ret != LOCATIONS_ERROR_NONE) {
518     return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to get location",
519                               ("Failed to get location, error: %d",ret));
520   }
521
522   *data = picojson::value(picojson::array());
523   ConvertGpsEvent(latitude, longitude, altitude, speed, direction, horizontal,
524                   vertical, timestamp, &data->get<picojson::array>());
525
526   return PlatformResult(ErrorCode::NO_ERROR);
527 }
528
529 }  // namespace humanactivitymonitor
530 }  // namespace extension