[Info] Unable to verify. HRM sensor not working on emulator.
Change-Id: Icf69396ab9e89e80152543633714a2ec068ca89e
Signed-off-by: Rafal Galka <r.galka@samsung.com>
'humanactivitymonitor_extension.h',
'humanactivitymonitor_instance.cc',
'humanactivitymonitor_instance.h',
+ 'humanactivitymonitor_manager.cc',
+ 'humanactivitymonitor_manager.h',
],
'conditions': [
['tizen == 1', {
HRM: 'HRM',
GPS: 'GPS'
};
+
var PedometerStepStatus = {
NOT_MOVING: 'NOT_MOVING',
WALKING: 'WALKING',
};
HumanActivityMonitorManager.prototype.start = function(type, changedCallback) {
+ // TODO(r.galka) check access
+ // HRM - http://tizen.org/privilege/healthinfo
+ // GPS - http://tizen.org/privilege/location
+
var args = validator_.validateArgs(arguments, [
{name: 'type', type: types_.ENUM, values: Object.keys(HumanActivityType)},
{name: 'changedCallback', type: types_.FUNCTION, optional: true, nullable: true}
]);
+ var listenerId ='HumanActivityMonitor_' + args.type;
+
var data = {
- type: args.type
+ type: args.type,
+ listenerId: listenerId
};
- var callback = function(result) {
- native_.callIfPossible(args.changedCallback);
- };
+ if (!native_.isListenerSet(listenerId)) {
+ var result = native_.callSync('HumanActivityMonitorManager_start', data);
+ if (native_.isFailure(result)) {
+ throw native_.getErrorObject(result);
+ }
+ }
- native_.call('HumanActivityMonitorManager_start', data, callback);
+ var listener = function(result) {
+ native_.callIfPossible(args.changedCallback, new HumanActivityHRMData(result));
+ };
+ native_.addListener(listenerId, listener);
};
HumanActivityMonitorManager.prototype.stop = function(type) {
var args = validator_.validateArgs(arguments, [
- {name: 'type', type: types_.ENUM, values: ['PEDOMETER', 'WRIST_UP', 'HRM', 'GPS']}
+ {name: 'type', type: types_.ENUM, values: Object.keys(HumanActivityType)}
]);
var data = {
type: args.type
};
- var result = native_.callSync('HumanActivityMonitorManager_stop', data);
+ var listenerId ='HumanActivityMonitor_' + args.type;
+ if (!native_.isListenerSet(listenerId)) {
+ return;
+ }
+
+ var result = native_.callSync('HumanActivityMonitorManager_stop', data);
if (native_.isFailure(result)) {
throw native_.getErrorObject(result);
}
+
+ native_.removeListener(listenerId);
};
HumanActivityMonitorManager.prototype.setAccumulativePedometerListener = function(changeCallback) {
HumanActivityAccumulativePedometerData.prototype.constructor = HumanActivityAccumulativePedometerData;
-function HumanActivityHRMData() {
- SetReadOnlyProperty(this, 'heartRate', null);
- SetReadOnlyProperty(this, 'rRInterval', null);
+function HumanActivityHRMData(data) {
+ SetReadOnlyProperty(this, 'heartRate', data.heartRate);
+ SetReadOnlyProperty(this, 'rRInterval', data.rRInterval);
}
HumanActivityHRMData.prototype = new HumanActivityData();
#include "humanactivitymonitor/humanactivitymonitor_instance.h"
#include <functional>
+#include <memory>
#include <string>
#include "common/picojson.h"
#include "common/logger.h"
#include "common/platform_result.h"
+#include "humanactivitymonitor/humanactivitymonitor_manager.h"
namespace extension {
namespace humanactivitymonitor {
HumanActivityMonitorInstance::~HumanActivityMonitorInstance() {
}
+PlatformResult HumanActivityMonitorInstance::Init() {
+ if (!manager_) {
+
+ manager_ = std::make_shared<HumanActivityMonitorManager>();
+ const PlatformResult& result = manager_->Init();
+ if (!result) {
+ LOGGER(ERROR) << "Error initializing manager: " << result.message();
+ manager_.reset();
+ return result;
+ }
+ }
+
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
#define CHECK_EXIST(args, name, out) \
if (!args.contains(name)) { \
ReportError(PlatformResult(ErrorCode::TYPE_MISMATCH_ERR, \
void HumanActivityMonitorInstance::HumanActivityMonitorManagerStart(
const picojson::value& args, picojson::object& out) {
- // TODO(r.galka) implement
+ CHECK_EXIST(args, "type", out)
+
+ PlatformResult result = Init();
+ if (!result) {
+ ReportError(result, &out);
+ return;
+ }
+
+ JsonCallback cb = [this, args](picojson::value* data) -> void {
+ if (!data) {
+ LOGGER(ERROR) << "No data passed to json callback";
+ return;
+ }
+
+ picojson::object& data_o = data->get<picojson::object>();
+ data_o["listenerId"] = args.get("listenerId");
+
+ PostMessage(data->serialize().c_str());
+ };
+
+ result = manager_->SetListener(args.get("type").get<std::string>(), cb);
+ if (result) {
+ ReportSuccess(out);
+ } else {
+ ReportError(result, &out);
+ }
}
void HumanActivityMonitorInstance::HumanActivityMonitorManagerStop(
const picojson::value& args, picojson::object& out) {
- // TODO(r.galka) implement
+ CHECK_EXIST(args, "type", out)
+
+ PlatformResult result = Init();
+ if (!result) {
+ ReportError(result, &out);
+ return;
+ }
+
+ result = manager_->UnsetListener(args.get("type").get<std::string>());
+ if (result) {
+ ReportSuccess(out);
+ } else {
+ ReportError(result, &out);
+ }
}
void HumanActivityMonitorInstance::HumanActivityMonitorManagerSetAccumulativePedometerListener(
#ifndef HUMANACTIVITYMONITOR_HUMANACTIVITYMONITOR_INSTANCE_H_
#define HUMANACTIVITYMONITOR_HUMANACTIVITYMONITOR_INSTANCE_H_
+#include <memory>
+
#include "common/extension.h"
#include "common/platform_result.h"
+#include "humanactivitymonitor/humanactivitymonitor_manager.h"
namespace extension {
namespace humanactivitymonitor {
const picojson::value& args, picojson::object& out);
void HumanActivityMonitorManagerSetAccumulativePedometerListener(
const picojson::value& args, picojson::object& out);
+
+ std::shared_ptr<HumanActivityMonitorManager> manager_;
+ common::PlatformResult Init();
};
} // namespace humanactivitymonitor
--- /dev/null
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "humanactivitymonitor/humanactivitymonitor_manager.h"
+
+#include <gesture_recognition.h>
+
+#include "common/logger.h"
+
+namespace extension {
+namespace humanactivitymonitor {
+
+using common::PlatformResult;
+using common::ErrorCode;
+
+HumanActivityMonitorManager::HumanActivityMonitorManager() {}
+
+HumanActivityMonitorManager::~HumanActivityMonitorManager() {
+ UnsetHrmListener();
+}
+
+PlatformResult HumanActivityMonitorManager::Init() {
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult HumanActivityMonitorManager::IsSupported(
+ const std::string& type) {
+
+ // check cache first
+ if (supported_.count(type)) {
+ return PlatformResult(supported_[type]
+ ? ErrorCode::NO_ERROR
+ : ErrorCode::NOT_SUPPORTED_ERR);
+ }
+
+ int ret;
+ bool supported = false;
+ if (type == kActivityTypePedometer) {
+ // TODO(r.galka) no native api for pedometer
+ // so just pass it for not supported.
+ } else if (type == kActivityTypeWristUp) {
+ // TODO(r.galka) implement when available in platform
+ } else if (type == kActivityTypeHrm) {
+ ret = sensor_is_supported(SENSOR_HRM, &supported);
+ if (ret != SENSOR_ERROR_NONE) {
+ LOGGER(ERROR) << "sensor_is_supported(HRM), error: " << ret;
+ return PlatformResult(ErrorCode::UNKNOWN_ERR,
+ "HRM sensor check failed");
+ }
+ } else if (type == kActivityTypeGps) {
+ // TODO(r.galka) implement when available in platform
+ } else {
+ return PlatformResult(ErrorCode::TYPE_MISMATCH_ERR);
+ }
+
+ supported_[type] = supported;
+
+ return PlatformResult(supported_[type]
+ ? ErrorCode::NO_ERROR
+ : ErrorCode::NOT_SUPPORTED_ERR);
+}
+
+PlatformResult HumanActivityMonitorManager::SetListener(
+ const std::string& type, JsonCallback callback) {
+
+ PlatformResult result = IsSupported(type);
+ if (!result) {
+ return result;
+ }
+
+ int ret;
+
+ // PEDOMETER
+ if (type == kActivityTypePedometer) {
+ // TODO(r.galka) Not Supported in current implementation.
+ }
+
+ // WRIST_UP
+ if (type == kActivityTypeWristUp) {
+ // TODO(r.galka) implement
+ }
+
+ // HRM
+ if (type == kActivityTypeHrm) {
+ return SetHrmListener(callback);
+ }
+
+ // GPS
+ if (type == kActivityTypeGps) {
+ // TODO(r.galka) implement
+ }
+}
+
+PlatformResult HumanActivityMonitorManager::UnsetListener(
+ const std::string& type) {
+
+ PlatformResult result = IsSupported(type);
+ if (!result) {
+ return result;
+ }
+
+ // PEDOMETER
+ if (type == kActivityTypePedometer) {
+ // TODO(r.galka) Not Supported in current implementation.
+ }
+
+ // WRIST_UP
+ if (type == kActivityTypeWristUp) {
+ // TODO(r.galka) implement
+ }
+
+ // HRM
+ if (type == kActivityTypeHrm) {
+ return UnsetHrmListener();
+ }
+
+ // GPS
+ if (type == kActivityTypeGps) {
+ // TODO(r.galka) implement
+ }
+}
+
+// HRM
+PlatformResult HumanActivityMonitorManager::SetHrmListener(
+ JsonCallback callback) {
+ sensor_h hrm_sensor;
+ int ret;
+
+ ret = sensor_get_default_sensor(SENSOR_HRM, &hrm_sensor);
+ if (ret != SENSOR_ERROR_NONE) {
+ LOGGER(ERROR) << "Failed to get HRM sensor, error: " << ret;
+ return PlatformResult(ErrorCode::UNKNOWN_ERR,
+ "Failed to get HRM sensor");
+ }
+
+ ret = sensor_create_listener(hrm_sensor, &hrm_sensor_listener_);
+ if (ret != SENSOR_ERROR_NONE) {
+ LOGGER(ERROR) << "Failed to create HRM sensor listener, error: " << ret;
+ return PlatformResult(ErrorCode::UNKNOWN_ERR,
+ "Failed to create HRM sensor listener");
+ }
+
+ ret = sensor_listener_set_event_cb(hrm_sensor_listener_,
+ 0,
+ OnHrmSensorEvent,
+ this);
+ if (ret != SENSOR_ERROR_NONE) {
+ LOGGER(ERROR) << "Failed to set HRM sensor listener, error: " << ret;
+ return PlatformResult(ErrorCode::UNKNOWN_ERR,
+ "Failed to set HRM sensor listener");
+ }
+
+ ret = sensor_listener_start(hrm_sensor_listener_);
+ if (ret != SENSOR_ERROR_NONE) {
+ LOGGER(ERROR) << "Failed to start HRM sensor listener, error: " << ret;
+ return PlatformResult(ErrorCode::UNKNOWN_ERR,
+ "Failed to start HRM sensor listener");
+ }
+
+ hrm_event_callback_ = callback;
+
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+PlatformResult HumanActivityMonitorManager::UnsetHrmListener() {
+ int ret;
+
+ if (hrm_sensor_listener_) {
+ ret = sensor_listener_stop(hrm_sensor_listener_);
+ if (ret != SENSOR_ERROR_NONE) {
+ LOGGER(ERROR) << "Failed to stop HRM sensor, error: " << ret;
+ return PlatformResult(ErrorCode::UNKNOWN_ERR,
+ "Failed to stop HRM sensor");
+ }
+
+ ret = sensor_listener_unset_event_cb(hrm_sensor_listener_);
+ if (ret != SENSOR_ERROR_NONE) {
+ LOGGER(ERROR) << "Failed to unset HRM sensor listener, error: " << ret;
+ return PlatformResult(ErrorCode::UNKNOWN_ERR,
+ "Failed to unset HRM sensor listener");
+ }
+
+ ret = sensor_destroy_listener(hrm_sensor_listener_);
+ if (ret != SENSOR_ERROR_NONE) {
+ LOGGER(ERROR) << "Failed to destroy HRM sensor listener, error: " << ret;
+ return PlatformResult(ErrorCode::UNKNOWN_ERR,
+ "Failed to destroy HRM sensor listener");
+ }
+ }
+
+ hrm_event_callback_ = nullptr;
+
+ return PlatformResult(ErrorCode::NO_ERROR);
+}
+
+void HumanActivityMonitorManager::OnHrmSensorEvent(
+ sensor_h sensor, sensor_event_s *event, void *user_data) {
+ LOGGER(DEBUG) << "Sensor event:";
+ LOGGER(DEBUG) << " |- accuracy: " << event->accuracy;
+ LOGGER(DEBUG) << " |- timestamp: " << event->timestamp;
+ LOGGER(DEBUG) << " |- value_count: " << event->value_count;
+
+ if (event->value_count < 2) {
+ LOGGER(ERROR) << "To few values of HRM event";
+ return;
+ }
+
+ LOGGER(DEBUG) << " |- values[0]: " << event->values[0];
+ LOGGER(DEBUG) << " |- values[1]: " << event->values[1];
+
+ float hr = event->values[0]; // heart beat rate 0 ~ 220 integer (bpm)
+
+ // there are no public native api for peak to peak interval.
+ // but RRI = (60 / HR) * 1000
+ // or unofficially values[1] is rri (0 ~ 5000 ms)
+ float rri = event->values[1];
+
+ HumanActivityMonitorManager* manager =
+ static_cast<HumanActivityMonitorManager*>(user_data);
+
+ picojson::value hrm_data = picojson::value(picojson::object());
+ picojson::object& hrm_data_o = hrm_data.get<picojson::object>();
+
+ hrm_data_o["heartRate"] = picojson::value(static_cast<double>(hr));
+ hrm_data_o["rRInterval"] = picojson::value(static_cast<double>(rri));
+
+ manager->hrm_event_callback_(&hrm_data);
+}
+
+} // namespace humanactivitymonitor
+} // namespace extension
--- /dev/null
+// Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef HUMANACTIVITYMONITOR_HUMANACTIVITYMONITOR_MANAGER_H
+#define HUMANACTIVITYMONITOR_HUMANACTIVITYMONITOR_MANAGER_H
+
+#include <functional>
+#include <sensor.h>
+#include <gesture_recognition.h>
+#include <string>
+
+#include "common/picojson.h"
+#include "common/platform_result.h"
+
+namespace extension {
+namespace humanactivitymonitor {
+
+namespace {
+const std::string kActivityTypePedometer = "PEDOMETER";
+const std::string kActivityTypeWristUp = "WRIST_UP";
+const std::string kActivityTypeHrm = "HRM";
+const std::string kActivityTypeGps = "GPS";
+}
+
+typedef std::function<void(picojson::value*)> JsonCallback;
+
+class HumanActivityMonitorManager {
+ public:
+ HumanActivityMonitorManager();
+ virtual ~HumanActivityMonitorManager();
+
+ common::PlatformResult Init();
+ common::PlatformResult IsSupported(const std::string& type);
+
+ common::PlatformResult SetListener(const std::string& type,
+ JsonCallback callback);
+ common::PlatformResult UnsetListener(const std::string& type);
+
+ private:
+ std::map<std::string, bool> supported_;
+
+ // HRM
+ sensor_listener_h hrm_sensor_listener_;
+ JsonCallback hrm_event_callback_;
+ common::PlatformResult SetHrmListener(JsonCallback callback);
+ common::PlatformResult UnsetHrmListener();
+ static void OnHrmSensorEvent(sensor_h sensor,
+ sensor_event_s *event,
+ void *data);
+};
+
+} // namespace humanactivitymonitor
+} // namespace extension
+
+#endif // HUMANACTIVITYMONITOR_HUMANACTIVITYMONITOR_MANAGER_H