// const deviceClass = require("../drivercomponent/deviceClass")(this.app.models);
let evaluator = require("math-expression-evaluator");
let logger;
// code for connecting to pubsub
let vfosMessagingPubsub = require("../pubsub/index.js");
// this parameters could be read from some external json
let broker = "amqp://fitman.uninova.pt";
let userName = "producer1";
let platformDomain = "pt.vfos";
let routingKeys = ["drivers"];
let communications = new vfosMessagingPubsub(broker, userName, platformDomain, routingKeys);
let pubsub = 0;
module.exports = function (sensor) {
/**
* register a sensor of a given device
* @param {string} deviceId ID of device
* @param {sensorConfiguration} sensorData data of the sensor
* @callback {Function} callback Callback function
* @param {Error|string} err Error object
* @param {any} result Result object
*/
sensor.addSensorToDevice = function (deviceId, sensorData, callback) {
// objects to create or find instances on the database
const sensorDataObject = this.app.models.sensorData;
const sensorConfiguration = this.app.models.sensorConfiguration;
// I have to register the sensor and the sensorConfiguration
const deviceConf = this.app.models.deviceConfiguration;
deviceConf.find({where: {_did: deviceId}, limit: 1}).then(
function (deviceConfig) {
sensorConfiguration.create(sensorData)
.then(function (result) {
// Checking if there are triggers so that a subscription can be created
if (sensorConf.triggers.length > 0) {
// 2. It retrieves a specific driver to process the reading on the appropiate protocol according to the sensor
// it send a logger function to store the logs that will be sent to the platform
let specificDriver = require("../driverImplementation/" + sensorConfig.driver.protocol)(logger);
// 3. It uses the driver to make the propietary call to the physical device and receive it in agnostic format
specificDriver.subscribe(deviceConfig, sensorConfig, pushToPlatform);
// 4. create to topic associated to the sensor to push the data
if (pubsub){
let prefixMessagingPrivateDestination2 = "pt.vfos";
let componentMessagingPrivateDestination2 = sensorData._did + "." + sensorData._sid;
}
}
callback(null, result.id);
})
.catch(function (err) {
console.log(err);
});
}).catch(function (err) {
console.log(err);
});
function pushToPlatform(data){
// 6. It will push the data to the vf-OS platform
if (pubsub){
communications.sendPrivateMessage(prefixMessagingPrivateDestination2, componentMessagingPrivateDestination2, data_package);
}
}
}
/**
* Store proprietary data from Device or Gateway
* @param {string} deviceId ID of device
* @param {string} sensorId ID of sensor
* @param {dataMeasure} dataMeasure data from the sensor
* @callback {Function} callback Callback function
* @param {Error|string} err Error object
* @param {any} result Result object
*/
sensor.storeSensorData = function (deviceId, sensorId, dataMeasure, callback) {
// Replace the code below with your implementation.
// Please make sure the callback is invoked.
process.nextTick(function () {
var err = new Error('Not implemented');
callback(err);
});
/*
var err0 = new Error('Invalid ID supplied');
err0.statusCode = 400;
return cb(err0);
*/
/*
var err1 = new Error('device not found');
err1.statusCode = 404;
return cb(err1);
*/
}
/**
* Get data from device / sensor
* @param {string} deviceId ID of device
* @param {string} sensorId ID of sensor
* @callback {Function} callback Callback function
* @param {Error|string} err Error object
* @param {dataMeasure} result Result object
*/
sensor.getDataSensor = function (deviceId, sensorId, callback) {
// 1. It retrieves sensor configuration info
const sensorConfiguration = this.app.models.sensorConfiguration;
const deviceConf = this.app.models.deviceConfiguration;
deviceConf.find({where: {_did: deviceId}, limit: 1}).then(
function (deviceConfig) {
sensorConfiguration.find({where: {_sid: sensorId}, limit: 1})
.then(function (sensorConfig) {
// 2. It retrieves a specific driver to process the reading on the appropiate protocol according to the sensor
// it send a logger function to store the logs that will be sent to the platform
let specificDriver = require("../driverImplementation/" + sensorConfig[0].driver.protocol)(logger);
// 3. It uses the driver to make the propietary call to the physical device and receive it in agnostic format
specificDriver.readSensorData(deviceConfig[0], sensorConfig[0]).then(compute_and_store).catch(function(e){callback(null, e);});
function compute_and_store(data) {
// 4. It substitutes the value of the sensor within a computing expression and processes it
data = evaluator.lex(sensorConfig[0].computingExpression.replace("%v", data)).toPostfix().postfixEval();
let data_package = {
data: data,
unit: sensorConfig[0].properties.unit,
timestamp: new Date()
}
// 5. If historicalData is activated, it stores the measure in a local database
if (sensorConfig[0].historicData) {
storage.storeSensorMeasure(data_package);
}
// 6. It will push the data to the vf-OS platform
if (pubsub){
communications.sendPrivateMessage(prefixMessagingPrivateDestination2, componentMessagingPrivateDestination2, data_package);
}
// 7. It finishes the request method when called using the REST API
callback(null, data_package); //protocol agnostic
}
});
}
).catch(function (err) {
console.log(err);
});
}
/**
* Send Command to Device / Sensor
* @param {string} deviceId ID of device
* @param {string} sensorId ID of sensor
* @param {commandOrder} command command sent to the sensor
* @callback {Function} callback Callback function
* @param {Error|string} err Error object
* @param {any} result Result object
*/
sensor.sendCommand = function (deviceId, sensorId, command, callback) {
// 1. It retrieves sensor configuration info
const sensorConfiguration = this.app.models.sensorConfiguration;
const deviceConf = this.app.models.deviceConfiguration;
deviceConf.find({where: {_did: deviceId}, limit: 1}).then(
function (deviceConfig) {
sensorConfiguration.find({where: {_sid: sensorId}, limit: 1})
.then(function (sensorConfig) {
// 2. It retrieves a specific driver to process the reading on the appropiate protocol according to the sensor
// it send a logger function to store the logs that will be sent to the platform
let specificDriver = require("../driverImplementation/" + sensorConfig.driver.protocol)(logger);
// 3. It uses the driver to make the propietary call send data to the sensor in agnostic
specificDriver.sendCommand(sensorConfig, command).then((data_package) => callback(null, data_package));
})
.catch(function (err) {
console.log(err);
});
});
/*
var err0 = new Error('Invalid ID supplied');
err0.statusCode = 400;
return cb(err0);
*/
/*
var err1 = new Error('device not found');
err1.statusCode = 404;
return cb(err1);
*/
}
/**
* Get historic data from device / sensor
* @param {string} deviceId ID of device
* @param {string} sensorId ID of sensor
* @param {string} offset number of minutes
* @callback {Function} callback Callback function
* @param {Error|string} err Error object
* @param {dataMeasure} result Result object
*/
sensor.getHistoricDataSensor = function (deviceId, sensorId, offset, callback) {
// Replace the code below with your implementation.
// Please make sure the callback is invoked.
process.nextTick(function () {
var err = new Error('Not implemented');
callback(err);
});
/*
var err0 = new Error('Invalid ID supplied');
err0.statusCode = 400;
return cb(err0);
*/
/*
var err1 = new Error('device not found');
err1.statusCode = 404;
return cb(err1);
*/
}
sensor.remoteMethod('addSensorToDevice', {
isStatic: true,
consumes: ['appplication/json'],
produces: ['application/json'],
accepts: [{
arg: 'deviceId',
type: 'string',
description: 'ID of device',
required: true,
http: {
source: 'path'
}
},
{
arg: 'sensorData',
type: 'sensorConfiguration',
description: 'data of the sensor',
required: true,
http: {
source: 'body'
}
}
],
returns: [],
http: {
verb: 'post',
path: '/devices/:deviceId/sensors'
},
description: 'register a sensor of a given device'
});
sensor.remoteMethod('storeSensorData', {
isStatic: true,
consumes: ['appplication/json'],
accepts: [{
arg: 'deviceId',
type: 'string',
description: 'ID of device',
required: true,
http: {
source: 'path'
}
},
{
arg: 'sensorId',
type: 'string',
description: 'ID of sensor',
required: true,
http: {
source: 'path'
}
},
{
arg: 'dataMeasure',
type: 'dataMeasure',
description: 'data from the sensor',
required: true,
http: {
source: 'body'
}
}
],
returns: [],
http: {
verb: 'post',
path: '/devices/:deviceId/sensors/:sensorId/Data'
},
description: 'Store proprietary data from Device or Gateway'
});
sensor.remoteMethod('getDataSensor', {
isStatic: true,
produces: ['application/json'],
accepts: [{
arg: 'deviceId',
type: 'string',
description: 'ID of device',
required: true,
http: {
source: 'path'
}
},
{
arg: 'sensorId',
type: 'string',
description: 'ID of sensor',
required: true,
http: {
source: 'path'
}
}
],
returns: [{
description: 'successful operation',
type: 'dataMeasure',
arg: 'data',
root: true
}],
http: {
verb: 'get',
path: '/devices/:deviceId/sensors/:sensorId/Data'
},
description: 'Get data from device / sensor'
});
sensor.remoteMethod('sendCommand', {
isStatic: true,
consumes: ['appplication/json'],
accepts: [{
arg: 'deviceId',
type: 'string',
description: 'ID of device',
required: true,
http: {
source: 'path'
}
},
{
arg: 'sensorId',
type: 'string',
description: 'ID of sensor',
required: true,
http: {
source: 'path'
}
},
{
arg: 'command',
type: 'commandOrder',
description: 'command sent to the sensor',
required: true,
http: {
source: 'body'
}
}
],
returns: [],
http: {
verb: 'post',
path: '/devices/:deviceId/sensors/:sensorId/Command'
},
description: 'Send Command to Device / Sensor'
});
sensor.remoteMethod('getHistoricDataSensor', {
isStatic: true,
produces: ['application/json'],
accepts: [{
arg: 'deviceId',
type: 'string',
description: 'ID of device',
required: true,
http: {
source: 'path'
}
},
{
arg: 'sensorId',
type: 'string',
description: 'ID of sensor',
required: true,
http: {
source: 'path'
}
},
{
arg: 'offset',
type: 'string',
description: 'number of minutes',
required: true,
http: {
source: 'query'
}
}
],
returns: [{
description: 'successful operation',
type: ['dataMeasure'],
arg: 'data',
root: true
}],
http: {
verb: 'get',
path: '/devices/:deviceId/sensors/:sensorId/Data/HistoricData'
},
description: 'Get historic data from device / sensor'
});
}