[HAM] Add SLEEP_DETECTOR and STRESS_MONITOR 18/175218/6
authorLukasz Bardeli <l.bardeli@samsung.com>
Mon, 14 May 2018 07:02:25 +0000 (09:02 +0200)
committerLukasz Bardeli <l.bardeli@samsung.com>
Mon, 14 May 2018 07:02:25 +0000 (09:02 +0200)
[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 <l.bardeli@samsung.com>
src/humanactivitymonitor/humanactivitymonitor_api.js
src/humanactivitymonitor/humanactivitymonitor_extension.cc
src/humanactivitymonitor/humanactivitymonitor_manager.cc

index 691b9533606b77fd1bf8dfeb04f683a1a661c2df..7cc7dae19814612061a2df9a08b9301b8c700ada 100755 (executable)
@@ -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();
index 6074271ec9c081f7cf88d83273b6aaa80ebc6651..e17fc87c794a3c5cb8a2184bc8bc5ed3b75c0b71 100644 (file)
@@ -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() {
index 457c39872341db21e93d91ca15fefb4766781b83..cff30589cf1bebd186f5f5cc49764d11e01fd083 100644 (file)
@@ -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<sensor_sleep_state_e>(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<double>(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<Monitor::GestureMonitor>(kActivityTypeWristUp)));
+  monitors_.insert(std::make_pair(kActivityTypeSleepDetector,
+                                  std::make_shared<Monitor::SensorMonitor>(
+                                      kActivityTypeSleepDetector, SENSOR_HUMAN_SLEEP_DETECTOR,
+                                      convert_sleep_detector, nullptr)));
+  monitors_.insert(std::make_pair(
+      kActivityTypeStressMonitor,
+      std::make_shared<Monitor::SensorMonitor>(
+          kActivityTypeStressMonitor, SENSOR_HUMAN_STRESS_MONITOR, convert_stress, nullptr)));
   monitors_.insert(std::make_pair(
       kActivityTypeHrm, std::make_shared<Monitor::SensorMonitor>(
                             kActivityTypeHrm, SENSOR_HRM, convert_hrm, convert_recorded_hrm)));