var EvenEmitter = require('events').EventEmitter;
var util = require('util');
var SensorManager = require('./Sensors.js').SensorManager;
/**
* Generic sensor class
* @constructor
*/
var Sensor = function (initOption) {
if (this.constructor === Sensor) {
throw new Error("Can't instantiate abstract class!");
}
/**
* @description Holds basic sensor information
* @private
* @memberof Sensor
* @member {Object} info
* @property {String} type - Sensor type
* @property {String} vendor - Vendor name
* @property {String} version - Sensor version
* @property {Number} freq - Sensor frequency (Hz)
* @property {Number} threshold - Threshold value
* @property {String} state - Sensor state
*/
this.info = {
type: 'N/A',
vendor: 'N/A',
version: 'N/A',
freq: -1, //Hz
threshold: -1, // Threshold is disable as default
state: 'idle'
};
/**
* @description Sensor data buffer
* @private
* @memberof Sensor
* @var {Array} buffer - Sensor data buffer
*/
this.buffer = new Array();
/**
* @var {Number} bufferSize - The size of buffer data
* @private
* @memberof Sensor
*/
this.bufferSize = 512; // default buffer size
/**
* @var {Number} intervalRead - An id return by setInterval() function
* @private
* @memberof Sensor
*/
this.intervalRead = 0;
}
/**
* @extends EventEmitter
*/
util.inherits(Sensor, EvenEmitter);
/**
* Start the sensor's operation
* @param {Object} self - Sensor object
*/
Sensor.prototype.start = function (self) {
this.info.state = 'active';
if (this.info.freq !== -1) {
this.intervalRead = setInterval(function () {
self.readData();
}, 1000 / this.info.freq);
}
};
/**
* Stop the sensor's operation
*/
Sensor.prototype.stop = function () {
this.info.state = 'idle';
clearInterval(this.intervalRead);
};
/**
* Reset data buffer
*/
Sensor.prototype.resetBuffer = function () {
while (this.buffer.length > 0) {
this.buffer.pop();
}
};
/*------------------ GETTER/SETTER FUNCTIONS -------------------------*/
/**
* Set sensor frequency
* @param {Number} freq - Frequency value
*/
Sensor.prototype.setFreq = function (freq) {
//TODO: Check if freq is a number
this.info.freq = freq;
if (this.info.hasOwnProperty('minFreq')) {
// if maxFreq is defined
if (freq < this.info.minFreq) {
console.log(this.info.type + "-Warning: set freq=minFreq(" + this.info.minFreq + ")");
this.info.freq = this.info.minFreq;
}
}
if (this.info.hasOwnProperty('maxFreq')) {
if (freq > this.info.maxFreq) {
console.log(this.info.type + "-Warning: set freq=maxFreq(" + this.info.maxFreq + ")");
this.info.freq = this.info.maxFreq;
}
}
//restart
this.stop();
this.start(this);
};
/**
* Retrieve sensor frequency
* @return {Number} Frequency of the sensor
*/
Sensor.prototype.getFreq = function () {
return this.info.freq;
}
/**
* Retrieve sensor type
* @return {String} The sensor type
*/
Sensor.prototype.getType = function () {
return this.info.type;
}
/**
* Set sensor threshold
* @param {int} freq - Threshold value
*/
Sensor.prototype.setThreshold = function (threshold) {
//TODO: check if threshold is a number
if (threshold >= 0) {
this.info.threshold = threshold;
} else {
console.log("Cannot set threshold value which is less than 0");
}
};
/**
* Disable the functionality of using threshold
*/
Sensor.prototype.disableThreshold = function () {
// reset threshold value to -1
this.info.threshold = -1;
}
/**
* Retrieve sensor threshold
* @return {Number} - Threshold value
*/
Sensor.prototype.getThreshold = function () {
return this.info.threshold;
};
/**
* Set sensor state
* @param {String} state - State value
*/
Sensor.prototype.setState = function (state) {
if (state === 'idle' || state === 'active' || state === 'errored') {
this.info.state = state;
}
}
/**
* Retrieve sensor state
* @return {Number} - Sensor state
*/
Sensor.prototype.getState = function () {
return this.info.state;
}
/**
* Set buffer size
* @param {Number} size - Buffer size
*/
Sensor.prototype.setBufferSize = function (size) {
//TODO: Check if size is a number
if (size > 0) {
this.bufferSize = size;
} else { // Ignore the setting if size <= 0, print the notification
console.log("Cannot set buffer's size less than or equal to 0");
}
}
/**
* Retrieve buffer size
* @return {Number} Buffer size
*/
Sensor.prototype.getBufferSize = function () {
return this.bufferSize;
}
/**
* Read data from the sensor
* @abstract
*/
Sensor.prototype.readData = function () {};
/**
* Read data from the data buffer
* @param {Number} numOfData - Number of data
* @return {Array} - Array of returned data
*/
Sensor.prototype.readDataBuffer = function (numOfData) {
//TODO: it should return recent data rather than data from the O position
return this.buffer.slice(0, numOfData - 1);
};
/**
* Print sensor's basic information (type + vendor + version)
*/
Sensor.prototype.toString = function () {
console.log(this.info.type + ' || '
+ 'Vendor: ' + this.info.vendor + ' || '
+ 'Version: ' + this.info.version);
};
/**
* Check sensor's validity. If this sensor is valid, register to use it
* @param {Object} initOption - sensor's initialized information
* @return {String} Sensor ID
* @throw Error when:
* + type of sensor is undefined, or
* + sensor is using, or
* + sensor is unsupported
* @fires TemperatureSensor#onerror
*/
Sensor.prototype.isValid = function (initOption) {
try {
var sensorId;
var validCode;
// check if it is possible to instantiate this sensor
if (initOption.type) {
if (initOption.id) {
sensorId = initOption.id;
validCode = SensorManager.isValid(initOption.type, initOption.id);
} else {
ids = SensorManager.getIds(initOption.type);
if (ids === null) {
validCode = SensorManager.isValid(initOption.type);
} else {
// check if there is any available id for this type of sensor
for (count = 0; count < ids.length; count++) {
if (!SensorManager.isUsing("temperature_ds18b20", ids[count])) {
sensorId = ids[count];
console.log("ID of this " + initOption.type + " sensor is missing. Assign it to id = " + sensorId);
this.info.id = sensorId;
break;
}
}
if (sensorId === undefined) {
throw new Error("All " + type + " sensor(s) are using. Initialization is fail");
}
validCode = SensorManager.isValid(initOption.type, sensorId);
}
}
} else {
throwError(9, initOption.type);
}
if (validCode === 1) {
if (sensorId) {
var assignCode = SensorManager.assignSensor(initOption.type, sensorId);
} else {
var assignCode = SensorManager.assignSensor(initOption.type);
}
if (assignCode === 1) {
for (var property in initOption) {
if (initOption.hasOwnProperty(property)) {
this.info[property] = initOption[property];
}
}
this.setState('active');
} else {
throwError(assignCode, initOption.type, sensorId);
}
} else {
throwError(validCode, initOption.type, sensorId);
}
return sensorId;
} catch (err) {
console.log(err);
console.log(err.stack);
this.setState('errored');
this.emit('onerror', err);
}
}
var throwError = function (errorCode, type, id) {
switch (errorCode) {
case 2:
throw new Error("The " + type + " sensor is using");
case 3:
throw new Error("The " + type + " sensor is unused");
case 4:
throw new Error("The " + type + "sensor with id = " + id + " is using");
case 5:
throw new Error("The " + type + "sensor with id = " + id + " is unused");
case 6:
throw new Error("There are multiple " + type + " sensor. An id is needed");
case 7:
throw new Error("The " + type + " sensor is unsupported");
case 8:
throw new Error("The " + type + " sensor with id = " + id + " is unsupported");
case 9:
throw new Error("The " + type + " sensor is undefined");
default:
throw new Error("Error code: " + errorCode + " is undefined");
}
}
/**
* @exports Sensor
*/
module.exports.Sensor = Sensor;