node-aurora
Version:
Provides an interface to the Aurora Dreamband.
250 lines (175 loc) • 8.23 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
var _getIterator2 = require('babel-runtime/core-js/get-iterator');
var _getIterator3 = _interopRequireDefault(_getIterator2);
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
var _assign = require('babel-runtime/core-js/object/assign');
var _assign2 = _interopRequireDefault(_assign);
var _typeof2 = require('babel-runtime/helpers/typeof');
var _typeof3 = _interopRequireDefault(_typeof2);
var _promise = require('babel-runtime/core-js/promise');
var _promise2 = _interopRequireDefault(_promise);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _AuroraConstants = require('./AuroraConstants');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var AuroraSessionParser = function AuroraSessionParser() {
(0, _classCallCheck3.default)(this, AuroraSessionParser);
};
AuroraSessionParser.parseSessionTxtObject = function (sessionTxtObject) {
var session = {
awakenings: 0,
sleepOnset: 0,
incomplete: false,
awakeAt: 0,
asleepAt: 0,
sleepScore: 0,
sleepDuration: {
total: 0,
unknown: 0,
awake: 0,
light: 0,
deep: 0,
rem: 0
},
events: [],
streams: []
};
var throwError = function throwError(error) {
session.error = error;
return _promise2.default.reject(session);
};
if ((typeof sessionTxtObject === 'undefined' ? 'undefined' : (0, _typeof3.default)(sessionTxtObject)) != 'object') return throwError('Session object invalid.');
//TODO: consider using deep assign
(0, _assign2.default)(session, sessionTxtObject);
if (!session.version || !session.date || !session.profile || !session.duration) return throwError('Session corrupted.');
if (parseInt(session.version) < 20001) return throwError('Aurora firmware version no longer supported.');
if (!Array.isArray(session.events)) return throwError('Session event array corrupted.');
if (!Array.isArray(session.streams)) return throwError('Session stream array corrupted.');
//if (session.duration < 1000 * 60 * 30) return throwError('Session is shorter than 30 minutes.');
for (var i = 0; i < session.events.length; i++) {
var event = session.events[i];
if (!event || (typeof event === 'undefined' ? 'undefined' : (0, _typeof3.default)(event)) != 'object') {
//todo: fix this mess...
//console.log('Missing event at index: ' + i);
session.events.splice(i, 1);
i--;
continue;
}
if (typeof event.id == 'undefined' || typeof event.time == 'undefined' || typeof event.flags == 'undefined') {
//console.log('Session event corrupted at index: ' + i);
session.events.splice(i, 1);
i--;
continue;
}
event.date = session.date + event.time;
}
if (session.streams) {
for (var _i = 0; _i < session.streams.length; _i++) {
var stream = session.streams[_i];
if (!stream || (typeof stream === 'undefined' ? 'undefined' : (0, _typeof3.default)(stream)) != 'object') {
//console.log('Missing stream at index: ' + i);
session.streams.splice(_i, 1);
_i--;
continue;
}
if (typeof stream.id == 'undefined' || typeof stream.time == 'undefined' || typeof stream.type == 'undefined' || !stream.file) {
//console('Session stream corrupted at index: ' + i);
session.streams.splice(_i, 1);
_i--;
continue;
}
stream.date = session.date + stream.time;
}
}
var firstSignalStageTime = 0;
var currentStage = 0;
var currentStageTime = 0;
var currentStageDate = 0;
var stageDurations = new Array((0, _keys2.default)(_AuroraConstants.SleepStages).length).fill(0);
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = (0, _getIterator3.default)(session.events), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var _event = _step.value;
switch (_event.id) {
case _AuroraConstants.EventIds.SLEEP_TRACKER_MONITOR:
var stage = _event.flags;
if (!firstSignalStageTime && stage > _AuroraConstants.SleepStages.UNKNOWN) {
firstSignalStageTime = _event.time;
}
if (currentStageTime) {
stageDurations[currentStage] += _event.time - currentStageTime;
}
//is this a non-awake stage?
if (stage > _AuroraConstants.SleepStages.AWAKE) {
//is this the first non-awake sleep stage?
if (!session.asleepAt) {
session.asleepAt = _event.date;
session.sleepOnset = _event.time - firstSignalStageTime;
}
}
//is this an awake stage and have we found the first sleep event?
else if (stage == _AuroraConstants.SleepStages.AWAKE && session.asleepAt) {
session.awakeAt = _event.date;
}
//update current stage/time
currentStage = stage;
currentStageTime = _event.time;
currentStageDate = _event.date;
break;
case _AuroraConstants.EventIds.AUTO_SHUTDOWN:
session.incomplete = true;
break;
case _AuroraConstants.EventIds.AWAKENING:
session.awakenings++;
break;
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
session.sleepDuration.total = stageDurations.reduce(function (p, c) {
return p + c;
});
session.sleepDuration.unknown = stageDurations[_AuroraConstants.SleepStages.UNKNOWN];
session.sleepDuration.awake = stageDurations[_AuroraConstants.SleepStages.AWAKE];
session.sleepDuration.light = stageDurations[_AuroraConstants.SleepStages.LIGHT];
session.sleepDuration.deep = stageDurations[_AuroraConstants.SleepStages.DEEP];
session.sleepDuration.rem = stageDurations[_AuroraConstants.SleepStages.REM];
if (session.sleepDuration.total) {
session.sleepScore = Math.round(1 / (1 + Math.exp(-3.7 * ((session.sleepDuration.rem + session.sleepDuration.deep) / session.sleepDuration.total - 0.25))) * 100);
}
//if we have a complete session with a valid sleep start time
//figure out when the awake time occurred
if (session.asleepAt && !session.incomplete) {
//is the last stage was awake (as it should be in the general case)
//we can use the last stage time as the awake time
if (currentStage == _AuroraConstants.SleepStages.AWAKE) {
session.awakeAt = currentStageDate;
}
//for any other known stages, (/or if the last known stage was short enough)
//we'll just use the session end time
else if (currentStage != _AuroraConstants.SleepStages.UNKNOWN || session.duration - currentStageTime < 1000 * 60 * 15) {
session.awakeAt = session.date + session.duration;
}
}
return _promise2.default.resolve(session);
};
exports.default = AuroraSessionParser;
;