Metal Detector / js /
app.model.js
/*
* Copyright (c) 2015 Samsung Electronics Co., Ltd. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*global window, tizen, console*/
/**
* Application model module.
* It is responsible for initializing and managing magnetic sensor.
* It also checks if magnetic sensor is supported.
*
* @module app.model
* @requires {@link app.common}
* @namespace app.model
* @memberof app
*/
// make sure that "app" namespace is created
window.app = window.app || {};
(function defineAppModel(app) {
'use strict';
/**
* Sensor type constant string.
*
* @memberof app.model
* @private
* @const {string}
*/
var SENSOR_TYPE = 'MAGNETIC',
/**
* Magnetometer capability key.
*
* @memberof app.model
* @private
* @const {string}
*/
MAGNETOMETER_CAPABILITY =
'http://tizen.org/feature/sensor.magnetometer',
/**
* Maximal signal strength.
*
* @memberof app.model
* @private
* @const {number}
*/
MAX_SIGNAL_STRENGTH = 5000,
/**
* Error types constants.
*
* @memberof app.model
* @public
* @const {object<string, string>}
* @namespace app.model.ERROR
*/
ERROR = Object.freeze({
/**
* Error raised when magnetic sensor is not supported by
* the device.
*
* @memberof app.model.ERROR
* @const {string}
*/
NOT_SUPPORTED: 'not_supported',
/**
* Error raised when sensor start procedure fails.
*
* @memberof app.model.ERROR
* @const {string}
*/
START_FAILURE: 'start_failure',
/**
* Raised when unknown error occurs.
*
* @memberof app.model.ERROR
* @const {string}
*/
UNKNOWN: 'unknown'
}),
/**
* Magnetic sensor object.
*
* @memberof app.model
* @private
* @type {Sensor}
*/
sensor = null,
/**
* Flag sensor started.
*
* @memberof app.model
* @private
* @type {boolean}
*/
isSensorStarted = false,
/**
* Sensor service.
*
* @memberof app.model
* @private
* @type {SensorService}
*/
sensorService = null,
/**
* Dispatches an event.
*
* @memberof app.model
* @private
* @type {function}
*/
dispatch = app.common.dispatchEvent;
// create namespace for the module
app.model = app.model || {};
/**
* Converts the number value expressed in radians to degrees.
*
* @memberof app.model
* @private
* @param {number} value
* @returns {number}
*/
function toDegrees(value) {
return value * 180 / Math.PI;
}
/**
* Returns rotation value in degrees for view elements based on
* electromagnetic strength of x and y axis vectors.
*
* Technically: calculates resultant vector deflection degree created by
* adding x and y vectors.
*
* @memberof app.model
* @private
* @param {number} x
* @param {number} y
* @returns {number}
*/
function calculateRotation(x, y) {
return -toDegrees(Math.atan2(x, -y));
}
/**
* Returns resultant vector signal strength created from signal strength
* vectors for each axis.
*
* @memberof app.model
* @private
* @param {number} x
* @param {number} y
* @param {number} z
* @returns {number}
*/
function calculateSignalStrength(x, y, z) {
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));
}
/**
* Returns signal strength relative to maximal signal strength in
* interval [0, maxNumber]. Uses logarithmic scale.
*
* @memberof app.model
* @public
* @param {number} signalStrength
* @param {number} maxNumber
* @returns {number}
*/
function calculateRelativeSignalStrength(signalStrength, maxNumber) {
return Math.ceil(signalStrength > MAX_SIGNAL_STRENGTH ? maxNumber :
Math.log(signalStrength) / Math.log(MAX_SIGNAL_STRENGTH) *
maxNumber);
}
/**
* Get sensor data success callback.
*
* @memberof app.model
* @private
* @fires "model.magnetic.update"
* @param {SensorMagneticData} sensorData
*/
function onGetSuccess(sensorData) {
var x = sensorData.x,
y = sensorData.y,
z = sensorData.z,
data = {
value: calculateSignalStrength(x, y, z),
rotation: calculateRotation(x, y),
rotationVisible: (x <= -1 || x >= 1) || (y <= -1 || y >= 1) ?
true : false
};
dispatch('model.magnetic.update', data);
}
/**
* Start sensor success callback.
* Sets isSensorStarted flag.
*
* @memberof app.model
* @private
* @fires "model.magnetic.ready"
*/
function onSensorStartSuccess() {
isSensorStarted = true;
dispatch('model.magnetic.ready');
try {
sensor.setChangeListener(onGetSuccess);
} catch (e) {
console.error('Execption occured during setting thee listener', e);
}
}
/**
* Start sensor error callback.
*
* @memberof app.model
* @private
* @fires "model.magnetic.error"
*/
function onSensorStartError() {
isSensorStarted = false;
dispatch('model.magnetic.error', ERROR.START_FAILURE);
}
/**
* Starts sensor.
* Sets change listener for data.
* If isSensorStarted is true returns null.
*
* @memberof app.model
* @public
*/
function startSensor() {
if (isSensorStarted) {
return;
}
try {
sensor.start(onSensorStartSuccess, onSensorStartError);
} catch (e) {
console.error('Exception occured during starting the sensor', e);
onSensorStartError();
}
}
/**
* Stops refresh sensor data.
* Unsets change listener for data.
* Sets isSensorStarted to false.
* If isSensorStarted is false returns null.
*
* @memberof app.model
* @public
*/
function stopSensor() {
isSensorStarted = false;
try {
sensor.unsetChangeListener();
sensor.stop();
} catch (e) {
console.error('Exception occurred during stopping the sensor', e);
}
}
/**
* Exits application. Stops sensor.
*
* @memberof app.model
* @public
*/
function exitApplication() {
if (sensor) {
stopSensor();
}
try {
tizen.application.getCurrentApplication().exit();
} catch (e) {
console.error('Error:', e.message);
}
}
/**
* Initializes module.
*
* @memberof app.model
* @public
*/
function init() {
var errorType = '';
// check sensor capability
try {
if (!tizen.systeminfo.getCapability(MAGNETOMETER_CAPABILITY)) {
dispatch('model.magnetic.error', ERROR.NOT_SUPPORTED);
}
} catch (e) {
dispatch('model.magnetic.error', ERROR.UNKNOWN);
}
// check if sensor is available
sensorService = tizen.sensorservice || null;
try {
sensor = sensorService.getDefaultSensor(SENSOR_TYPE);
} catch (error) {
if (error.type === 'NotSupportedError') {
errorType = ERROR.NOT_SUPPORTED;
} else {
errorType = ERROR.UNKNOWN;
}
dispatch('model.magnetic.error', errorType);
return;
}
startSensor();
}
app.model.ERROR = ERROR;
app.model.startSensor = startSensor;
app.model.stopSensor = stopSensor;
app.model.calculateRelativeSignalStrength = calculateRelativeSignalStrength;
app.model.exitApplication = exitApplication;
app.model.init = init;
})(window.app);