[ham] Fixed sleep recorder, returned value
[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 <activity_recognition.h>
20 #include <gesture_recognition.h>
21 #include <location_batch.h>
22 #include <sensor.h>
23 #include <sensor_internal.h>
24 #include <system_info.h>
25 #include <mutex>
26
27 #include "common/logger.h"
28 #include "common/optional.h"
29 #include "common/picojson.h"
30 #include "common/scope_exit.h"
31 #include "common/tools.h"
32
33 namespace extension {
34 namespace humanactivitymonitor {
35
36 using common::PlatformResult;
37 using common::ErrorCode;
38 using common::tools::ReportError;
39 using common::tools::ReportSuccess;
40
41 typedef std::map<sensor_recorder_data_e, const std::string&> SensorRecorderDataMap;
42 typedef std::map<sensor_recorder_query_e, const std::string&> SensorRecorderQueryMap;
43
44 namespace {
45
46 const std::string kActivityTypePedometer = "PEDOMETER";
47 const std::string kActivityTypeWristUp = "WRIST_UP";
48 const std::string kActivityTypeHrm = "HRM";
49 const std::string kActivityTypeSleepMonitor = "SLEEP_MONITOR";
50 const std::string kActivityTypePressure = "PRESSURE";
51 const std::string kActivityTypeSleepDetector = "SLEEP_DETECTOR";
52 const std::string kActivityTypeStressMonitor = "STRESS_MONITOR";
53
54 const std::string kSleepStateAwake = "AWAKE";
55 const std::string kSleepStateAsleep = "ASLEEP";
56 const std::string kSleepStateUnknown = "UNKNOWN";
57
58 const std::string kCallbackInterval = "callbackInterval";
59 const std::string kSampleInterval = "sampleInterval";
60
61 const std::string kStatus = "status";
62 const std::string kTimestamp = "timestamp";
63 const std::string kStressScore = "stressScore";
64
65 const std::string kStepStatus = "stepStatus";
66 const std::string kSpeed = "speed";
67 const std::string kWalkingFrequency = "walkingFrequency";
68 const std::string kCumulativeDistance = "cumulativeDistance";
69 const std::string kCumulativeCalorie = "cumulativeCalorie";
70 const std::string kCumulativeTotalStepCount = "cumulativeTotalStepCount";
71 const std::string kCumulativeWalkStepCount = "cumulativeWalkStepCount";
72 const std::string kCumulativeRunStepCount = "cumulativeRunStepCount";
73 const std::string kStepCountDifferences = "stepCountDifferences";
74 const std::string kStepCountDifference = "stepCountDifference";
75
76 const std::string kAccumulativeDistance = "accumulativeDistance";
77 const std::string kAccumulativeCalorie = "accumulativeCalorie";
78 const std::string kAccumulativeTotalStepCount = "accumulativeTotalStepCount";
79 const std::string kAccumulativeWalkStepCount = "accumulativeWalkStepCount";
80 const std::string kAccumulativeRunStepCount = "accumulativeRunStepCount";
81
82 const std::string kRecordedStartTime = "startTime";
83 const std::string kRecordedEndTime = "endTime";
84 const std::string kRecordedHeartRate = "heartRate";
85
86 const std::string kRecordedDistance = "distance";
87 const std::string kRecordedCalorie = "calorie";
88 const std::string kRecordedTotalStepCount = "totalStepCount";
89 const std::string kRecordedWalkStepCount = "walkStepCount";
90 const std::string kRecordedRunStepCount = "runStepCount";
91
92 const std::string kRecordedMin = "min";
93 const std::string kRecordedMax = "max";
94 const std::string kRecordedAverage = "average";
95
96 const std::string kRecordedAnchorTime = "anchorTime";
97 const std::string kRecordedInterval = "interval";
98
99 ErrorCode getErrorCode(const int errorCode) {
100   ScopeLogger();
101   switch (errorCode) {
102     case SENSOR_ERROR_IO_ERROR:
103       return ErrorCode::IO_ERR;
104     case SENSOR_ERROR_NOT_SUPPORTED:
105       return ErrorCode::NOT_SUPPORTED_ERR;
106     case SENSOR_ERROR_PERMISSION_DENIED:
107       return ErrorCode::PERMISSION_DENIED_ERR;
108     case SENSOR_ERROR_NOT_AVAILABLE:
109       return ErrorCode::SERVICE_NOT_AVAILABLE_ERR;
110     case SENSOR_ERROR_NO_DATA:
111       return ErrorCode::NOT_FOUND_ERR;
112     case SENSOR_ERROR_INVALID_PARAMETER:
113       return ErrorCode::INVALID_VALUES_ERR;
114     case SENSOR_ERROR_OUT_OF_MEMORY:
115     case SENSOR_ERROR_OPERATION_FAILED:
116     case SENSOR_ERROR_NOT_NEED_CALIBRATION:
117     default:
118       return ErrorCode::ABORT_ERR;
119   }
120 }
121
122 // helper structure, allows easier access to data values
123 struct PedometerDataWrapper : public sensor_pedometer_data_t {
124   inline float steps() const {
125     return values[0];
126   }
127
128   inline float walk_steps() const {
129     return values[1];
130   }
131
132   inline float run_steps() const {
133     return values[2];
134   }
135
136   inline float distance() const {
137     return values[3];
138   }
139
140   inline float calories() const {
141     return values[4];
142   }
143
144   inline float speed() const {
145     return values[5];
146   }
147
148   inline float frequency() const {
149     return values[6];
150   }
151
152   inline sensor_pedometer_state_e state() const {
153     return static_cast<sensor_pedometer_state_e>(values[7]);
154   }
155 };
156
157 static int64_t getCurrentTimeStamp(unsigned long long evTime) {
158   ScopeLogger();
159   struct timespec t;
160   unsigned long long systemCurrentTime = 0;
161   unsigned long long realCurrentTime = 0;
162   unsigned long long timeDiff = 0;
163   int64_t timeStamp = 0;
164
165   // get current system monotonic  time
166   clock_gettime(CLOCK_MONOTONIC, &t);
167   systemCurrentTime =
168       ((unsigned long long)(t.tv_sec) * 1000000000LL + t.tv_nsec) / 1000000;  // convert millisecond
169   timeDiff = (systemCurrentTime - (evTime / 1000));
170
171   // get current epoch time(millisecond)
172   clock_gettime(CLOCK_REALTIME, &t);
173   realCurrentTime = ((unsigned long long)(t.tv_sec) * 1000000000LL + t.tv_nsec) / 1000000;
174   timeStamp = static_cast<int64_t>(realCurrentTime - timeDiff);
175
176   return timeStamp;
177 }
178
179 void InsertStepDifference(float step_difference, int64_t timestamp, picojson::array* out) {
180   ScopeLogger();
181
182   picojson::object d;
183
184   d.insert(std::make_pair(kStepCountDifference, picojson::value(step_difference)));
185   d.insert(std::make_pair(kTimestamp, picojson::value(static_cast<float>(timestamp))));
186
187   out->push_back(picojson::value{d});
188 }
189
190 std::string FromSensorPedometerState(sensor_pedometer_state_e e) {
191   switch (e) {
192     case SENSOR_PEDOMETER_STATE_STOP:
193       return "NOT_MOVING";
194
195     case SENSOR_PEDOMETER_STATE_WALK:
196       return "WALKING";
197
198     case SENSOR_PEDOMETER_STATE_RUN:
199       return "RUNNING";
200
201     case SENSOR_PEDOMETER_STATE_UNKNOWN:
202     default:
203       return "UNKNOWN";
204   }
205 }
206
207 PlatformResult ConvertRecordedTime(void* data, picojson::object* obj) {
208   ScopeLogger("convert_recorded_time");
209
210   time_t start_time, end_time;
211
212   int ret = sensor_recorder_data_get_time(data, &start_time, &end_time);
213   if (SENSOR_ERROR_NONE != ret) {
214     return LogAndCreateResult(getErrorCode(ret), "Failed to get time",
215                               ("Failed to get time, error: %d (%s)", ret, get_error_message(ret)));
216   }
217
218   obj->insert(std::make_pair(kRecordedStartTime, picojson::value(static_cast<double>(start_time))));
219   obj->insert(std::make_pair(kRecordedEndTime, picojson::value(static_cast<double>(end_time))));
220
221   return PlatformResult(ErrorCode::NO_ERROR);
222 }
223
224 PlatformResult ConvertRecordedInt(void* data, picojson::object* obj,
225                                   const SensorRecorderDataMap& map) {
226   ScopeLogger();
227
228   int ret = SENSOR_ERROR_NONE;
229   int tmp = 0;
230
231   for (auto& it : map) {
232     ret = sensor_recorder_data_get_int(data, it.first, &tmp);
233     if (SENSOR_ERROR_NONE != ret) {
234       return LogAndCreateResult(
235           getErrorCode(ret), "Failed to get int value",
236           ("Failed to get int value, error: %d (%s)", ret, get_error_message(ret)));
237     }
238
239     obj->insert(std::make_pair(it.second, picojson::value(static_cast<double>(tmp))));
240   }
241
242   return PlatformResult(ErrorCode::NO_ERROR);
243 }
244
245 PlatformResult ConvertRecordedDouble(void* data, picojson::object* obj,
246                                      const SensorRecorderDataMap& map) {
247   ScopeLogger();
248
249   int ret = SENSOR_ERROR_NONE;
250   double tmp = 0;
251
252   for (auto& it : map) {
253     ret = sensor_recorder_data_get_double(data, it.first, &tmp);
254     if (SENSOR_ERROR_NONE != ret) {
255       return LogAndCreateResult(
256           getErrorCode(ret), "Failed to get double value",
257           ("Failed to get double value, error: %d (%s)", ret, get_error_message(ret)));
258     }
259
260     obj->insert(std::make_pair(it.second, picojson::value(static_cast<double>(tmp))));
261   }
262
263   return PlatformResult(ErrorCode::NO_ERROR);
264 }
265
266 }  // namespace
267
268 const std::string kActivityTypeGps = "GPS";
269
270 class HumanActivityMonitorManager::Monitor {
271  public:
272   class GestureMonitor;
273   class SensorMonitor;
274   class GpsMonitor;
275   class PedometerMonitor;
276
277   explicit Monitor(const std::string& t) : type_(t) {
278     ScopeLogger("type %s", type().c_str());
279   }
280
281   virtual ~Monitor() {
282     ScopeLogger("type %s", type().c_str());
283   }
284
285   std::string type() const {
286     return type_;
287   }
288
289   JsonCallback& event_callback() {
290     return event_callback_;
291   }
292
293   PlatformResult SetListener(JsonCallback callback, const picojson::value& args) {
294     ScopeLogger("type %s", type().c_str());
295
296     auto result = IsSupported();
297     if (!result) {
298       return result;
299     }
300
301     result = SetListenerImpl(args);
302     if (!result) {
303       return result;
304     }
305
306     event_callback_ = callback;
307     return result;
308   }
309
310   PlatformResult UnsetListener() {
311     ScopeLogger("type %s", type().c_str());
312
313     auto result = IsSupported();
314     if (!result) {
315       return result;
316     }
317
318     result = UnsetListenerImpl();
319     if (!result) {
320       return result;
321     }
322
323     event_callback_ = nullptr;
324     return result;
325   }
326
327   PlatformResult GetData(picojson::value* data) {
328     ScopeLogger("type %s", type().c_str());
329
330     auto result = IsSupported();
331     if (!result) {
332       return result;
333     }
334
335     return GetDataImpl(data);
336   }
337
338   PlatformResult StartDataRecorder(int interval, int retention_period) {
339     ScopeLogger("type %s", type().c_str());
340
341     auto result = IsSupported();
342     if (!result) {
343       return result;
344     }
345
346     return StartDataRecorderImpl(interval, retention_period);
347   }
348
349   PlatformResult StopDataRecorder() {
350     ScopeLogger("type %s", type().c_str());
351
352     return StopDataRecorderImpl();
353   }
354
355   PlatformResult ReadRecorderData(picojson::array* data, const picojson::value& query) {
356     ScopeLogger("type %s", type().c_str());
357
358     auto result = IsSupported();
359     if (!result) {
360       return result;
361     }
362
363     return ReadRecorderDataImpl(data, query);
364   }
365
366  protected:
367   virtual PlatformResult IsSupportedImpl(bool* supported) const {
368     ScopeLogger("type %s", type().c_str());
369     *supported = false;
370     return PlatformResult(ErrorCode::NO_ERROR);
371   }
372
373   virtual PlatformResult SetListenerImpl(const picojson::value& args) {
374     ScopeLogger("type %s", type().c_str());
375     return LogAndCreateResult(ErrorCode::NOT_SUPPORTED_ERR, "NOT_SUPPORTED_ERR");
376   }
377
378   virtual PlatformResult UnsetListenerImpl() {
379     ScopeLogger("type %s", type().c_str());
380     return LogAndCreateResult(ErrorCode::NOT_SUPPORTED_ERR, "NOT_SUPPORTED_ERR");
381   }
382
383   virtual PlatformResult GetDataImpl(picojson::value* data) const {
384     ScopeLogger("type %s", type().c_str());
385     return LogAndCreateResult(ErrorCode::NOT_SUPPORTED_ERR, "NOT_SUPPORTED_ERR");
386   }
387
388   virtual PlatformResult StartDataRecorderImpl(int interval, int retention_period) const {
389     ScopeLogger("type %s", type().c_str());
390     return LogAndCreateResult(ErrorCode::NOT_SUPPORTED_ERR, "NOT_SUPPORTED_ERR");
391   }
392
393   virtual PlatformResult StopDataRecorderImpl() const {
394     ScopeLogger("type %s", type().c_str());
395     return LogAndCreateResult(ErrorCode::NOT_SUPPORTED_ERR, "NOT_SUPPORTED_ERR");
396   }
397
398   virtual PlatformResult ReadRecorderDataImpl(picojson::array* data, const picojson::value& query) {
399     ScopeLogger("type %s", type().c_str());
400     return LogAndCreateResult(ErrorCode::NOT_SUPPORTED_ERR, "NOT_SUPPORTED_ERR");
401   }
402
403  public:
404   PlatformResult IsSupported() {
405     ScopeLogger("type %s", type().c_str());
406
407     if (!is_supported_) {
408       bool is_supported = false;
409       auto res = IsSupportedImpl(&is_supported);
410       if (!res) {
411         return res;
412       } else {
413         is_supported_ = is_supported;
414       }
415     }
416
417     if (*is_supported_) {
418       return PlatformResult(ErrorCode::NO_ERROR);
419     } else {
420       return LogAndCreateResult(ErrorCode::NOT_SUPPORTED_ERR, "NOT_SUPPORTED_ERR");
421     }
422   }
423
424  private:
425   std::string type_;
426   common::optional<bool> is_supported_;
427   JsonCallback event_callback_;
428 };
429
430 class HumanActivityMonitorManager::Monitor::GestureMonitor
431     : public HumanActivityMonitorManager::Monitor {
432  public:
433   explicit GestureMonitor(const std::string& t) : Monitor(t), handle_(nullptr) {
434     ScopeLogger("type %s", type().c_str());
435   }
436
437   virtual ~GestureMonitor() override {
438     ScopeLogger("type %s", type().c_str());
439     UnsetListenerImpl();
440   }
441
442  protected:
443   virtual PlatformResult IsSupportedImpl(bool* s) const override {
444     ScopeLogger("type %s", type().c_str());
445
446     bool supported = false;
447
448     int ret = gesture_is_supported(GESTURE_WRIST_UP, &supported);
449     if (GESTURE_ERROR_NONE != ret) {
450       if (ret == GESTURE_ERROR_NOT_SUPPORTED) {
451         return LogAndCreateResult(ErrorCode::NOT_SUPPORTED_ERR, "WRIST_UP gesture check failed",
452                                   ("gesture_is_supported(GESTURE_WRIST_UP), error: %d (%s)", ret,
453                                    get_error_message(ret)));
454       } else {
455         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "WRIST_UP gesture check failed",
456                                   ("gesture_is_supported(GESTURE_WRIST_UP), error: %d (%s)", ret,
457                                    get_error_message(ret)));
458       }
459     }
460
461     *s = supported;
462     return PlatformResult(ErrorCode::NO_ERROR);
463   }
464
465   virtual PlatformResult SetListenerImpl(const picojson::value&) override {
466     ScopeLogger("type %s", type().c_str());
467
468     if (!handle_) {
469       int ret = gesture_create(&handle_);
470       if (GESTURE_ERROR_NONE != ret) {
471         return LogAndCreateResult(
472             ErrorCode::UNKNOWN_ERR, "Failed to create WRIST_UP listener",
473             ("Failed to create WRIST_UP handle, error: %d (%s)", ret, get_error_message(ret)));
474       }
475
476       ret = gesture_start_recognition(handle_, GESTURE_WRIST_UP, GESTURE_OPTION_DEFAULT,
477                                       OnWristUpEvent, this);
478       if (GESTURE_ERROR_NONE != ret) {
479         return LogAndCreateResult(
480             ErrorCode::UNKNOWN_ERR, "Failed to start WRIST_UP listener",
481             ("Failed to start WRIST_UP listener, error: %d (%s)", ret, get_error_message(ret)));
482       }
483     }
484
485     return PlatformResult(ErrorCode::NO_ERROR);
486   }
487
488   virtual PlatformResult UnsetListenerImpl() override {
489     ScopeLogger("type %s", type().c_str());
490
491     if (handle_) {
492       int ret = gesture_stop_recognition(handle_);
493       if (GESTURE_ERROR_NONE != ret) {
494         LoggerE("Failed to stop WRIST_UP detection, error: %d", ret);
495       }
496
497       ret = gesture_release(handle_);
498       if (GESTURE_ERROR_NONE != ret) {
499         LoggerE("Failed to release WRIST_UP handle, error: %d", ret);
500       }
501
502       handle_ = nullptr;
503     }
504
505     return PlatformResult(ErrorCode::NO_ERROR);
506   }
507
508   // GetData is not supported by gesture monitor
509
510  private:
511   static void OnWristUpEvent(gesture_type_e gesture, const gesture_data_h data, double timestamp,
512                              gesture_error_e error, void* user_data) {
513     ScopeLogger();
514
515     auto monitor = static_cast<GestureMonitor*>(user_data);
516     auto& callback = monitor->event_callback();
517
518     if (!callback) {
519       LoggerE("No WRIST_UP event callback registered, skipping.");
520       return;
521     }
522
523     picojson::value v = picojson::value(picojson::object());
524     callback(&v);
525   }
526
527   gesture_h handle_;
528 };
529
530 class HumanActivityMonitorManager::Monitor::SensorMonitor
531     : public HumanActivityMonitorManager::Monitor {
532  public:
533   using SensorEventConverter =
534       std::function<PlatformResult(sensor_event_s* event, picojson::object* o)>;
535   using SensorRecordedConverter = std::function<PlatformResult(void* data, picojson::object* o)>;
536
537   SensorMonitor(const std::string& t, sensor_type_e s, const SensorEventConverter& c,
538                 const SensorRecordedConverter& r)
539       : Monitor(t),
540         converter_(c),
541         converter_recorded_(r),
542         sensor_(s),
543         handle_(nullptr),
544         recorded_data_(nullptr) {
545     ScopeLogger("type %s", type().c_str());
546   }
547
548   virtual ~SensorMonitor() override {
549     ScopeLogger("type %s", type().c_str());
550     UnsetListenerImpl();
551   }
552
553  protected:
554   virtual PlatformResult IsSupportedImpl(bool* s) const override {
555     ScopeLogger("type %s", type().c_str());
556
557     bool supported = false;
558
559     int ret = sensor_is_supported(sensor_, &supported);
560     if (SENSOR_ERROR_NONE != ret) {
561       return LogAndCreateResult(
562           ErrorCode::UNKNOWN_ERR, "Sensor support check failed",
563           ("sensor_is_supported(%d), error: %d (%s)", sensor_, ret, get_error_message(ret)));
564     }
565
566     *s = supported;
567     return PlatformResult(ErrorCode::NO_ERROR);
568   }
569
570   virtual PlatformResult SetListenerImpl(const picojson::value& args) override {
571     ScopeLogger("type %s", type().c_str());
572
573     if (!handle_) {
574       sensor_h sensor_handle = nullptr;
575       int ret = sensor_get_default_sensor(sensor_, &sensor_handle);
576
577       if (SENSOR_ERROR_NONE != ret) {
578         return LogAndCreateResult(
579             ErrorCode::UNKNOWN_ERR, "Failed to get default sensor",
580             ("Failed to get (%d) sensor, error: %d (%s)", sensor_, ret, get_error_message(ret)));
581       }
582
583       ret = sensor_create_listener(sensor_handle, &handle_);
584       if (SENSOR_ERROR_NONE != ret) {
585         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to create sensor listener",
586                                   ("Failed to create (%d) sensor listener, error: %d (%s)", sensor_,
587                                    ret, get_error_message(ret)));
588       }
589
590       ret = sensor_listener_set_option(handle_, SENSOR_OPTION_ALWAYS_ON);
591       if (SENSOR_ERROR_NONE != ret) {
592         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to set sensor listener option",
593                                   ("Failed to set (%d) sensor listener option, error: %d (%s)",
594                                    sensor_, ret, get_error_message(ret)));
595       }
596
597       int interval = 0;
598       auto& js_interval = args.get(kCallbackInterval);
599
600       if (js_interval.is<double>()) {
601         interval = js_interval.get<double>();
602         LoggerD("callbackInterval: %d", interval);
603       }
604
605       ret = sensor_listener_set_event_cb(handle_, interval, OnSensorEvent, this);
606       if (SENSOR_ERROR_NONE != ret) {
607         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to set sensor listener",
608                                   ("Failed to set (%d) sensor listener, error: %d (%s)", sensor_,
609                                    ret, get_error_message(ret)));
610       }
611
612       ret = sensor_listener_start(handle_);
613       if (SENSOR_ERROR_NONE != ret) {
614         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to start sensor listener",
615                                   ("Failed to start (%d) sensor listener, error: %d (%s)", sensor_,
616                                    ret, get_error_message(ret)));
617       }
618     }
619
620     return PlatformResult(ErrorCode::NO_ERROR);
621   }
622
623   virtual PlatformResult UnsetListenerImpl() override {
624     ScopeLogger("type %s", type().c_str());
625
626     if (handle_) {
627       int ret = sensor_listener_stop(handle_);
628       if (SENSOR_ERROR_NONE != ret) {
629         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to stop sensor listener",
630                                   ("Failed to stop (%d) sensor listener, error: %d (%s)", sensor_,
631                                    ret, get_error_message(ret)));
632       }
633
634       ret = sensor_listener_unset_event_cb(handle_);
635       if (SENSOR_ERROR_NONE != ret) {
636         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to unset sensor listener",
637                                   ("Failed to unset (%d) sensor listener, error: %d (%s)", sensor_,
638                                    ret, get_error_message(ret)));
639       }
640
641       ret = sensor_destroy_listener(handle_);
642       if (SENSOR_ERROR_NONE != ret) {
643         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to destroy sensor listener",
644                                   ("Failed to destroy (%d) sensor listener, error: %d (%s)",
645                                    sensor_, ret, get_error_message(ret)));
646       }
647
648       handle_ = nullptr;
649     }
650
651     return PlatformResult(ErrorCode::NO_ERROR);
652   }
653
654   virtual PlatformResult GetDataImpl(picojson::value* data) const override {
655     ScopeLogger("type %s", type().c_str());
656
657     if (!handle_) {
658       return LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "SERVICE_NOT_AVAILABLE_ERR");
659     }
660
661     sensor_event_s event = {0};
662     int ret = sensor_listener_read_data(handle_, &event);
663
664     if (SENSOR_ERROR_NONE != ret) {
665       return LogAndCreateResult(
666           ErrorCode::UNKNOWN_ERR, "Failed to get sensor data",
667           ("Failed to get (%d) sensor data, error: %d (%s)", sensor_, ret, get_error_message(ret)));
668     }
669
670     if (SENSOR_HUMAN_PEDOMETER == sensor_) {
671       // read data of pedometer does not have valid diff[] , so diff_count set 0
672       const auto pedometer_data = (PedometerDataWrapper*)(&event);
673       pedometer_data->diffs_count = 0;
674     }
675
676     *data = picojson::value(picojson::object());
677     auto result = converter_(&event, &data->get<picojson::object>());
678     if (!result) {
679       return result;
680     }
681
682     return PlatformResult(ErrorCode::NO_ERROR);
683   }
684
685   virtual PlatformResult StartDataRecorderImpl(int interval, int retention_period) const override {
686     ScopeLogger("type %s", type().c_str());
687
688     sensor_recorder_option_h option = nullptr;
689
690     int ret = sensor_recorder_create_option(&option);
691     if (SENSOR_ERROR_NONE != ret) {
692       return LogAndCreateResult(getErrorCode(ret), "Failed to create recorder option",
693                                 ("Failed to create (%d) recorder option, error: %d (%s)", sensor_,
694                                  ret, get_error_message(ret)));
695     }
696
697     SCOPE_EXIT {
698       sensor_recorder_destroy_option(option);
699     };
700
701     auto result = SetOptions(&option, interval, retention_period);
702     if (!result) {
703       return result;
704     }
705
706     ret = sensor_recorder_start(sensor_, option);
707     if (SENSOR_ERROR_NONE != ret) {
708       return LogAndCreateResult(
709           getErrorCode(ret), "Failed to start recording",
710           ("Failed to start (%d) recording, error: %d (%s)", sensor_, ret, get_error_message(ret)));
711     }
712
713     return PlatformResult(ErrorCode::NO_ERROR);
714   }
715
716   virtual PlatformResult StopDataRecorderImpl() const override {
717     ScopeLogger("type %s", type().c_str());
718
719     int ret = sensor_recorder_stop(sensor_);
720     if (SENSOR_ERROR_NONE != ret) {
721       return LogAndCreateResult(
722           getErrorCode(ret), "Failed to stop recording",
723           ("Failed to stop (%d) recording, error: %d (%s)", sensor_, ret, get_error_message(ret)));
724     }
725
726     return PlatformResult(ErrorCode::NO_ERROR);
727   }
728
729   virtual PlatformResult ReadRecorderDataImpl(picojson::array* data,
730                                               const picojson::value& query) override {
731     ScopeLogger("type %s", type().c_str());
732
733     std::lock_guard<std::mutex> lock(mutex_);
734     this->recorded_data_ = data;
735
736     sensor_recorder_query_h query_h = nullptr;
737     int ret = sensor_recorder_create_query(&query_h);
738     if (SENSOR_ERROR_NONE != ret) {
739       return LogAndCreateResult(
740           getErrorCode(ret), "Failed to create query",
741           ("Failed to create (%d) query, error: %d (%s)", sensor_, ret, get_error_message(ret)));
742     }
743
744     SCOPE_EXIT {
745       sensor_recorder_destroy_query(query_h);
746     };
747
748     if (!query.is<picojson::null>()) {
749       auto result = SetQuery(&query_h, query);
750       if (!result) {
751         return result;
752       }
753     }
754
755     ret =
756         sensor_recorder_read_sync(sensor_, query_h, SensorRecordedDataCb, static_cast<void*>(this));
757     if (SENSOR_ERROR_NONE != ret) {
758       return LogAndCreateResult(getErrorCode(ret), "Failed to read recorded data",
759                                 ("Failed to read (%d) recorded data, error: %d (%s)", sensor_, ret,
760                                  get_error_message(ret)));
761     }
762
763     return PlatformResult(ErrorCode::NO_ERROR);
764   }
765
766   void addRecordedData(picojson::value* data) {
767     ScopeLogger();
768     recorded_data_->push_back(*data);
769   }
770
771   SensorEventConverter converter_;
772   SensorRecordedConverter converter_recorded_;
773
774  private:
775   static void OnSensorEvent(sensor_h, sensor_event_s* event, void* user_data) {
776     ScopeLogger();
777
778     auto monitor = static_cast<SensorMonitor*>(user_data);
779     auto& callback = monitor->event_callback();
780
781     if (!callback) {
782       LoggerE("No sensor event callback registered, skipping.");
783       return;
784     }
785
786     picojson::value sensor_data{picojson::object{}};
787
788     auto result = monitor->converter_(event, &sensor_data.get<picojson::object>());
789     if (!result) {
790       LoggerE("Failed to convert sensor data: %s", result.message().c_str());
791       return;
792     }
793
794     callback(&sensor_data);
795   }
796
797   static bool SensorRecordedDataCb(sensor_type_e type, void* data, int remains,
798                                    sensor_error_e error, void* user_data) {
799     ScopeLogger();
800
801     auto monitor = static_cast<SensorMonitor*>(user_data);
802
803     picojson::value val = picojson::value(picojson::object());
804     picojson::object* obj = &val.get<picojson::object>();
805
806     auto result = monitor->converter_recorded_(data, obj);
807     if (result) {
808       monitor->addRecordedData(&val);
809     }
810
811     return true;  // continue
812   }
813
814   PlatformResult SetOptions(sensor_recorder_option_h* option, int interval,
815                             int retention_period) const {
816     ScopeLogger();
817
818     int ret = SENSOR_ERROR_NONE;
819
820     if (SENSOR_HRM == sensor_) {
821       ret = sensor_recorder_option_set_int(*option, SENSOR_RECORDER_OPTION_INTERVAL, interval);
822
823       if (SENSOR_ERROR_NONE != ret) {
824         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to set recorder option",
825                                   ("Failed to set (%d) recorder option, error: %d (%s)", sensor_,
826                                    ret, get_error_message(ret)));
827       }
828     }
829
830     ret = sensor_recorder_option_set_int(*option, SENSOR_RECORDER_OPTION_RETENTION_PERIOD,
831                                          retention_period);
832     if (SENSOR_ERROR_NONE != ret) {
833       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to set recorder option",
834                                 ("Failed to set (%d) recorder option, error: %d (%s)", sensor_, ret,
835                                  get_error_message(ret)));
836     }
837
838     return PlatformResult(ErrorCode::NO_ERROR);
839   }
840
841   PlatformResult SetQuery(sensor_recorder_query_h* query_h, const picojson::value& query) const {
842     ScopeLogger();
843
844     SensorRecorderQueryMap map_query{
845         {SENSOR_RECORDER_QUERY_START_TIME, kRecordedStartTime},
846         {SENSOR_RECORDER_QUERY_END_TIME, kRecordedEndTime},
847     };
848
849     if (SENSOR_HUMAN_PEDOMETER == sensor_ || SENSOR_PRESSURE == sensor_) {
850       map_query.insert(std::make_pair(SENSOR_RECORDER_QUERY_ANCHOR_TIME, kRecordedAnchorTime));
851       map_query.insert(std::make_pair(SENSOR_RECORDER_QUERY_TIME_INTERVAL, kRecordedInterval));
852     }
853
854     for (auto& it : map_query) {
855       int val = -1;
856       if (query.get(it.second).is<double>()) {
857         val = query.get(it.second).get<double>();
858         if (0 <= val) {
859           int ret;
860           if (SENSOR_RECORDER_QUERY_TIME_INTERVAL != it.first) {
861             ret = sensor_recorder_query_set_time(*query_h, it.first, val);
862           } else {
863             ret = sensor_recorder_query_set_int(*query_h, it.first, val);
864           }
865           if (SENSOR_ERROR_NONE != ret) {
866             return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to set query parameter",
867                                       ("Failed to set (%d) query parameter, error: %d (%s)",
868                                        sensor_, ret, get_error_message(ret)));
869           }
870         }
871       }
872     }
873
874     return PlatformResult(ErrorCode::NO_ERROR);
875   }
876
877   sensor_type_e sensor_;
878   sensor_listener_h handle_;
879   picojson::array* recorded_data_;
880   std::mutex mutex_;
881 };
882
883 class HumanActivityMonitorManager::Monitor::PedometerMonitor
884     : public HumanActivityMonitorManager::Monitor::SensorMonitor {
885  private:
886   bool is_first_read;
887
888  public:
889   PedometerMonitor()
890       : SensorMonitor(kActivityTypePedometer, SENSOR_HUMAN_PEDOMETER, nullptr, nullptr),
891         is_first_read(true) {
892     ScopeLogger();
893     converter_ = [this](sensor_event_s* event, picojson::object* data) -> PlatformResult {
894
895       ScopeLogger("Entered into asynchronous function, convert_pedometer");
896
897       const auto pedometer_data = (PedometerDataWrapper*)event;
898
899       static PedometerDataWrapper initial_pedometer_data;
900
901       if (this->is_first_read) {
902         initial_pedometer_data = *pedometer_data;
903         this->is_first_read = false;
904       }
905
906       static float steps_so_far = 0.0;
907
908       const auto state = pedometer_data->state();
909
910       data->insert(std::make_pair(kStepStatus, picojson::value(FromSensorPedometerState(state))));
911       data->insert(std::make_pair(kSpeed, picojson::value(pedometer_data->speed())));
912       data->insert(std::make_pair(kWalkingFrequency, picojson::value(pedometer_data->frequency())));
913
914       data->insert(std::make_pair(
915           kCumulativeDistance,
916           picojson::value(pedometer_data->distance() - initial_pedometer_data.distance())));
917       data->insert(std::make_pair(
918           kCumulativeCalorie,
919           picojson::value(pedometer_data->calories() - initial_pedometer_data.calories())));
920       data->insert(std::make_pair(
921           kCumulativeTotalStepCount,
922           picojson::value(pedometer_data->steps() - initial_pedometer_data.steps())));
923       data->insert(std::make_pair(
924           kCumulativeWalkStepCount,
925           picojson::value(pedometer_data->walk_steps() - initial_pedometer_data.walk_steps())));
926       data->insert(std::make_pair(
927           kCumulativeRunStepCount,
928           picojson::value(pedometer_data->run_steps() - initial_pedometer_data.run_steps())));
929
930       data->insert(
931           std::make_pair(kAccumulativeDistance, picojson::value(pedometer_data->distance())));
932       data->insert(
933           std::make_pair(kAccumulativeCalorie, picojson::value(pedometer_data->calories())));
934       data->insert(
935           std::make_pair(kAccumulativeTotalStepCount, picojson::value(pedometer_data->steps())));
936       data->insert(std::make_pair(kAccumulativeWalkStepCount,
937                                   picojson::value(pedometer_data->walk_steps())));
938       data->insert(
939           std::make_pair(kAccumulativeRunStepCount, picojson::value(pedometer_data->run_steps())));
940
941       auto& diffs =
942           data->insert(std::make_pair(kStepCountDifferences, picojson::value{picojson::array{}}))
943               .first->second.get<picojson::array>();
944       LoggerD("pedometer_data->diffs_count: %d", pedometer_data->diffs_count);
945       if (pedometer_data->diffs_count > 0) {
946         for (int i = 0; i < pedometer_data->diffs_count; ++i) {
947           InsertStepDifference(pedometer_data->diffs[i].steps,
948                                getCurrentTimeStamp(pedometer_data->diffs[i].timestamp) / 1000,
949                                &diffs);
950         }
951       } else {
952         InsertStepDifference(steps_so_far > 0.0 ? pedometer_data->steps() - steps_so_far : 0.0,
953                              getCurrentTimeStamp(pedometer_data->timestamp) / 1000, &diffs);
954       }
955
956       steps_so_far = pedometer_data->steps();
957
958       return PlatformResult(ErrorCode::NO_ERROR);
959     };
960
961     converter_recorded_ = [](void* data, picojson::object* obj) -> PlatformResult {
962       ScopeLogger("Entered into asynchronous function, convert_recorded_pedometer");
963
964       SensorRecorderDataMap map_int{{SENSOR_RECORDER_DATA_STEPS, kRecordedTotalStepCount},
965                                     {SENSOR_RECORDER_DATA_WALK_STEPS, kRecordedWalkStepCount},
966                                     {SENSOR_RECORDER_DATA_RUN_STEPS, kRecordedRunStepCount}};
967
968       SensorRecorderDataMap map_double{{SENSOR_RECORDER_DATA_DISTANCE, kRecordedDistance},
969                                        {SENSOR_RECORDER_DATA_CALORIE, kRecordedCalorie}};
970
971       auto result = ConvertRecordedInt(data, obj, map_int);
972       if (!result) {
973         return result;
974       }
975
976       result = ConvertRecordedDouble(data, obj, map_double);
977       if (!result) {
978         return result;
979       }
980
981       return ConvertRecordedTime(data, obj);
982     };
983   }
984
985   virtual ~PedometerMonitor() {
986     ScopeLogger();
987   }
988
989   virtual PlatformResult SetListenerImpl(const picojson::value& args) override {
990     ScopeLogger();
991     is_first_read = true;
992     return HumanActivityMonitorManager::Monitor::SensorMonitor::SetListenerImpl(args);
993   }
994 };
995
996 class HumanActivityMonitorManager::Monitor::GpsMonitor
997     : public HumanActivityMonitorManager::Monitor {
998  public:
999   explicit GpsMonitor(const std::string& t) : Monitor(t), handle_(nullptr) {
1000     ScopeLogger("type %s", type().c_str());
1001   }
1002
1003   virtual ~GpsMonitor() override {
1004     ScopeLogger("type %s", type().c_str());
1005     UnsetListenerImpl();
1006   }
1007
1008  protected:
1009   virtual PlatformResult IsSupportedImpl(bool* s) const override {
1010     ScopeLogger("type %s", type().c_str());
1011
1012     int ret = 0;
1013     ret = system_info_get_platform_bool("http://tizen.org/feature/location.batch", s);
1014     if (SYSTEM_INFO_ERROR_NONE != ret) {
1015       return LogAndCreateResult(
1016           ErrorCode::UNKNOWN_ERR, "Failed to get location.batch feature",
1017           ("system_info_get_platform_bool error: %d (%s)", ret, get_error_message(ret)));
1018     }
1019     return PlatformResult(ErrorCode::NO_ERROR);
1020   }
1021
1022   virtual PlatformResult SetListenerImpl(const picojson::value& args) override {
1023     ScopeLogger("type %s", type().c_str());
1024
1025     int ret = 0;
1026
1027     if (!handle_) {
1028       int ret = location_manager_create(LOCATIONS_METHOD_GPS, &handle_);
1029       if (LOCATIONS_ERROR_NONE != ret) {
1030         return LogAndCreateResult(
1031             ErrorCode::UNKNOWN_ERR, "Failed to create location manager",
1032             ("Failed to create location manager, error: %d (%s)", ret, get_error_message(ret)));
1033       }
1034
1035       ret = location_manager_set_setting_changed_cb(LOCATIONS_METHOD_GPS, OnGpsSettingEvent, this);
1036       if (LOCATIONS_ERROR_NONE != ret) {
1037         return LogAndCreateResult(
1038             ErrorCode::UNKNOWN_ERR, "Failed to set setting listener",
1039             ("Failed to set setting listener, error: %d (%s)", ret, get_error_message(ret)));
1040       }
1041     } else {
1042       ret = location_manager_stop_batch(handle_);
1043       if (LOCATIONS_ERROR_NONE != ret) {
1044         return LogAndCreateResult(
1045             ErrorCode::UNKNOWN_ERR, "Failed to stop location manager",
1046             ("Failed to stop location manager, error: %d (%s)", ret, get_error_message(ret)));
1047       }
1048     }
1049
1050     int callback_interval = static_cast<int>(args.get(kCallbackInterval).get<double>() / 1000);
1051     int sample_interval = static_cast<int>(args.get(kSampleInterval).get<double>() / 1000);
1052     LoggerD("callbackInterval: %d, sampleInterval: %d", callback_interval, sample_interval);
1053
1054     ret = location_manager_set_location_batch_cb(handle_, OnGpsEvent,
1055                                                  sample_interval,    // batch_interval
1056                                                  callback_interval,  // batch_period
1057                                                  this);
1058     if (LOCATIONS_ERROR_NONE != ret) {
1059       if (LOCATIONS_ERROR_INVALID_PARAMETER == ret) {
1060         return LogAndCreateResult(
1061             ErrorCode::INVALID_VALUES_ERR, "Failed to set location listener",
1062             ("Failed to set location listener, error: %d (%s)", ret, get_error_message(ret)));
1063       }
1064       return LogAndCreateResult(
1065           ErrorCode::UNKNOWN_ERR, "Failed to set location listener",
1066           ("Failed to set location listener, error: %d (%s)", ret, get_error_message(ret)));
1067     }
1068
1069     ret = location_manager_start_batch(handle_);
1070     if (LOCATIONS_ERROR_NONE != ret) {
1071       return LogAndCreateResult(
1072           ErrorCode::UNKNOWN_ERR, "Failed to start location manager",
1073           ("Failed to start location manager, error: %d (%s)", ret, get_error_message(ret)));
1074     }
1075
1076     return PlatformResult(ErrorCode::NO_ERROR);
1077   }
1078
1079   virtual PlatformResult UnsetListenerImpl() override {
1080     ScopeLogger("type %s", type().c_str());
1081
1082     if (handle_) {
1083       int ret = location_manager_stop_batch(handle_);
1084       if (LOCATIONS_ERROR_NONE != ret) {
1085         return LogAndCreateResult(
1086             ErrorCode::UNKNOWN_ERR, "Failed to stop location manager",
1087             ("Failed to stop location manager, error: %d (%s)", ret, get_error_message(ret)));
1088       }
1089
1090       ret = location_manager_unset_setting_changed_cb(LOCATIONS_METHOD_GPS);
1091       if (LOCATIONS_ERROR_NONE != ret) {
1092         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
1093                                   "Failed to unset location setting changed cb",
1094                                   ("Failed to unset location setting changed cb, error: %d (%s)",
1095                                    ret, get_error_message(ret)));
1096       }
1097
1098       ret = location_manager_destroy(handle_);
1099       if (LOCATIONS_ERROR_NONE != ret) {
1100         return LogAndCreateResult(
1101             ErrorCode::UNKNOWN_ERR, "Failed to destroy location manager",
1102             ("Failed to destroy location manager, error: %d (%s)", ret, get_error_message(ret)));
1103       }
1104
1105       handle_ = nullptr;
1106     }
1107
1108     return PlatformResult(ErrorCode::NO_ERROR);
1109   }
1110
1111   virtual PlatformResult GetDataImpl(picojson::value* data) const override {
1112     ScopeLogger("type %s", type().c_str());
1113
1114     if (!handle_) {
1115       return LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "SERVICE_NOT_AVAILABLE_ERR");
1116     }
1117
1118     double altitude = 0.0, latitude = 0.0, longitude = 0.0, climb = 0.0, direction = 0.0,
1119            speed = 0.0, horizontal = 0.0, vertical = 0.0;
1120     location_accuracy_level_e level = LOCATIONS_ACCURACY_NONE;
1121     time_t timestamp = 0;
1122
1123     int ret =
1124         location_manager_get_location(handle_, &altitude, &latitude, &longitude, &climb, &direction,
1125                                       &speed, &level, &horizontal, &vertical, &timestamp);
1126     if (LOCATIONS_ERROR_NONE != ret) {
1127       return LogAndCreateResult(
1128           ErrorCode::UNKNOWN_ERR, "Failed to get location",
1129           ("Failed to get location, error: %d (%s)", ret, get_error_message(ret)));
1130     }
1131
1132     *data = picojson::value(picojson::array());
1133     ConvertGpsEvent(latitude, longitude, altitude, speed, direction, horizontal, vertical,
1134                     timestamp, &data->get<picojson::array>());
1135
1136     return PlatformResult(ErrorCode::NO_ERROR);
1137   }
1138
1139  private:
1140   static void OnGpsSettingEvent(location_method_e method, bool enable, void* user_data) {
1141     ScopeLogger();
1142
1143     if (LOCATIONS_METHOD_GPS != method) {
1144       LoggerD("Location method different from GPS");
1145       return;
1146     }
1147
1148     auto monitor = static_cast<GpsMonitor*>(user_data);
1149     auto& callback = monitor->event_callback();
1150
1151     if (!callback) {
1152       LoggerE("No GPS event callback registered, skipping.");
1153       return;
1154     }
1155
1156     if (!enable) {
1157       picojson::value val{picojson::object{}};
1158       auto& obj = val.get<picojson::object>();
1159
1160       LogAndReportError(
1161           PlatformResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR, "GPS service is not available"),
1162           &obj, ("GPS service is not available"));
1163
1164       callback(&val);
1165     }
1166   }
1167
1168   static void OnGpsEvent(int num_of_location, void* user_data) {
1169     ScopeLogger();
1170
1171     auto monitor = static_cast<GpsMonitor*>(user_data);
1172     auto& callback = monitor->event_callback();
1173
1174     if (!callback) {
1175       LoggerE("No GPS event callback registered, skipping.");
1176       return;
1177     }
1178
1179     if (0 == num_of_location) {
1180       LoggerE("No GPS locations available, skipping.");
1181       return;
1182     }
1183
1184     picojson::value gps_info{picojson::array{}};
1185     int ret = location_manager_foreach_location_batch(monitor->handle_, ConvertGpsEvent,
1186                                                       &gps_info.get<picojson::array>());
1187     if (LOCATIONS_ERROR_NONE != ret) {
1188       LoggerE("Failed to convert location, error: %d", ret);
1189       return;
1190     }
1191
1192     picojson::value out{picojson::object{}};
1193     (out.get<picojson::object>())["gpsInfo"] = gps_info;
1194
1195     callback(&out);
1196   }
1197
1198   static bool ConvertGpsEvent(double latitude, double longitude, double altitude, double speed,
1199                               double direction, double horizontal, double vertical,
1200                               time_t timestamp, void* user_data) {
1201     ScopeLogger();
1202
1203     auto gps_info_array = static_cast<picojson::array*>(user_data);
1204
1205     picojson::value gps_info{picojson::object{}};
1206     auto& gps_info_o = gps_info.get<picojson::object>();
1207
1208     gps_info_o["latitude"] = picojson::value(latitude);
1209     gps_info_o["longitude"] = picojson::value(longitude);
1210     gps_info_o["altitude"] = picojson::value(altitude);
1211     gps_info_o["speed"] = picojson::value(speed);
1212     // TODO(r.galka): errorRange not available in CAPI
1213     gps_info_o["errorRange"] = picojson::value(horizontal);
1214     gps_info_o[kTimestamp] = picojson::value(static_cast<double>(timestamp));
1215
1216     gps_info_array->push_back(gps_info);
1217
1218     return true;
1219   }
1220
1221   location_manager_h handle_;
1222 };
1223
1224 class HumanActivityMonitorManager::ActivityRecognition {
1225  public:
1226   PlatformResult AddListener(const std::string& type, JsonCallback callback, long* watch_id) {
1227     ScopeLogger();
1228
1229     activity_type_e activity_type = ToActivityType(type);
1230     auto result = IsSupported(activity_type);
1231
1232     if (!result) {
1233       return result;
1234     }
1235
1236     activity_h handle = nullptr;
1237     int ret = activity_create(&handle);
1238     if (ACTIVITY_ERROR_NONE != ret) {
1239       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to create activity",
1240                                 ("activity_create() error: %d - %s", ret, get_error_message(ret)));
1241     }
1242
1243     const auto id = GetNextId();
1244     auto data = std::make_shared<ActivityData>(id, callback, handle);
1245
1246     ret = activity_start_recognition(handle, activity_type, OnActivityRecognitionEvent, data.get());
1247     if (ACTIVITY_ERROR_NONE != ret) {
1248       return LogAndCreateResult(
1249           ErrorCode::UNKNOWN_ERR, "Failed to start activity recognition",
1250           ("activity_start_recognition() error: %d - %s", ret, get_error_message(ret)));
1251     }
1252
1253     activity_data_.insert(std::make_pair(id, data));
1254     *watch_id = id;
1255
1256     return result;
1257   }
1258
1259   PlatformResult RemoveListener(long watch_id) {
1260     ScopeLogger();
1261
1262     const auto it = activity_data_.find(watch_id);
1263
1264     if (activity_data_.end() != it) {
1265       activity_data_.erase(it);
1266     }
1267
1268     return PlatformResult(ErrorCode::NO_ERROR);
1269   }
1270
1271  private:
1272   struct ActivityData {
1273     ActivityData(long id, const JsonCallback& cb, activity_h h)
1274         : watch_id(id), callback(cb), handle(h) {
1275     }
1276
1277     ~ActivityData() {
1278       if (handle) {
1279         activity_stop_recognition(handle);
1280         activity_release(handle);
1281       }
1282     }
1283
1284     long watch_id;
1285     JsonCallback callback;
1286     activity_h handle;
1287   };
1288
1289   static long GetNextId() {
1290     static long id = 0;
1291     return ++id;
1292   }
1293
1294   static void OnActivityRecognitionEvent(activity_type_e type, const activity_data_h data,
1295                                          double timestamp, activity_error_e callback_error,
1296                                          void* user_data) {
1297     ScopeLogger();
1298
1299     auto activity_data = static_cast<ActivityData*>(user_data);
1300     JsonCallback callback = activity_data->callback;
1301
1302     picojson::value val{picojson::object{}};
1303     auto& obj = val.get<picojson::object>();
1304     obj.insert(
1305         std::make_pair("watchId", picojson::value(static_cast<double>(activity_data->watch_id))));
1306
1307     if (ACTIVITY_ERROR_NONE != callback_error) {
1308       LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "System operation has failed"), &obj,
1309                         ("activity_recognition_cb() has failed with error code %d - %s",
1310                          callback_error, get_error_message(callback_error)));
1311       callback(&val);
1312       return;
1313     }
1314
1315     activity_accuracy_e accuracy = ACTIVITY_ACCURACY_MID;
1316
1317     int ret = activity_get_accuracy(data, &accuracy);
1318     if (ret != ACTIVITY_ERROR_NONE) {
1319       LogAndReportError(PlatformResult(ErrorCode::ABORT_ERR, "System operation has failed"), &obj,
1320                         ("activity_get_accuracy() has failed with error code %d - %s", ret,
1321                          get_error_message(ret)));
1322       callback(&val);
1323       return;
1324     }
1325     timestamp = std::floor(timestamp);
1326     SLoggerD("Activity type: (%d)", type);
1327     SLoggerD("Activity accuracy: (%d)", accuracy);
1328     SLoggerD("Activity timestamp: (%f)", timestamp);
1329
1330     picojson::value result{picojson::object{}};
1331     auto& result_obj = result.get<picojson::object>();
1332
1333     result_obj.insert(std::make_pair("type", picojson::value(FromActivityType(type))));
1334     result_obj.insert(std::make_pair("accuracy", picojson::value(FromActivityAccuracy(accuracy))));
1335     result_obj.insert(std::make_pair(kTimestamp, picojson::value(timestamp)));
1336
1337     ReportSuccess(result, obj);
1338     callback(&val);
1339   }
1340
1341   PlatformResult IsSupported(activity_type_e type) {
1342     ScopeLogger();
1343
1344     bool supported = false;
1345     int ret = activity_is_supported(type, &supported);
1346
1347     if (ret == ACTIVITY_ERROR_NOT_SUPPORTED || !supported) {
1348       return LogAndCreateResult(ErrorCode::NOT_SUPPORTED_ERR, "Activity type is not supported",
1349                                 ("Type %d not supported", type));
1350     } else if (ret != ACTIVITY_ERROR_NONE) {
1351       return LogAndCreateResult(
1352           ErrorCode::UNKNOWN_ERR, "activity_is_supported failed",
1353           ("activity_is_supported error %d - %s", ret, get_error_message(ret)));
1354     } else {
1355       return PlatformResult(ErrorCode::NO_ERROR);
1356     }
1357   }
1358
1359 #define ACTIVITY_TYPE_E                \
1360   X(ACTIVITY_STATIONARY, "STATIONARY") \
1361   X(ACTIVITY_WALK, "WALKING")          \
1362   X(ACTIVITY_RUN, "RUNNING")           \
1363   X(ACTIVITY_IN_VEHICLE, "IN_VEHICLE") \
1364   XD(static_cast<activity_type_e>(-1), "unknown")
1365
1366 #define ACTIVITY_ACCURACY_E          \
1367   X(ACTIVITY_ACCURACY_LOW, "LOW")    \
1368   X(ACTIVITY_ACCURACY_MID, "MEDIUM") \
1369   X(ACTIVITY_ACCURACY_HIGH, "HIGH")  \
1370   XD(static_cast<activity_accuracy_e>(-1), "unknown")
1371
1372 #define X(v, s) \
1373   case v:       \
1374     return s;
1375 #define XD(v, s)                                               \
1376   default:                                                     \
1377     LoggerE("Unknown value: %d, returning default: %s", e, s); \
1378     return s;
1379
1380   static std::string FromActivityType(activity_type_e e) {
1381     ScopeLogger();
1382
1383     switch (e) { ACTIVITY_TYPE_E }
1384   }
1385
1386   static std::string FromActivityAccuracy(activity_accuracy_e e) {
1387     ScopeLogger();
1388
1389     switch (e) { ACTIVITY_ACCURACY_E }
1390   }
1391
1392 #undef X
1393 #undef XD
1394
1395 #define X(v, s) \
1396   if (e == s) return v;
1397 #define XD(v, s)                                                     \
1398   LoggerE("Unknown value: %s, returning default: %d", e.c_str(), v); \
1399   return v;
1400
1401   static activity_type_e ToActivityType(const std::string& e) {
1402     ScopeLogger();
1403
1404     ACTIVITY_TYPE_E
1405   }
1406
1407 #undef X
1408 #undef XD
1409
1410 #undef ACTIVITY_ACCURACY_E
1411 #undef ACTIVITY_TYPE_E
1412
1413   std::map<long, std::shared_ptr<ActivityData>> activity_data_;
1414 };
1415
1416 PlatformResult SleepStateToString(int state, std::string* sleep_state) {
1417   ScopeLogger("%d", state);
1418   if (sleep_state) {
1419     switch (state) {
1420       case SENSOR_SLEEP_STATE_WAKE:
1421         *sleep_state = kSleepStateAwake;
1422         break;
1423       case SENSOR_SLEEP_STATE_SLEEP:
1424         *sleep_state = kSleepStateAsleep;
1425         break;
1426       case SENSOR_SLEEP_STATE_UNKNOWN:
1427         *sleep_state = kSleepStateUnknown;
1428         break;
1429       default:
1430         return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown sleep state",
1431                                   ("Unknown sleep state: %d", state));
1432     }
1433     return PlatformResult(ErrorCode::NO_ERROR);
1434   }
1435   return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
1436                             "Cannot return sleep state, return pointer is null");
1437 }
1438
1439 HumanActivityMonitorManager::HumanActivityMonitorManager()
1440     : activity_recognition_(std::make_shared<ActivityRecognition>()) {
1441   ScopeLogger();
1442
1443   auto convert_hrm = [](sensor_event_s* event, picojson::object* data) -> PlatformResult {
1444     ScopeLogger("Entered into asynchronous function, convert_hrm");
1445
1446     LoggerD("Sensor event:");
1447     LoggerD("|- accuracy: %d", event->accuracy);
1448     LoggerD("|- timestamp: %llu", event->timestamp);
1449     LoggerD("|- value_count: %d", event->value_count);
1450
1451     if (event->value_count < 2) {
1452       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "To few values of HRM event");
1453     }
1454
1455     LoggerD("|- values[0][HR ]: %f", event->values[0]);
1456     LoggerD("|- values[2][RRI]: %f", event->values[2]);
1457
1458     float hr = floor(event->values[0] + 0.5);  // heart beat rate 0 ~ 220 integer (bpm)
1459
1460     // there are no public native api documentation for peak to peak interval.
1461     // but RRI = (60 / HR) * 1000
1462     // @ 18.05.2018
1463     // in capi, rri is in values[2], but it is not documented because value can be unstable
1464     // and it is not available on all devices. On solis it works fine.
1465
1466     float rri = floor(event->values[2] + 0.5);  // rr-interval 0 ~ 5000 integer (ms)
1467
1468     data->insert(std::make_pair("heartRate", picojson::value(static_cast<double>(hr))));
1469     data->insert(std::make_pair("rRInterval", picojson::value(static_cast<double>(rri))));
1470
1471     return PlatformResult(ErrorCode::NO_ERROR);
1472   };
1473
1474   auto convert_sleep = [](sensor_event_s* event, picojson::object* data) -> PlatformResult {
1475     ScopeLogger("Entered into asynchronous function, convert_sleep");
1476
1477     if (event->value_count < 1) {
1478       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "To few values of SLEEP event");
1479     }
1480
1481     sensor_sleep_state_e state = static_cast<sensor_sleep_state_e>(event->values[0]);
1482     std::string sleep_state;
1483     PlatformResult result = SleepStateToString(state, &sleep_state);
1484     if (!result) {
1485       return result;
1486     }
1487
1488     data->insert(std::make_pair(kStatus, picojson::value(sleep_state)));
1489     data->insert(std::make_pair(
1490         kTimestamp, picojson::value(static_cast<double>(getCurrentTimeStamp(event->timestamp)))));
1491
1492     return PlatformResult(ErrorCode::NO_ERROR);
1493   };
1494
1495   auto convert_sleep_detector = [](sensor_event_s* event,
1496                                    picojson::object* data) -> PlatformResult {
1497     ScopeLogger("convert_sleep_detector");
1498
1499     if (event->value_count < 1) {
1500       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "To few values of SLEEP event");
1501     }
1502
1503     sensor_sleep_state_e state = static_cast<sensor_sleep_state_e>(event->values[0]);
1504     std::string sleep_state;
1505     PlatformResult result = SleepStateToString(state, &sleep_state);
1506     if (!result) {
1507       return result;
1508     }
1509
1510     data->insert(std::make_pair(kStatus, picojson::value(sleep_state)));
1511
1512     return PlatformResult(ErrorCode::NO_ERROR);
1513   };
1514
1515   auto convert_stress = [](sensor_event_s* event, picojson::object* data) -> PlatformResult {
1516     ScopeLogger("convert_stress");
1517
1518     if (event->value_count < 1) {
1519       return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "To few values of STRESS event");
1520     }
1521
1522     float stress_score = event->values[0];
1523     data->insert(std::make_pair(kStressScore, picojson::value(static_cast<double>(stress_score))));
1524
1525     return PlatformResult(ErrorCode::NO_ERROR);
1526   };
1527
1528   auto convert_recorded_hrm = [](void* data, picojson::object* obj) -> PlatformResult {
1529     ScopeLogger("Entered into asynchronous function, convert_recorded_hrm");
1530
1531     SensorRecorderDataMap map_int{
1532         {SENSOR_RECORDER_DATA_HEART_RATE, kRecordedHeartRate},
1533     };
1534
1535     auto result = ConvertRecordedInt(data, obj, map_int);
1536     if (!result) {
1537       return result;
1538     }
1539
1540     return ConvertRecordedTime(data, obj);
1541   };
1542
1543   auto convert_recorded_sleep_monitor = [](void* data, picojson::object* obj) -> PlatformResult {
1544     ScopeLogger("Entered into asynchronous function, convert_recorded_sleep_monitor");
1545
1546     int state = 0;
1547     int ret = sensor_recorder_data_get_int(data, SENSOR_RECORDER_DATA_SLEEP_STATE, &state);
1548     if (SENSOR_ERROR_NONE != ret) {
1549       return LogAndCreateResult(
1550           getErrorCode(ret), "Failed to get int value",
1551           ("Failed to get int value, error: %d (%s)", ret, get_error_message(ret)));
1552     }
1553
1554     std::string sleep_state;
1555     PlatformResult result = SleepStateToString(state, &sleep_state);
1556     if (!result) {
1557       return result;
1558     }
1559
1560     obj->insert(std::make_pair(kStatus, picojson::value(sleep_state)));
1561
1562     return ConvertRecordedTime(data, obj);
1563   };
1564
1565   auto convert_recorded_pressure = [](void* data, picojson::object* obj) -> PlatformResult {
1566     ScopeLogger("Entered into asynchronous function, convert_recorded_pressure");
1567
1568     SensorRecorderDataMap map_double{{SENSOR_RECORDER_DATA_MAX_PRESSURE, kRecordedMax},
1569                                      {SENSOR_RECORDER_DATA_MIN_PRESSURE, kRecordedMin},
1570                                      {SENSOR_RECORDER_DATA_AVERAGE_PRESSURE, kRecordedAverage}};
1571
1572     auto result = ConvertRecordedDouble(data, obj, map_double);
1573     if (!result) {
1574       return result;
1575     }
1576
1577     return ConvertRecordedTime(data, obj);
1578   };
1579
1580   monitors_.insert(
1581       std::make_pair(kActivityTypePedometer, std::make_shared<Monitor::PedometerMonitor>()));
1582   monitors_.insert(std::make_pair(kActivityTypeWristUp,
1583                                   std::make_shared<Monitor::GestureMonitor>(kActivityTypeWristUp)));
1584   monitors_.insert(std::make_pair(kActivityTypeSleepDetector,
1585                                   std::make_shared<Monitor::SensorMonitor>(
1586                                       kActivityTypeSleepDetector, SENSOR_HUMAN_SLEEP_DETECTOR,
1587                                       convert_sleep_detector, nullptr)));
1588   monitors_.insert(std::make_pair(
1589       kActivityTypeStressMonitor,
1590       std::make_shared<Monitor::SensorMonitor>(
1591           kActivityTypeStressMonitor, SENSOR_HUMAN_STRESS_MONITOR, convert_stress, nullptr)));
1592   monitors_.insert(std::make_pair(
1593       kActivityTypeHrm, std::make_shared<Monitor::SensorMonitor>(
1594                             kActivityTypeHrm, SENSOR_HRM, convert_hrm, convert_recorded_hrm)));
1595   monitors_.insert(
1596       std::make_pair(kActivityTypeGps, std::make_shared<Monitor::GpsMonitor>(kActivityTypeGps)));
1597   monitors_.insert(std::make_pair(kActivityTypeSleepMonitor,
1598                                   std::make_shared<Monitor::SensorMonitor>(
1599                                       kActivityTypeSleepMonitor, SENSOR_HUMAN_SLEEP_MONITOR,
1600                                       convert_sleep, convert_recorded_sleep_monitor)));
1601   monitors_.insert(std::make_pair(kActivityTypePressure, std::make_shared<Monitor::SensorMonitor>(
1602                                                              kActivityTypePressure, SENSOR_PRESSURE,
1603                                                              nullptr, convert_recorded_pressure)));
1604 }
1605
1606 HumanActivityMonitorManager::~HumanActivityMonitorManager() {
1607   ScopeLogger();
1608 }
1609
1610 PlatformResult HumanActivityMonitorManager::Init() {
1611   ScopeLogger();
1612   return PlatformResult(ErrorCode::NO_ERROR);
1613 }
1614
1615 PlatformResult HumanActivityMonitorManager::IsSupported(const std::string& type) {
1616   return this->GetMonitor(type)->IsSupported();
1617 }
1618
1619 PlatformResult HumanActivityMonitorManager::SetListener(const std::string& type,
1620                                                         JsonCallback callback,
1621                                                         const picojson::value& args) {
1622   ScopeLogger();
1623   return GetMonitor(type)->SetListener(callback, args);
1624 }
1625
1626 PlatformResult HumanActivityMonitorManager::UnsetListener(const std::string& type) {
1627   ScopeLogger();
1628   return GetMonitor(type)->UnsetListener();
1629 }
1630
1631 PlatformResult HumanActivityMonitorManager::GetHumanActivityData(const std::string& type,
1632                                                                  picojson::value* data) {
1633   ScopeLogger();
1634   return GetMonitor(type)->GetData(data);
1635 }
1636
1637 PlatformResult HumanActivityMonitorManager::AddActivityRecognitionListener(const std::string& type,
1638                                                                            JsonCallback callback,
1639                                                                            long* watch_id) {
1640   ScopeLogger();
1641   return activity_recognition_->AddListener(type, callback, watch_id);
1642 }
1643
1644 PlatformResult HumanActivityMonitorManager::RemoveActivityRecognitionListener(const long watch_id) {
1645   ScopeLogger();
1646   return activity_recognition_->RemoveListener(watch_id);
1647 }
1648
1649 PlatformResult HumanActivityMonitorManager::StartDataRecorder(const std::string& type, int interval,
1650                                                               int retention_period) {
1651   ScopeLogger();
1652   return GetMonitor(type)->StartDataRecorder(interval, retention_period);
1653 }
1654
1655 PlatformResult HumanActivityMonitorManager::StopDataRecorder(const std::string& type) {
1656   ScopeLogger();
1657   return GetMonitor(type)->StopDataRecorder();
1658 }
1659
1660 PlatformResult HumanActivityMonitorManager::ReadRecorderData(const std::string& type,
1661                                                              picojson::array* data,
1662                                                              const picojson::value& query) {
1663   ScopeLogger();
1664   return GetMonitor(type)->ReadRecorderData(data, query);
1665 }
1666
1667 std::shared_ptr<HumanActivityMonitorManager::Monitor> HumanActivityMonitorManager::GetMonitor(
1668     const std::string& type) {
1669   ScopeLogger();
1670
1671   const auto it = monitors_.find(type);
1672
1673   if (monitors_.end() != it) {
1674     return it->second;
1675   } else {
1676     return std::make_shared<Monitor>(type);  // return default unsupported monitor
1677   }
1678 }
1679
1680 }  // namespace humanactivitymonitor
1681 }  // namespace extension