From: Lukasz Bardeli Date: Mon, 14 May 2018 07:02:25 +0000 (+0200) Subject: [HAM] Add SLEEP_DETECTOR and STRESS_MONITOR X-Git-Tag: submit/tizen/20180518.121229~7^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b15212367cc89189c588636ef553c0941dd52c64;p=platform%2Fcore%2Fapi%2Fwebapi-plugins.git [HAM] Add SLEEP_DETECTOR and STRESS_MONITOR [Verification] Code compiles without error. Tested in chrome console var listenerId; function errorCallback(error) { alert(error.name + ": " + error.message); console.log(error.name + ": " + error.message); } function listener(label) { alert("Stress level: " + label); console.log("Stress level: " + label); } var ranges = [new tizen.StressMonitorDataRange("Normal",10, 50), new tizen.StressMonitorDataRange("Stress Alarm 1",0, 20), new tizen.StressMonitorDataRange("Stress Alarm 2",50), new tizen.StressMonitorDataRange("Stress Alarm 3",30,100)]; try { listenerId = tizen.humanactivitymonitor.addStressMonitorChangeListener(ranges, listener, errorCallback); } catch (error) { console.log(error.name + ": " + error.message); } function onchangedCB(info) { alert("score: " + info.stressScore); console.log("score: " + info.stressScore); } function onerrorCB(error) { alert("Error occurred, name: " + error.name + ", message: " + error.message); console.log("Error occurred, name: " + error.name + ", message: " + error.message); } try { tizen.humanactivitymonitor.start("STRESS_MONITOR", onchangedCB, onerrorCB, {callbackInterval: 1500, sampleInterval: 100}); } catch (err) { console.log(err.name + ": " + err.message); } ACR: http://suprem.sec.samsung.net/jira/browse/TWDAPI-178 Change-Id: I56aaba87989d84d8364a8212afd98eff3d8edcee Signed-off-by: Lukasz Bardeli --- diff --git a/src/humanactivitymonitor/humanactivitymonitor_api.js b/src/humanactivitymonitor/humanactivitymonitor_api.js index 691b9533..7cc7dae1 100755 --- a/src/humanactivitymonitor/humanactivitymonitor_api.js +++ b/src/humanactivitymonitor/humanactivitymonitor_api.js @@ -15,6 +15,7 @@ */ var utils_ = xwalk.utils; +var privilege_ = utils_.privilege; var type_ = utils_.type; var converter_ = utils_.converter; var validator_ = utils_.validator; @@ -43,7 +44,9 @@ var HumanActivityType = { WRIST_UP: 'WRIST_UP', HRM: 'HRM', GPS: 'GPS', - SLEEP_MONITOR: 'SLEEP_MONITOR' + SLEEP_MONITOR: 'SLEEP_MONITOR', + SLEEP_DETECTOR: 'SLEEP_DETECTOR', + STRESS_MONITOR: 'STRESS_MONITOR' }; var HumanActivityRecorderType = { @@ -108,6 +111,10 @@ function convertActivityData(type, data) { return new HumanActivityGPSInfoArray(gpsInfo); case HumanActivityType.SLEEP_MONITOR: return new HumanActivitySleepMonitorData(data); + case HumanActivityType.SLEEP_DETECTOR: + return new HumanActivitySleepDetectorData(data); + case HumanActivityType.STRESS_MONITOR: + return new HumanActivityStressMonitorData(data); default: utils_.error('Uknown human activity type: ' + type); } @@ -146,6 +153,51 @@ function convertActivityRecorderData(type, data) { return createRecorderData(func, data); } +function StressMonitorDataRange(label, min, max) { + validator_.validateConstructorCall(this, tizen.StressMonitorDataRange); + + var args = validator_.validateArgs(arguments, [ + { name: 'label', type: types_.STRING, optional: true, nullable: false }, + { name: 'min', type: types_.UNSIGNED_LONG, optional: true, nullable: false }, + { name: 'max', type: types_.UNSIGNED_LONG, optional: true, nullable: false } + ]); + + var _label = !type_.isNullOrUndefined(args.label) ? args.label : ""; + var _min = !type_.isNullOrUndefined(args.min) ? args.min : 0; + var _max = !type_.isNull(args.max) ? args.max : undefined; + + Object.defineProperties(this, { + label: { + get: function() { + return _label; + }, + set: function(v) { + _label = !type_.isNullOrUndefined(v) ? v : _label; + }, + enumerable: true + }, + min: { + get: function() { + return _min; + }, + set: function(v) { + _min = !type_.isNullOrUndefined(v) ? converter_.toUnsignedLong(v) : _min; + }, + enumerable: true + }, + max: { + get: function() { + return _max; + }, + set: function(v) { + _max = !type_.isNullOrUndefined(v) ? converter_.toUnsignedLong(v) : _max; + }, + enumerable: true + } + }); +}; + + function ActivityRecognitionListenerManager() { this.listeners = {}; this.nextId = 1; @@ -288,6 +340,8 @@ function GPSCallback(result) { } } +var stressListener = null; + HumanActivityMonitorManager.prototype.start = function(type, changedCallback) { var args = validator_.validateArgs(arguments, [ {name: 'type', type: types_.ENUM, values: Object.keys(HumanActivityType)}, @@ -296,7 +350,7 @@ HumanActivityMonitorManager.prototype.start = function(type, changedCallback) { {name: 'options', type : types_.DICTIONARY, optional : true, nullable : true} ]); - var listenerId = 'HumanActivityMonitor_' + args.type; + var listenerId = 'HumanActivityMonitor_' + args.type; var optionsAttributes = ["callbackInterval", "sampleInterval"], options = args.options || {}; var callbackInterval = null, sampleInterval = null; @@ -326,6 +380,9 @@ HumanActivityMonitorManager.prototype.start = function(type, changedCallback) { case HumanActivityType.GPS: listener = GPSCallback; break; + case HumanActivityType.STRESS_MONITOR: + listener = stressMonitorListener.onListener; + break; default: listener = function(result) { native_.callIfPossible(args.changedCallback, convertActivityData(args.type, result)); @@ -347,7 +404,7 @@ HumanActivityMonitorManager.prototype.start = function(type, changedCallback) { pedometerListener = args.changedCallback; } - if (HumanActivityType.GPS === args.type) { + if (HumanActivityType.GPS === args.type || HumanActivityType.STRESS_MONITOR === args.type) { var callback = function(result) { if (native_.isFailure(result)) { native_.callIfPossible(args.errorCallback, native_.getErrorObject(result)); @@ -356,7 +413,11 @@ HumanActivityMonitorManager.prototype.start = function(type, changedCallback) { } }; - GPSListener = callback; + if (HumanActivityType.GPS === args.type) { + GPSListener = callback; + } else if (HumanActivityType.STRESS_MONITOR === args.type){ + stressListener = callback; + } } }; @@ -380,6 +441,10 @@ HumanActivityMonitorManager.prototype.stop = function(type) { if (HumanActivityType.GPS === args.type) { GPSListener = null; } + + if (HumanActivityType.STRESS_MONITOR === args.type) { + stressListener = null; + } }; HumanActivityMonitorManager.prototype.setAccumulativePedometerListener = function() { @@ -675,6 +740,78 @@ HumanActivityMonitorManager.prototype.removeGestureRecognitionListener = functio gestureRecognitionListener.removeListener(args.watchId); }; +function StressMonitorListenerManager() { + this.listeners = {}; + this.nextId = 1; +}; + +StressMonitorListenerManager.prototype.onListener = function(data) { + + if (stressListener) { + stressListener(data); + } + var score = data.stressScore; + for (var watchId in stressMonitorListener.listeners) { + if (stressMonitorListener.listeners.hasOwnProperty(watchId)) { + var _listener = stressMonitorListener.listeners[watchId]; + var rangeArray = _listener.ranges; + for (var id in rangeArray) { + var _min = rangeArray[id].min; + var _max = !type_.isUndefined(rangeArray[id].max) ? rangeArray[id].max : Number.MAX_VALUE; + if ((score >= _min && score < _max) && (_listener.lastStressScore < _min || _listener.lastStressScore >= _max)) { + _listener.listener(rangeArray[id].label); + } + } + _listener.lastStressScore = score; + } + } +}; + +StressMonitorListenerManager.prototype.addListener = function(ranges, listener, errorCallback) { + + var id = this.nextId++; + + this.listeners[id] = { + ranges: ranges, + listener: listener, + lastStressScore: -1 + }; + + return id; +}; + +StressMonitorListenerManager.prototype.removeListener = function(watchId) { + if (this.listeners.hasOwnProperty(watchId)) { + delete this.listeners[watchId]; + } +}; + +var stressMonitorListener = new StressMonitorListenerManager(); + +HumanActivityMonitorManager.prototype.addStressMonitorChangeListener = function() { + utils_.checkPrivilegeAccess(privilege_.HEALTHINFO); + var args = validator_.validateMethod(arguments, [{ + name : 'ranges', + type: types_.ARRAY, + values: StressMonitorDataRange + }, + { + name : 'listener', + type : types_.FUNCTION + }]); + + return stressMonitorListener.addListener(args.ranges, args.listener); +}; + +HumanActivityMonitorManager.prototype.removeStressMonitorChangeListener = function() { + var args = validator_.validateMethod(arguments, [{ + name : 'watchId', + type : types_.LONG, + }]); + + stressMonitorListener.removeListener(args.watchId); +}; + function StepDifference(data) { SetReadOnlyProperty(this, 'stepCountDifference', data.stepCountDifference); SetReadOnlyProperty(this, 'timestamp', data.timestamp); @@ -769,6 +906,20 @@ function HumanActivitySleepMonitorData(data) { HumanActivitySleepMonitorData.prototype = new HumanActivityData(); HumanActivitySleepMonitorData.prototype.constructor = HumanActivitySleepMonitorData; +function HumanActivitySleepDetectorData(data) { + SetReadOnlyProperty(this, 'status', data.status); +} + +HumanActivitySleepDetectorData.prototype = new HumanActivityData(); +HumanActivitySleepDetectorData.prototype.constructor = HumanActivitySleepMonitorData; + +function HumanActivityStressMonitorData(data) { + SetReadOnlyProperty(this, 'stressScore', data.stressScore); +} + +HumanActivityStressMonitorData.prototype = new HumanActivityData(); +HumanActivityStressMonitorData.prototype.constructor = HumanActivityStressMonitorData + //Recorded data function HumanActivityRecorderData(data) { if (data) { @@ -831,4 +982,6 @@ function GestureData(data) { HumanActivityRecorderPressureData.prototype = new HumanActivityRecorderData(); HumanActivityRecorderPressureData.prototype.constructor = HumanActivityRecorderPressureData; +tizen.StressMonitorDataRange = StressMonitorDataRange; + exports = new HumanActivityMonitorManager(); diff --git a/src/humanactivitymonitor/humanactivitymonitor_extension.cc b/src/humanactivitymonitor/humanactivitymonitor_extension.cc index 6074271e..e17fc87c 100644 --- a/src/humanactivitymonitor/humanactivitymonitor_extension.cc +++ b/src/humanactivitymonitor/humanactivitymonitor_extension.cc @@ -27,6 +27,9 @@ common::Extension* CreateExtension() { HumanActivityMonitorExtension::HumanActivityMonitorExtension() { SetExtensionName("tizen.humanactivitymonitor"); SetJavaScriptAPI(kSource_humanactivitymonitor_api); + + const char* entry_points[] = {"tizen.StressMonitorDataRange", NULL}; + SetExtraJSEntryPoints(entry_points); } HumanActivityMonitorExtension::~HumanActivityMonitorExtension() { diff --git a/src/humanactivitymonitor/humanactivitymonitor_manager.cc b/src/humanactivitymonitor/humanactivitymonitor_manager.cc index 457c3987..cff30589 100644 --- a/src/humanactivitymonitor/humanactivitymonitor_manager.cc +++ b/src/humanactivitymonitor/humanactivitymonitor_manager.cc @@ -48,6 +48,8 @@ const std::string kActivityTypeWristUp = "WRIST_UP"; const std::string kActivityTypeHrm = "HRM"; const std::string kActivityTypeSleepMonitor = "SLEEP_MONITOR"; const std::string kActivityTypePressure = "PRESSURE"; +const std::string kActivityTypeSleepDetector = "SLEEP_DETECTOR"; +const std::string kActivityTypeStressMonitor = "STRESS_MONITOR"; const std::string kSleepStateAwake = "AWAKE"; const std::string kSleepStateAsleep = "ASLEEP"; @@ -58,6 +60,7 @@ const std::string kSampleInterval = "sampleInterval"; const std::string kStatus = "status"; const std::string kTimestamp = "timestamp"; +const std::string kStressScore = "stressScore"; const std::string kStepStatus = "stepStatus"; const std::string kSpeed = "speed"; @@ -1445,6 +1448,53 @@ HumanActivityMonitorManager::HumanActivityMonitorManager() return ConvertRecordedTime(data, obj); }; + auto convert_sleep_detector = [](sensor_event_s* event, + picojson::object* data) -> PlatformResult { + ScopeLogger("convert_sleep_detector"); + + if (event->value_count < 1) { + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "To few values of SLEEP event"); + } + + sensor_sleep_state_e state = static_cast(event->values[0]); + std::string sleep_state; + + switch (state) { + case SENSOR_SLEEP_STATE_WAKE: + sleep_state = kSleepStateAwake; + break; + + case SENSOR_SLEEP_STATE_SLEEP: + sleep_state = kSleepStateAsleep; + break; + + case SENSOR_SLEEP_STATE_UNKNOWN: + sleep_state = kSleepStateUnknown; + break; + + default: + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "Unknown sleep state", + ("Unknown sleep state: %d", state)); + } + + data->insert(std::make_pair(kStatus, picojson::value(sleep_state))); + + return PlatformResult(ErrorCode::NO_ERROR); + }; + + auto convert_stress = [](sensor_event_s* event, picojson::object* data) -> PlatformResult { + ScopeLogger("convert_stress"); + + if (event->value_count < 1) { + return LogAndCreateResult(ErrorCode::UNKNOWN_ERR, "To few values of STRESS event"); + } + + float stress_score = event->values[0]; + data->insert(std::make_pair(kStressScore, picojson::value(static_cast(stress_score)))); + + return PlatformResult(ErrorCode::NO_ERROR); + }; + auto convert_recorded_hrm = [](void* data, picojson::object* obj) -> PlatformResult { ScopeLogger("Entered into asynchronous function, convert_recorded_hrm"); @@ -1494,6 +1544,14 @@ HumanActivityMonitorManager::HumanActivityMonitorManager() convert_pedometer, convert_recorded_pedometer))); monitors_.insert(std::make_pair(kActivityTypeWristUp, std::make_shared(kActivityTypeWristUp))); + monitors_.insert(std::make_pair(kActivityTypeSleepDetector, + std::make_shared( + kActivityTypeSleepDetector, SENSOR_HUMAN_SLEEP_DETECTOR, + convert_sleep_detector, nullptr))); + monitors_.insert(std::make_pair( + kActivityTypeStressMonitor, + std::make_shared( + kActivityTypeStressMonitor, SENSOR_HUMAN_STRESS_MONITOR, convert_stress, nullptr))); monitors_.insert(std::make_pair( kActivityTypeHrm, std::make_shared( kActivityTypeHrm, SENSOR_HRM, convert_hrm, convert_recorded_hrm)));