UNPKG

com.wefitter.plugins.healthkit

Version:

Interact with the iOS HealthKit SDK and connects to the Wefitter server

477 lines (420 loc) 16.2 kB
function WeFitterHealthKit() { } var matches = function(object, typeOrClass) { return (typeof typeOrClass === 'string') ? typeof object === typeOrClass : object instanceof typeOrClass; }; var rounds = function(object, prop) { var val = object[prop]; if (!matches(val, Date)) return; object[prop] = Math.round(val.getTime() / 1000); }; var hasValidDates = function(object) { if (!matches(object.startDate, Date)) { throw new TypeError("startDate must be a JavaScript Date Object"); } if (!matches(object.endDate, Date)) { throw new TypeError("endDate must be a JavaScript Date Object"); } rounds(object, 'startDate'); rounds(object, 'endDate'); return object; }; var getChecker = function(options) { return function paramChecker(type) { var value = options[type]; if (type === 'startDate' || type === 'endDate') { if (!matches(value, Date)) throw new TypeError(type + ' must be a JavaScript Date'); } else if (type === 'samples') { if (!Array.isArray(value)) throw new TypeError(type + ' must be a JavaScript Array'); } else { if (!value) throw new TypeError('Missing required paramter ' + type); } }; }; // Supports: // define('type'); // define('type', fn); // define('type', obj); // define('type', obj, fn) var define = function(isPublic, runCordova, methodName, params, fn) { if (params == null) params = {}; if (typeof params === 'function') { fn = params; params = {}; } if (!fn) fn = Function.prototype; var isEmpty = !!(params && params.noArgs); var checks = params.required || []; if (!Array.isArray(checks)) checks = [checks]; if (isEmpty) { var result = function(callback, onError) { cordova.exec(callback, onError, 'WeFitterHealthKit', methodName, []); }; if (isPublic) { WeFitterHealthKit.prototype[methodName] = result; } return result; } else { var result; if (runCordova) { result = function(options, callback, onError) { if (!options) options = {}; try { checks.forEach(getChecker(options)); fn(options); } catch (error) { onError(error.message); } var args = options ? [options] : []; cordova.exec(callback, onError, 'WeFitterHealthKit', methodName, args); }; } else { result = function(options, callback, onError) { if (!options) options = {}; try { checks.forEach(getChecker(options)); fn(options, callback, onError); } catch (error) { onError(error.message); } }; } if (isPublic) { WeFitterHealthKit.prototype[methodName] = result; } return result; }; }; var HealthKitCordova = {}; var WefitterHealthkitJSLib = { active: true, healthConnectionId: null, cordovaHealthkitPlugin: HealthKitCordova, API_URL: 'https://www.wefitter.com/api/v1/', API_TOKEN: null, AUTH_TOKEN: null, setAPIURL: function(url) { this.API_URL = url; }, setAPIToken: function(apiToken) { this.API_TOKEN = apiToken; }, setAuthToken: function(authToken) { this.AUTH_TOKEN = authToken; }, setActive: function (value) { if (value) { this.active = true; } else { this.active = false; } }, setHealthConnectionId: function (id) { this.healthConnectionId = id; window.localStorage.setItem('healthConnectionId', JSON.stringify(id)); }, getHealthConnectionId: function () { if (!this.healthConnectionId) { this.healthConnectionId = window.localStorage.getItem('healthConnectionId'); } return this.healthConnectionId; }, isActive: function () { return this.active; }, getWorkouts: function () { var _this = this; return new Promise( function(resolve, reject) { _this.cordovaHealthkitPlugin.findWorkouts({}, function (result) { resolve(result); }, function (error) { reject(); } ); }); }, aggregatedSampleType: function (data) { var _this = this; return new Promise( function(resolve, reject) { _this.cordovaHealthkitPlugin.checkAuthStatus({ "type": data.sampleType }, function (result) { _this.cordovaHealthkitPlugin.querySampleTypeAggregated({ 'startDate': data.startDate, 'endDate': data.endDate, 'aggregation': data.aggregation, 'sampleType': data.sampleType, 'unit': data.unit }, function (result) { resolve(result); }, function (error) { reject(); } ); }, function () { //don't have permission reject(); } ); } ); }, parseDataObjectAjax: function (data) { var query = ''; var dataKeys = Object.keys(data); for (var i = 0; i < dataKeys.length; i++) { var dataValue = ((typeof data[dataKeys[i]] === "object") && (data[dataKeys[i]] !== null)) ? JSON.stringify( data[dataKeys[i]]) : data[dataKeys[i]]; query = query + dataKeys[i] + '=' + encodeURIComponent(dataValue); if (i != dataKeys.length - 1) { query = query + '&'; } } return query; }, updateActivityData: function (sampleTypeData, callback, onError) { var params = { id: this.getHealthConnectionId(), workouts: { workouts: sampleTypeData.workouts || [], daily: sampleTypeData.daily } }; var _this = this; var request = new XMLHttpRequest(); request.onreadystatechange = function () { if (request.readyState == 4) { if (request.status == 200) { callback("data sent correctly"); } else { // _this.consoleLog("data send failed"); onError("data send failed"); throw new Exception("data send failed"); } } } request.open("POST", this.API_URL + 'connections/healthkit', true); request.setRequestHeader('X-Wefitter-ApiToken', this.API_TOKEN); request.setRequestHeader('X-Wefitter-Authorization',"Bearer " + this.AUTH_TOKEN); request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); request.send(this.parseDataObjectAjax(params)); }, run: function (options, callback, onError) { var _this = this; if (this.API_TOKEN == null || this.AUTH_TOKEN == null) { onError("auth variables are undefined"); return; } if (!this.getHealthConnectionId()) { // _this.consoleLog('asking to the sever for healthConnectionId'); var request = new XMLHttpRequest(); request.onreadystatechange = function () { if (request.readyState == 4) { if (request.status == 200) { // _this.consoleLog("data sent correctly"); _this.setHealthConnectionId(JSON.parse(request.response).content.id); _this.continueRun(options.backendConfig, callback, onError); } else { // _this.consoleLog("data send failed"); onError("data send failed"); throw new Exception("data send failed"); } } } request.open("GET", this.API_URL + "app/connections/22", true); request.setRequestHeader('X-Wefitter-ApiToken', this.API_TOKEN); request.setRequestHeader('X-Wefitter-Authorization',"Bearer " + this.AUTH_TOKEN); request.send(); } else { this.continueRun(options.backendConfig, callback, onError); } }, continueRun: function(noDefaultConfig, callback, onError) { var _this = this; // this.consoleLog('starting run...'); if (this.isActive()) { // this.consoleLog('profile is active'); if (noDefaultConfig) { this.getHealthkitConfig(function(data) { _this.sendDataToServer(data, callback, onError); }, callback, onError); } else { var sampleTypeList = [ { key: 'workouts', startDate: new Date(new Date().getTime() - 6 * 24 * 60 * 60 * 1000), // seven days ago endDate: new Date(), aggregation: 'day' }, { key: 'steps', sampleType: 'HKQuantityTypeIdentifierStepCount', unit: 'count', startDate: new Date(new Date().getTime() - 6 * 24 * 60 * 60 * 1000), endDate: new Date(), aggregation: 'day' }, { key: 'calories', sampleType: 'HKQuantityTypeIdentifierActiveEnergyBurned', unit: 'kcal', startDate: new Date(new Date().getTime() - 6 * 24 * 60 * 60 * 1000), endDate: new Date(), aggregation: 'day' }, { key: 'distance_walking', sampleType: 'HKQuantityTypeIdentifierDistanceWalkingRunning', unit: 'm', startDate: new Date(new Date().getTime() - 6 * 24 * 60 * 60 * 1000), endDate: new Date(), aggregation: 'day' }, { key: 'distance_biking', sampleType: 'HKQuantityTypeIdentifierDistanceCycling', unit: 'm', startDate: new Date(new Date().getTime() - 6 * 24 * 60 * 60 * 1000), endDate: new Date(), aggregation: 'day' } ]; this.sendDataToServer(sampleTypeList, callback, onError); } } else { callback("profile is not active"); // this.consoleLog("profile is not active") } }, sendDataToServer: function(typeList, callback, onError) { var sampleTypeData = {}; var promises = [this.getWorkouts()]; for (var i = 1; i < typeList.length; i++) { promises.push(this.aggregatedSampleType(typeList[i])) } var _this = this; window.Promise.all(promises) .then(function (values) { // _this.consoleLog('connection done'); var dataToSend = { workouts: values[0], daily: {} }; for (var index = 1; index < values.length; index++) { if (values[index]) { dataToSend.daily[typeList[index].key] = values[index]; } } _this.updateActivityData(dataToSend, callback, onError); }, function (error) { // _this.consoleLog('healthkit auth error'); onError("healthkit permissions error"); }); }, getHealthkitConfig: function(postfunc, callback, onError) { var _this = this; var request = new XMLHttpRequest(); request.onreadystatechange = function () { if (request.readyState == 4) { if (request.status == 200) { // _this.consoleLog("data get correctly"); var response = []; var rawResponse = JSON.parse(request.response).content; for (var i = 0; i < rawResponse.length; i++) { var obj = { key: rawResponse[i].key }; if (rawResponse[i].params) { var startDate = rawResponse[i].params.startDate; startDate = startDate.split(' '); var startDateDate = startDate[0].split(/\-/); var startDateTime = startDate[1]; var startDateObject = new Date(startDateDate[0] + '/' + startDateDate[1] + '/' + startDateDate[2] + ' ' + startDateTime); var endDate = rawResponse[i].params.endDate; endDate = endDate.split(' '); var endDateDate = endDate[0].split(/\-/); var endDateTime = endDate[1]; var endDateObject = new Date(endDateDate[0] + '/' + endDateDate[1] + '/' + endDateDate[2] + ' ' + endDateTime); obj.startDate = startDateObject; obj.endDate = endDateObject; obj.aggregation = rawResponse[i].params.aggregation; obj.sampleType = rawResponse[i].params.sampleType; obj.unit = rawResponse[i].params.unit; } response.push(obj); } postfunc(response); } else { // _this.consoleLog("data send failed"); onError("data send failed"); } } } request.open("GET", this.API_URL + "app/connections/healthkit_config", true); request.setRequestHeader('X-Wefitter-ApiToken', this.API_TOKEN); request.setRequestHeader('X-Wefitter-Authorization',"Bearer " + this.AUTH_TOKEN); request.send(); }, consoleLog: function(logString) { if (typeof logString == "string") { console.log("[wefitter-healthkit-plugin] " + logString); } else { console.log("[wefitter-healthkit-plugin]"); console.log(logString); } } }; define(true, true, 'available', {noArgs: true}); define(true, false, 'run', WefitterHealthkitJSLib.run.bind(WefitterHealthkitJSLib)); define(true, false, 'setAPIURL', WefitterHealthkitJSLib.setAPIURL.bind(WefitterHealthkitJSLib)); define(true, false, 'setAPIToken', WefitterHealthkitJSLib.setAPIToken.bind(WefitterHealthkitJSLib)); define(true, false, 'setAuthToken', WefitterHealthkitJSLib.setAuthToken.bind(WefitterHealthkitJSLib)); HealthKitCordova.checkAuthStatus = define(false, true, 'checkAuthStatus'); HealthKitCordova.requestAuthorization = define(false, true, 'requestAuthorization'); HealthKitCordova.readDateOfBirth = define(false, true, 'readDateOfBirth', {noArgs: true}); HealthKitCordova.readGender = define(false, true, 'readGender', {noArgs: true}); HealthKitCordova.readFitzpatrickSkinType = define(false, true, 'readFitzpatrickSkinType', {noArgs: true}); HealthKitCordova.findWorkouts = define(false, true, 'findWorkouts'); HealthKitCordova.delete = define(false, true, 'delete'); HealthKitCordova.readWeight = define(false, true, 'readWeight'); HealthKitCordova.readHeight = define(false, true, 'readHeight'); HealthKitCordova.readBloodType = define(false, true, 'readBloodType', {noArgs: true}); HealthKitCordova.saveWeight = define(false, true, 'saveWeight', function(options) { if (options.date == null) options.date = new Date(); if (typeof options.date === 'object') rounds(options, 'date'); }); HealthKitCordova.saveHeight = define(false, true, 'saveHeight', function(options) { if (options.date == null) options.date = new Date(); if (typeof options.date === 'object') rounds(options, 'date'); }); HealthKitCordova.saveWorkout = define(false, true, 'saveWorkout', {required: 'startDate'}, function(options) { var hasEnd = matches(options.endDate, Date); var hasDuration = options.duration && options.duration > 0; rounds(options, 'startDate'); if (!hasEnd && !hasDuration) { throw new TypeError("endDate must be JavaScript Date Object, or the duration must be set"); } if (hasEnd) rounds(options, 'endDate'); }); HealthKitCordova.monitorSampleType = define(false, true, 'monitorSampleType', {required: 'sampleType'}); HealthKitCordova.querySampleType = define(false, true, 'querySampleType', {required: 'sampleType'}, hasValidDates); HealthKitCordova.querySampleTypeAggregated = define(false, true, 'querySampleTypeAggregated', {required: 'sampleType'}, hasValidDates); HealthKitCordova.deleteSamples = define(false, true, 'deleteSamples', {required: 'sampleType'}, hasValidDates); HealthKitCordova.queryCorrelationType = define(false, true, 'queryCorrelationType', {required: 'correlationType'}, hasValidDates); HealthKitCordova.saveQuantitySample = define(false, true, 'saveQuantitySample', {required: 'sampleType'}, hasValidDates); HealthKitCordova.saveCorrelation = define(false, true, 'saveCorrelation', {required: ['correlationType', 'samples']}, function(options) { hasValidDates(options); options.objects = options.samples.map(hasValidDates); }); HealthKitCordova.sumQuantityType = define(false, true, 'sumQuantityType', {required: ['sampleType']}, hasValidDates); WeFitterHealthKit.install = function() { if (!window.plugins) window.plugins = {}; window.plugins.wefitterhealthkit = new WeFitterHealthKit(); return window.plugins.wefitterhealthkit; }; cordova.addConstructor(WeFitterHealthKit.install);