2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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.
17 #include "humanactivitymonitor/humanactivitymonitor_manager.h"
19 #include <gesture_recognition.h>
21 #include "common/logger.h"
24 namespace humanactivitymonitor {
26 using common::PlatformResult;
27 using common::ErrorCode;
29 HumanActivityMonitorManager::HumanActivityMonitorManager()
30 : gesture_handle_(nullptr),
31 hrm_sensor_listener_(nullptr),
32 location_handle_(nullptr) {
36 HumanActivityMonitorManager::~HumanActivityMonitorManager() {
38 UnsetWristUpListener();
43 PlatformResult HumanActivityMonitorManager::Init() {
45 return PlatformResult(ErrorCode::NO_ERROR);
48 PlatformResult HumanActivityMonitorManager::IsSupported(
49 const std::string& type) {
52 if (supported_.count(type)) {
53 return LogAndCreateResult(supported_[type]
55 : ErrorCode::NOT_SUPPORTED_ERR);
59 bool supported = false;
60 if (type == kActivityTypePedometer) {
61 // TODO(r.galka) no native api for pedometer
62 // so just pass it for not supported.
63 } else if (type == kActivityTypeWristUp) {
64 ret = gesture_is_supported(GESTURE_WRIST_UP, &supported);
65 if (ret != SENSOR_ERROR_NONE) {
66 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
67 "WRIST_UP gesture check failed",
68 ("gesture_is_supported(GESTURE_WRIST_UP), error: %d",ret));
70 } else if (type == kActivityTypeHrm) {
71 ret = sensor_is_supported(SENSOR_HRM, &supported);
72 if (ret != SENSOR_ERROR_NONE) {
73 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
74 "HRM sensor check failed",
75 ("sensor_is_supported(HRM), error: %d",ret));
77 } else if (type == kActivityTypeGps) {
78 supported = location_manager_is_supported_method(LOCATIONS_METHOD_GPS);
80 return LogAndCreateResult(ErrorCode::TYPE_MISMATCH_ERR);
83 supported_[type] = supported;
85 return LogAndCreateResult(supported_[type]
87 : ErrorCode::NOT_SUPPORTED_ERR);
90 PlatformResult HumanActivityMonitorManager::SetListener(
91 const std::string& type, JsonCallback callback) {
93 PlatformResult result = IsSupported(type);
98 if (type == kActivityTypePedometer) {
99 // TODO(r.galka) Not Supported in current implementation.
102 if (type == kActivityTypeWristUp) {
103 return SetWristUpListener(callback);
106 if (type == kActivityTypeHrm) {
107 return SetHrmListener(callback);
110 if (type == kActivityTypeGps) {
111 return SetGpsListener(callback);
114 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Undefined activity type");
117 PlatformResult HumanActivityMonitorManager::UnsetListener(
118 const std::string& type) {
120 PlatformResult result = IsSupported(type);
125 if (type == kActivityTypePedometer) {
126 // TODO(r.galka) Not Supported in current implementation.
129 if (type == kActivityTypeWristUp) {
130 return UnsetWristUpListener();
133 if (type == kActivityTypeHrm) {
134 return UnsetHrmListener();
137 if (type == kActivityTypeGps) {
138 return UnsetGpsListener();
141 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Undefined activity type");
144 PlatformResult HumanActivityMonitorManager::GetHumanActivityData(
145 const std::string& type,
146 picojson::value* data) {
149 if (type == kActivityTypePedometer) {
150 // TODO(r.galka) Not Supported in current implementation.
153 if (type == kActivityTypeWristUp) {
154 return LogAndCreateResult(ErrorCode::NOT_SUPPORTED_ERR);
157 if (type == kActivityTypeHrm) {
158 return GetHrmData(data);
161 if (type == kActivityTypeGps) {
162 return GetGpsData(data);
165 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Undefined activity type");
169 PlatformResult HumanActivityMonitorManager::SetWristUpListener(
170 JsonCallback callback) {
174 ret = gesture_create(&gesture_handle_);
175 if (ret != GESTURE_ERROR_NONE) {
176 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
177 "Failed to create WRIST_UP listener",
178 ("Failed to create WRIST_UP handle, error: %d",ret));
181 ret = gesture_start_recognition(gesture_handle_,
183 GESTURE_OPTION_DEFAULT,
186 if (ret != GESTURE_ERROR_NONE) {
187 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
188 "Failed to start WRIST_UP listener",
189 ("Failed to start WRIST_UP listener, error: %d",ret));
192 wrist_up_event_callback_ = callback;
194 return PlatformResult(ErrorCode::NO_ERROR);
197 PlatformResult HumanActivityMonitorManager::UnsetWristUpListener() {
200 if (gesture_handle_) {
201 int ret = gesture_stop_recognition(gesture_handle_);
202 if (ret != GESTURE_ERROR_NONE) {
203 LOGGER(ERROR) << "Failed to stop WRIST_UP detection, error: " << ret;
206 ret = gesture_release(gesture_handle_);
207 if (ret != GESTURE_ERROR_NONE) {
208 LOGGER(ERROR) << "Failed to release WRIST_UP handle, error: " << ret;
212 wrist_up_event_callback_ = nullptr;
214 return PlatformResult(ErrorCode::NO_ERROR);
217 void HumanActivityMonitorManager::OnWristUpEvent(gesture_type_e gesture,
218 const gesture_data_h data,
220 gesture_error_e error,
223 HumanActivityMonitorManager* manager =
224 static_cast<HumanActivityMonitorManager*>(user_data);
226 if (!manager->wrist_up_event_callback_) {
227 LOGGER(ERROR) << "No WRIST_UP event callback registered, skipping.";
231 picojson::value v = picojson::value(); // null value
232 manager->wrist_up_event_callback_(&v);
236 PlatformResult HumanActivityMonitorManager::SetHrmListener(
237 JsonCallback callback) {
242 ret = sensor_get_default_sensor(SENSOR_HRM, &hrm_sensor);
243 if (ret != SENSOR_ERROR_NONE) {
244 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
245 "Failed to get HRM sensor",
246 ("Failed to get HRM sensor, error: %d",ret));
249 ret = sensor_create_listener(hrm_sensor, &hrm_sensor_listener_);
250 if (ret != SENSOR_ERROR_NONE) {
251 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
252 "Failed to create HRM sensor listener",
253 ("Failed to create HRM sensor listener, error: %d",ret));
256 ret = sensor_listener_set_event_cb(hrm_sensor_listener_,
260 if (ret != SENSOR_ERROR_NONE) {
261 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
262 "Failed to set HRM sensor listener",
263 ("Failed to set HRM sensor listener, error: %d",ret));
266 ret = sensor_listener_start(hrm_sensor_listener_);
267 if (ret != SENSOR_ERROR_NONE) {
268 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
269 "Failed to start HRM sensor listener",
270 ("Failed to start HRM sensor listener, error: %d",ret));
273 hrm_event_callback_ = callback;
275 return PlatformResult(ErrorCode::NO_ERROR);
278 PlatformResult HumanActivityMonitorManager::UnsetHrmListener() {
281 if (hrm_sensor_listener_) {
282 int ret = sensor_listener_stop(hrm_sensor_listener_);
283 if (ret != SENSOR_ERROR_NONE) {
284 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
285 "Failed to stop HRM sensor",
286 ("Failed to stop HRM sensor, error: "%d,ret));
289 ret = sensor_listener_unset_event_cb(hrm_sensor_listener_);
290 if (ret != SENSOR_ERROR_NONE) {
291 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
292 "Failed to unset HRM sensor listener",
293 ("Failed to unset HRM sensor listener, error: %d",ret));
296 ret = sensor_destroy_listener(hrm_sensor_listener_);
297 if (ret != SENSOR_ERROR_NONE) {
298 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
299 "Failed to destroy HRM sensor listener",
300 ("Failed to destroy HRM sensor listener, error: %d",ret));
304 hrm_event_callback_ = nullptr;
306 return PlatformResult(ErrorCode::NO_ERROR);
309 static PlatformResult ConvertHrmEvent(sensor_event_s* event,
310 picojson::object* data) {
311 LOGGER(DEBUG) << "Sensor event:";
312 LOGGER(DEBUG) << " |- accuracy: " << event->accuracy;
313 LOGGER(DEBUG) << " |- timestamp: " << event->timestamp;
314 LOGGER(DEBUG) << " |- value_count: " << event->value_count;
316 if (event->value_count < 2) {
317 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "To few values of HRM event");
320 LOGGER(DEBUG) << " |- values[0]: " << event->values[0];
321 LOGGER(DEBUG) << " |- values[1]: " << event->values[1];
323 float hr = floor( event->values[0] + 0.5); // heart beat rate 0 ~ 220 integer (bpm)
325 // there are no public native api for peak to peak interval.
326 // but RRI = (60 / HR) * 1000
327 // or unofficially values[1] is rri (0 ~ 5000 ms)
328 float rri = floor(event->values[1] + 0.5);
331 (*data)["heartRate"] = picojson::value(static_cast<double>(hr));
332 (*data)["rRInterval"] = picojson::value(static_cast<double>(rri));
334 return PlatformResult(ErrorCode::NO_ERROR);
337 void HumanActivityMonitorManager::OnHrmSensorEvent(
338 sensor_h /*sensor*/, sensor_event_s *event, void *user_data) {
341 HumanActivityMonitorManager* manager =
342 static_cast<HumanActivityMonitorManager*>(user_data);
344 if (!manager->hrm_event_callback_) {
345 LOGGER(ERROR) << "No HRM event callback registered, skipping.";
349 picojson::value hrm_data = picojson::value(picojson::object());
350 PlatformResult result = ConvertHrmEvent(event,
351 &hrm_data.get<picojson::object>());
353 LOGGER(ERROR) << "Failed to convert HRM data: " << result.message();
357 manager->hrm_event_callback_(&hrm_data);
360 PlatformResult HumanActivityMonitorManager::GetHrmData(picojson::value* data) {
362 if (!hrm_sensor_listener_) {
363 return LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR);
368 sensor_event_s event;
369 ret = sensor_listener_read_data(hrm_sensor_listener_, &event);
370 if (ret != SENSOR_ERROR_NONE) {
371 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
372 "Failed to get HRM sensor data",
373 ("Failed to get HRM sensor data, error: %d",ret));
376 *data = picojson::value(picojson::object());
377 PlatformResult result = ConvertHrmEvent(&event,
378 &data->get<picojson::object>());
383 return PlatformResult(ErrorCode::NO_ERROR);
387 PlatformResult HumanActivityMonitorManager::SetGpsListener(
388 JsonCallback callback) {
392 ret = location_manager_create(LOCATIONS_METHOD_GPS, &location_handle_);
393 if (ret != LOCATIONS_ERROR_NONE) {
394 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
395 "Failed to create location manager",
396 ("Failed to create location manager, error: %d",ret));
399 ret = location_manager_set_location_batch_cb(location_handle_,
404 if (ret != LOCATIONS_ERROR_NONE) {
405 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
406 "Failed to set location listener",
407 ("Failed to set location listener, error: %d",ret));
410 ret = location_manager_start_batch(location_handle_);
411 if (ret != LOCATIONS_ERROR_NONE) {
412 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
413 "Failed to start location manager",
414 ("Failed to start location manager, error: %d",ret));
417 gps_event_callback_ = callback;
419 return PlatformResult(ErrorCode::NO_ERROR);
422 PlatformResult HumanActivityMonitorManager::UnsetGpsListener() {
425 if (location_handle_) {
426 int ret = location_manager_stop_batch(location_handle_);
427 if (ret != LOCATIONS_ERROR_NONE) {
428 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
429 "Failed to stop location manager",
430 ("Failed to stop location manager, error: %d",ret));
433 ret = location_manager_unset_location_batch_cb(location_handle_);
434 if (ret != LOCATIONS_ERROR_NONE) {
435 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
436 "Failed to unset location listener",
437 ("Failed to unset location listener, error: %d",ret));
440 ret = location_manager_destroy(location_handle_);
441 if (ret != LOCATIONS_ERROR_NONE) {
442 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR,
443 "Failed to destroy location manager",
444 ("Failed to destroy location manager, error: %d",ret));
448 gps_event_callback_ = nullptr;
450 return PlatformResult(ErrorCode::NO_ERROR);
453 static bool ConvertGpsEvent(double latitude, double longitude, double altitude,
454 double speed, double direction, double horizontal,
455 double vertical, time_t timestamp,
458 picojson::array* gps_info_array = static_cast<picojson::array*>(user_data);
460 picojson::value gps_info = picojson::value(picojson::object());
461 picojson::object& gps_info_o = gps_info.get<picojson::object>();
463 gps_info_o["latitude"] = picojson::value(latitude);
464 gps_info_o["longitude"] = picojson::value(longitude);
465 gps_info_o["altitude"] = picojson::value(altitude);
466 gps_info_o["speed"] = picojson::value(speed);
467 // TODO(r.galka) errorRange not available in CAPI
468 gps_info_o["errorRange"] = picojson::value(static_cast<double>(0));
469 gps_info_o["timestamp"] = picojson::value(static_cast<double>(timestamp));
471 gps_info_array->push_back(gps_info);
476 void HumanActivityMonitorManager::OnGpsEvent(int num_of_location,
479 HumanActivityMonitorManager* manager =
480 static_cast<HumanActivityMonitorManager*>(user_data);
482 if (!manager->gps_event_callback_) {
483 LOGGER(ERROR) << "No GPS event callback registered, skipping.";
487 if (0 == num_of_location) {
488 LOGGER(ERROR) << "No GPS locations available, skipping.";
492 picojson::value gps_info = picojson::value(picojson::array());
493 int ret = location_manager_foreach_location_batch(
494 manager->location_handle_,
496 &gps_info.get<picojson::array>());
497 if (ret != LOCATIONS_ERROR_NONE) {
498 LOGGER(ERROR) << "Failed to convert location, error: " << ret;
502 manager->gps_event_callback_(&gps_info);
505 PlatformResult HumanActivityMonitorManager::GetGpsData(picojson::value* data) {
507 if (!location_handle_) {
508 return LogAndCreateResult(ErrorCode::SERVICE_NOT_AVAILABLE_ERR);
512 double altitude, latitude, longitude, climb,
513 direction, speed, horizontal, vertical;
514 location_accuracy_level_e level;
516 ret = location_manager_get_location(location_handle_, &altitude, &latitude,
517 &longitude, &climb, &direction, &speed,
518 &level, &horizontal, &vertical,
520 if (ret != LOCATIONS_ERROR_NONE) {
521 return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Failed to get location",
522 ("Failed to get location, error: %d",ret));
525 *data = picojson::value(picojson::array());
526 ConvertGpsEvent(latitude, longitude, altitude, speed, direction, horizontal,
527 vertical, timestamp, &data->get<picojson::array>());
529 return PlatformResult(ErrorCode::NO_ERROR);
532 } // namespace humanactivitymonitor
533 } // namespace extension