From: Pawel Andruszkiewicz Date: Tue, 5 Apr 2016 13:11:09 +0000 (+0200) Subject: [HAM] Added pedometer support. X-Git-Tag: submit/tizen/20160408.075806^2~4^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bfa43f235c081949864533923d5beaab10ea0314;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [HAM] Added pedometer support. Change-Id: I9c454199a40ccd52a579e2a3ceb320a7d6a15fca Signed-off-by: Pawel Andruszkiewicz --- diff --git a/packaging/webapi-plugins.spec b/packaging/webapi-plugins.spec index f3390943..183a19b6 100644 --- a/packaging/webapi-plugins.spec +++ b/packaging/webapi-plugins.spec @@ -338,6 +338,7 @@ BuildRequires: pkgconfig(capi-web-url-download) BuildRequires: pkgconfig(motion) BuildRequires: pkgconfig(capi-system-sensor) BuildRequires: pkgconfig(capi-location-manager) +BuildRequires: pkgconfig(sensor) %endif %if 0%{?tizen_feature_iotcon_support} diff --git a/src/humanactivitymonitor/humanactivitymonitor.gyp b/src/humanactivitymonitor/humanactivitymonitor.gyp index 38f27a38..6c250c18 100755 --- a/src/humanactivitymonitor/humanactivitymonitor.gyp +++ b/src/humanactivitymonitor/humanactivitymonitor.gyp @@ -25,6 +25,7 @@ 'motion', 'capi-system-sensor', 'capi-location-manager', + 'sensor', ] }, }], diff --git a/src/humanactivitymonitor/humanactivitymonitor_api.js b/src/humanactivitymonitor/humanactivitymonitor_api.js index b40a82a9..e71b6a7b 100755 --- a/src/humanactivitymonitor/humanactivitymonitor_api.js +++ b/src/humanactivitymonitor/humanactivitymonitor_api.js @@ -32,6 +32,8 @@ function SetReadOnlyProperty(obj, n, v) { Object.defineProperty(obj, n, {value: v, writable: false}); } +var ACCUMULATIVE_PEDOMETER_DATA = 'ACCUMULATIVE_PEDOMETER_DATA'; + var HumanActivityType = { PEDOMETER: 'PEDOMETER', WRIST_UP: 'WRIST_UP', @@ -67,8 +69,9 @@ var SleepStatus = { function convertActivityData(type, data) { switch (type) { case HumanActivityType.PEDOMETER: - // TODO(r.galka) Not Supported in current implementation - return undefined; + return new HumanActivityPedometerData(data); + case ACCUMULATIVE_PEDOMETER_DATA: + return new HumanActivityAccumulativePedometerData(data); case HumanActivityType.WRIST_UP: return null; case HumanActivityType.HRM: @@ -206,6 +209,22 @@ function stopListener(listenerId, method, data) { native_.removeListener(listenerId); } +// Pedometer listener and accumulative pedometer listener are handled by a single +// callback. Native side sends both objects, JS side needs to pass the data to +// appropriate listeners. +var pedometerListener = null; +var accumulativePedometerListener = null; + +function pedometerCallback(result) { + if (pedometerListener) { + pedometerListener(convertActivityData(HumanActivityType.PEDOMETER, result)); + } + + if (accumulativePedometerListener) { + accumulativePedometerListener(convertActivityData(ACCUMULATIVE_PEDOMETER_DATA, result)); + } +} + HumanActivityMonitorManager.prototype.start = function(type, changedCallback) { var args = validator_.validateArgs(arguments, [ {name: 'type', type: types_.ENUM, values: Object.keys(HumanActivityType)}, @@ -241,11 +260,13 @@ HumanActivityMonitorManager.prototype.start = function(type, changedCallback) { break; } + var listener = HumanActivityType.PEDOMETER === args.type ? pedometerCallback : function(result) { + native_.callIfPossible(args.changedCallback, convertActivityData(args.type, result)); + }; + console.log("callbackInterval = " + callbackInterval + ", sampleInterval = " + sampleInterval); startListener(listenerId, - function(result) { - native_.callIfPossible(args.changedCallback, convertActivityData(args.type, result)); - }, + listener, 'HumanActivityMonitorManager_start', { type: args.type, listenerId: listenerId, @@ -253,6 +274,10 @@ HumanActivityMonitorManager.prototype.start = function(type, changedCallback) { sampleInterval: sampleInterval } ); + + if (HumanActivityType.PEDOMETER === args.type) { + pedometerListener = args.changedCallback; + } }; HumanActivityMonitorManager.prototype.stop = function(type) { @@ -263,29 +288,34 @@ HumanActivityMonitorManager.prototype.stop = function(type) { stopListener('HumanActivityMonitor_' + args.type, 'HumanActivityMonitorManager_stop', { type: args.type }); -}; -var accumulativePedometerListenerId = 'HumanActivityMonitor_AccumulativePedometerListener'; + if (HumanActivityType.PEDOMETER === args.type) { + pedometerListener = null; + } +}; -HumanActivityMonitorManager.prototype.setAccumulativePedometerListener = function(changeCallback) { +HumanActivityMonitorManager.prototype.setAccumulativePedometerListener = function() { var args = validator_.validateArgs(arguments, [ {name: 'changeCallback', type: types_.FUNCTION} ]); - var listenerId = accumulativePedometerListenerId; + var oldPedometerListener = pedometerListener; - startListener(listenerId, - function(result) { - args.changeCallback(convertActivityData(HumanActivityType.PEDOMETER, result)); - }, - 'HumanActivityMonitorManager_setAccumulativePedometerListener', - { listenerId: listenerId }); + // calling start() will overwrite pedometerListener, needs to be restored afterwards + this.start(HumanActivityType.PEDOMETER, args.changeCallback); + + accumulativePedometerListener = args.changeCallback; + pedometerListener = oldPedometerListener; }; HumanActivityMonitorManager.prototype.unsetAccumulativePedometerListener = function() { - stopListener(accumulativePedometerListenerId, - 'HumanActivityMonitorManager_unsetAccumulativePedometerListener', - {}); + var oldPedometerListener = pedometerListener; + + // calling stop() will overwrite pedometerListener, needs to be restored afterwards + this.stop(HumanActivityType.PEDOMETER); + + accumulativePedometerListener = null; + pedometerListener = oldPedometerListener; }; @@ -327,9 +357,9 @@ HumanActivityMonitorManager.prototype.removeActivityRecognitionListener = functi activityRecognitionListener.removeListener(args.watchId); }; -function StepDifference() { - SetReadOnlyProperty(this, 'stepCountDifference', null); - SetReadOnlyProperty(this, 'timestamp', null); +function StepDifference(data) { + SetReadOnlyProperty(this, 'stepCountDifference', data.stepCountDifference); + SetReadOnlyProperty(this, 'timestamp', data.timestamp); } @@ -337,32 +367,42 @@ function HumanActivityData() { } -function HumanActivityPedometerData() { - SetReadOnlyProperty(this, 'stepStatus', null); - SetReadOnlyProperty(this, 'speed', null); - SetReadOnlyProperty(this, 'walkingFrequency', null); - SetReadOnlyProperty(this, 'cumulativeDistance', null); - SetReadOnlyProperty(this, 'cumulativeCalorie', null); - SetReadOnlyProperty(this, 'cumulativeTotalStepCount', null); - SetReadOnlyProperty(this, 'cumulativeWalkStepCount', null); - SetReadOnlyProperty(this, 'cumulativeRunStepCount', null); - SetReadOnlyProperty(this, 'stepCountDifferences', null); +function HumanActivityPedometerData(data) { + SetReadOnlyProperty(this, 'stepStatus', data.stepStatus); + SetReadOnlyProperty(this, 'speed', data.speed); + SetReadOnlyProperty(this, 'walkingFrequency', data.walkingFrequency); + SetReadOnlyProperty(this, 'cumulativeDistance', data.cumulativeDistance); + SetReadOnlyProperty(this, 'cumulativeCalorie', data.cumulativeCalorie); + SetReadOnlyProperty(this, 'cumulativeTotalStepCount', data.cumulativeTotalStepCount); + SetReadOnlyProperty(this, 'cumulativeWalkStepCount', data.cumulativeWalkStepCount); + SetReadOnlyProperty(this, 'cumulativeRunStepCount', data.cumulativeRunStepCount); + + var steps = []; + for (var i = 0; i < data.stepCountDifferences.length; ++i) { + steps.push(new StepDifference(data.stepCountDifferences[i])); + } + SetReadOnlyProperty(this, 'stepCountDifferences', steps); } HumanActivityPedometerData.prototype = new HumanActivityData(); HumanActivityPedometerData.prototype.constructor = HumanActivityPedometerData; -function HumanActivityAccumulativePedometerData() { - SetReadOnlyProperty(this, 'stepStatus', null); - SetReadOnlyProperty(this, 'speed', null); - SetReadOnlyProperty(this, 'walkingFrequency', null); - SetReadOnlyProperty(this, 'accumulativeDistance', null); - SetReadOnlyProperty(this, 'accumulativeCalorie', null); - SetReadOnlyProperty(this, 'accumulativeTotalStepCount', null); - SetReadOnlyProperty(this, 'accumulativeWalkStepCount', null); - SetReadOnlyProperty(this, 'accumulativeRunStepCount', null); - SetReadOnlyProperty(this, 'stepCountDifferences', null); +function HumanActivityAccumulativePedometerData(data) { + SetReadOnlyProperty(this, 'stepStatus', data.stepStatus); + SetReadOnlyProperty(this, 'speed', data.speed); + SetReadOnlyProperty(this, 'walkingFrequency', data.walkingFrequency); + SetReadOnlyProperty(this, 'accumulativeDistance', data.accumulativeDistance); + SetReadOnlyProperty(this, 'accumulativeCalorie', data.accumulativeCalorie); + SetReadOnlyProperty(this, 'accumulativeTotalStepCount', data.accumulativeTotalStepCount); + SetReadOnlyProperty(this, 'accumulativeWalkStepCount', data.accumulativeWalkStepCount); + SetReadOnlyProperty(this, 'accumulativeRunStepCount', data.accumulativeRunStepCount); + + var steps = []; + for (var i = 0; i < data.stepCountDifferences.length; ++i) { + steps.push(new StepDifference(data.stepCountDifferences[i])); + } + SetReadOnlyProperty(this, 'stepCountDifferences', steps); } HumanActivityAccumulativePedometerData.prototype = new HumanActivityData(); diff --git a/src/humanactivitymonitor/humanactivitymonitor_instance.cc b/src/humanactivitymonitor/humanactivitymonitor_instance.cc index f00a6b9b..d572ba34 100755 --- a/src/humanactivitymonitor/humanactivitymonitor_instance.cc +++ b/src/humanactivitymonitor/humanactivitymonitor_instance.cc @@ -54,10 +54,6 @@ HumanActivityMonitorInstance::HumanActivityMonitorInstance() { HumanActivityMonitorManagerStart); REGISTER_SYNC("HumanActivityMonitorManager_stop", HumanActivityMonitorManagerStop); - REGISTER_SYNC("HumanActivityMonitorManager_setAccumulativePedometerListener", - HumanActivityMonitorManagerSetAccumulativePedometerListener); - REGISTER_SYNC("HumanActivityMonitorManager_unsetAccumulativePedometerListener", - HumanActivityMonitorManagerUnsetAccumulativePedometerListener); REGISTER_SYNC("HumanActivityMonitorManager_addActivityRecognitionListener", HumanActivityMonitorManagerAddActivityRecognitionListener); REGISTER_SYNC("HumanActivityMonitorManager_removeActivityRecognitionListener", @@ -204,24 +200,6 @@ void HumanActivityMonitorInstance::HumanActivityMonitorManagerStop( } } -void HumanActivityMonitorInstance::HumanActivityMonitorManagerSetAccumulativePedometerListener( - const picojson::value& args, picojson::object& out) { - LoggerD("Enter"); - - CHECK_PRIVILEGE_ACCESS(kPrivilegeHealthInfo, &out); - - // TODO(r.galka) implement -} - -void HumanActivityMonitorInstance::HumanActivityMonitorManagerUnsetAccumulativePedometerListener( - const picojson::value& args, picojson::object& out) { - LoggerD("Enter"); - - CHECK_PRIVILEGE_ACCESS(kPrivilegeHealthInfo, &out); - - // TODO(r.galka) implement -} - void HumanActivityMonitorInstance::HumanActivityMonitorManagerAddActivityRecognitionListener( const picojson::value& args, picojson::object& out) { LoggerD("Enter"); diff --git a/src/humanactivitymonitor/humanactivitymonitor_instance.h b/src/humanactivitymonitor/humanactivitymonitor_instance.h index 9ee22a78..07f0e1ae 100755 --- a/src/humanactivitymonitor/humanactivitymonitor_instance.h +++ b/src/humanactivitymonitor/humanactivitymonitor_instance.h @@ -34,14 +34,10 @@ class HumanActivityMonitorInstance : public common::ParsedInstance { private: void HumanActivityMonitorManagerStop( const picojson::value& args, picojson::object& out); - void HumanActivityMonitorManagerUnsetAccumulativePedometerListener( - const picojson::value& args, picojson::object& out); void HumanActivityMonitorManagerGetHumanActivityData( const picojson::value& args, picojson::object& out); void HumanActivityMonitorManagerStart( const picojson::value& args, picojson::object& out); - void HumanActivityMonitorManagerSetAccumulativePedometerListener( - const picojson::value& args, picojson::object& out); void HumanActivityMonitorManagerAddActivityRecognitionListener( const picojson::value& args, picojson::object& out); void HumanActivityMonitorManagerRemoveActivityRecognitionListener( diff --git a/src/humanactivitymonitor/humanactivitymonitor_manager.cc b/src/humanactivitymonitor/humanactivitymonitor_manager.cc index a32dbf48..d75da607 100755 --- a/src/humanactivitymonitor/humanactivitymonitor_manager.cc +++ b/src/humanactivitymonitor/humanactivitymonitor_manager.cc @@ -20,6 +20,7 @@ #include #include #include +#include #include "common/logger.h" #include "common/optional.h" @@ -51,6 +52,85 @@ const std::string kSampleInterval = "sampleInterval"; const std::string kStatus = "status"; const std::string kTimestamp = "timestamp"; +const std::string kStepStatus = "stepStatus"; +const std::string kSpeed = "speed"; +const std::string kWalkingFrequency = "walkingFrequency"; +const std::string kCumulativeDistance = "cumulativeDistance"; +const std::string kCumulativeCalorie = "cumulativeCalorie"; +const std::string kCumulativeTotalStepCount = "cumulativeTotalStepCount"; +const std::string kCumulativeWalkStepCount = "cumulativeWalkStepCount"; +const std::string kCumulativeRunStepCount = "cumulativeRunStepCount"; +const std::string kStepCountDifferences = "stepCountDifferences"; +const std::string kStepCountDifference = "stepCountDifference"; + +const std::string kAccumulativeDistance = "accumulativeDistance"; +const std::string kAccumulativeCalorie = "accumulativeCalorie"; +const std::string kAccumulativeTotalStepCount = "accumulativeTotalStepCount"; +const std::string kAccumulativeWalkStepCount = "accumulativeWalkStepCount"; +const std::string kAccumulativeRunStepCount = "accumulativeRunStepCount"; + +// helper structure, allows easier access to data values +struct PedometerDataWrapper : public sensor_pedometer_data_t { + inline float steps() const { + return values[0]; + } + + inline float walk_steps() const { + return values[1]; + } + + inline float run_steps() const { + return values[2]; + } + + inline float distance() const { + return values[3]; + } + + inline float calories() const { + return values[4]; + } + + inline float speed() const { + return values[5]; + } + + inline float frequency() const { + return values[6]; + } + + inline sensor_pedometer_state_e state() const { + return static_cast(values[7]); + } +}; + +void InsertStepDifference(float step_difference, float timestamp, picojson::array* out) { + ScopeLogger(); + + picojson::object d; + + d.insert(std::make_pair(kStepCountDifference, picojson::value(step_difference))); + d.insert(std::make_pair(kTimestamp, picojson::value(timestamp))); + + out->push_back(picojson::value{d}); +} + +std::string FromSensorPedometerState(sensor_pedometer_state_e e) { + switch (e) { + case SENSOR_PEDOMETER_STATE_STOP: + return "NOT_MOVING"; + + case SENSOR_PEDOMETER_STATE_WALK: + return "WALKING"; + + case SENSOR_PEDOMETER_STATE_RUN: + return "RUNNING"; + + default: + return "UNKNOWN"; + } +} + } // namespace const std::string kActivityTypeGps = "GPS"; @@ -815,6 +895,51 @@ HumanActivityMonitorManager::HumanActivityMonitorManager() : activity_recognition_(std::make_shared()) { ScopeLogger(); + auto convert_pedometer = [](sensor_event_s* event, picojson::object* data) -> PlatformResult { + ScopeLogger("convert_pedometer"); + + const auto pedometer_data = (PedometerDataWrapper*)event; + + static const auto initial_pedometer_data = *pedometer_data; // will be initialized only once + static float steps_so_far = 0.0; + + const auto state = pedometer_data->state(); + + if (SENSOR_PEDOMETER_STATE_UNKNOWN == state) { + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown sensor step state"); + } + + data->insert(std::make_pair(kStepStatus, picojson::value(FromSensorPedometerState(state)))); + data->insert(std::make_pair(kSpeed, picojson::value(pedometer_data->speed()))); + data->insert(std::make_pair(kWalkingFrequency, picojson::value(pedometer_data->frequency()))); + + data->insert(std::make_pair(kCumulativeDistance, picojson::value(pedometer_data->distance() - initial_pedometer_data.distance()))); + data->insert(std::make_pair(kCumulativeCalorie, picojson::value(pedometer_data->calories() - initial_pedometer_data.calories()))); + data->insert(std::make_pair(kCumulativeTotalStepCount, picojson::value(pedometer_data->steps() - initial_pedometer_data.steps()))); + data->insert(std::make_pair(kCumulativeWalkStepCount, picojson::value(pedometer_data->walk_steps() - initial_pedometer_data.walk_steps()))); + data->insert(std::make_pair(kCumulativeRunStepCount, picojson::value(pedometer_data->run_steps() - initial_pedometer_data.run_steps()))); + + data->insert(std::make_pair(kAccumulativeDistance, picojson::value(pedometer_data->distance()))); + data->insert(std::make_pair(kAccumulativeCalorie, picojson::value(pedometer_data->calories()))); + data->insert(std::make_pair(kAccumulativeTotalStepCount, picojson::value(pedometer_data->steps()))); + data->insert(std::make_pair(kAccumulativeWalkStepCount, picojson::value(pedometer_data->walk_steps()))); + data->insert(std::make_pair(kAccumulativeRunStepCount, picojson::value(pedometer_data->run_steps()))); + + auto& diffs = data->insert(std::make_pair(kStepCountDifferences, picojson::value{picojson::array{}})).first->second.get(); + + if (pedometer_data->diffs_count > 0) { + for (int i = 0; i < pedometer_data->diffs_count; ++i) { + InsertStepDifference(pedometer_data->diffs[i].steps, pedometer_data->diffs[i].timestamp, &diffs); + } + } else { + InsertStepDifference(steps_so_far > 0.0 ? pedometer_data->steps() - steps_so_far : 0.0, pedometer_data->timestamp, &diffs); + } + + steps_so_far = pedometer_data->steps(); + + return PlatformResult(ErrorCode::NO_ERROR); + }; + auto convert_hrm = [](sensor_event_s* event, picojson::object* data) -> PlatformResult { ScopeLogger("convert_hrm"); @@ -879,7 +1004,7 @@ HumanActivityMonitorManager::HumanActivityMonitorManager() return PlatformResult(ErrorCode::NO_ERROR); }; - monitors_.insert(std::make_pair(kActivityTypePedometer, std::make_shared(kActivityTypePedometer))); // not supported + monitors_.insert(std::make_pair(kActivityTypePedometer, std::make_shared(kActivityTypePedometer, SENSOR_HUMAN_PEDOMETER, convert_pedometer))); monitors_.insert(std::make_pair(kActivityTypeWristUp, std::make_shared(kActivityTypeWristUp))); monitors_.insert(std::make_pair(kActivityTypeHrm, std::make_shared(kActivityTypeHrm, SENSOR_HRM, convert_hrm))); monitors_.insert(std::make_pair(kActivityTypeGps, std::make_shared(kActivityTypeGps)));