/**
* Temperature Sensor Driver.
* @module temp
* @author Dave Leitch
* @requires brewdefs
* @requires ds18x20
* @requires brewlog
* @requires events
* @desc This driver usedis to monitor all temperature sensors.
* Periodically all sensors are checked for any changes.
* If a change is detected, the new temperature is emitted.
*/
let ds18x20;
const brewlog = require("../../../common/brewlog.js");
const broker = require("../../../common/broker.js");
let PROBES = require('./probes.js');
let sampleInterval = null;
let started = false;
function setSampleInterval(secs){
brewlog.info("setSampleInterval", `${secs} secs`);
if (sampleInterval !== null){
clearInterval(sampleInterval);
sampleInterval = null;
}
module.exports.getStatus(true);//.then(console.log);
sampleInterval = setInterval(() => module.exports.getStatus(true)/*.then(console.log)*/, secs * 1000);
}
module.exports = {
/* Upon initialisation, check that all temperature sensors are found.
* If not then subsequent temperature measurements will report a fail
*/
start(brewOptions) {
brewlog.info("temp.js","start");
return new Promise((resolve, reject) => {
if (started === true){
resolve(brewOptions);
return;
}
if (brewOptions.sim.simulate){
ds18x20 = require('../../../sim/ds18x20.js');
}else{
// @ts-ignore
ds18x20 = require('ds18x20');
}
const done = resolve;
if (sampleInterval === null){
ds18x20.isDriverLoaded((err, isLoaded) => {
if (err){
brewlog.critical("Temperature driver is not loaded.", err);
reject(err);
}
else {
ds18x20.list((err, listOfDeviceIds) => {
if(err){
brewlog.critical("Failed to start temp:",err);
reject(err);
}
else{
ds18x20.getAll((err, tempObj) => {
if(err){
brewlog.error("Failed to get all temperatures", err);
reject(err);
}else{
PROBES.forEach(probe => {
probe.publishTemp = broker.create(probe.name);
if (brewOptions.sim.simulate){
ds18x20.set(probe.name, brewOptions.sim.ambientTemp);
}
});
if (brewOptions.sim.simulate){
setSampleInterval(60 / brewOptions.sim.speedupFactor);
brewOptions.ambientTemp = brewOptions.sim.ambientTemp;
}else{
setSampleInterval(10);
// const ambientId = PROBES.find(probe => probe.name === 'TempGlycol').id;
// brewOptions.ambientTemp = tempObj[ambientId];
}
started = true;
done(brewOptions);
}
});
}
});//list
}
});
}//timer null
});
},
/**
* Stop the temperature service.
*/
stop() {
return new Promise((resolve, reject) => {
if (started === true){
if (sampleInterval !== null){
clearInterval(sampleInterval);
}
sampleInterval = null;
started = false;
PROBES.forEach(({name}) => {
broker.destroy(name);
});
}
brewlog.info("temp.js", "stopped");
resolve();
});
},
setSampleInterval,
/**
* Emit the current temperature.
* @desc Only the probes whose temperature has changed will fire an event.
* @param {boolean} force - Force a status reading regardless of value.
* @fires temp
*/
getStatus(force = false) {
return new Promise((resolve, reject) => {
//brewlog.info("temp.getStatus", `${force}`)
ds18x20.getAll((err, tempObj) => {
let result = [];
if(err){
// brewlog.critical("Failed to find any temp sensors.", err);
resolve(result);
}else{
PROBES.forEach(probe => {
for (const key in tempObj){
if (key == probe.id){
const value = tempObj[key];
const delta = (probe.prevValue === null) ? 0 : probe.prevValue - value;
if (value == 85){
//85 can be indiciative of an error but not always
// brewlog.warning(`${probe.name} has maybe failed (85)`);
}else{
if ((force === true) || (Math.abs(delta) > 0.5))
{
if (probe.publishTemp){
probe.publishTemp(value);
probe.prevValue = value;
}
}
}//if 85
result.push({name:probe.name, value});
}//if probe.id
}//for key
});//PROBES.forEach
resolve(result);
}//else
});//getAll
});//promise
},//getStatus
/**
* @desc Get temp of a single probe.
* @param {string} name - Probe name.
*/
getTemp(name) {
return new Promise((resolve, reject) => {
try {
const probe = PROBES.find(p => p.name === name);
ds18x20.get(probe.id, (err, temp) => {
if (err){
reject(err);
}else{
resolve(temp);
}
});
} catch (err) {
console.log(name);
reject(err);
}
});
}
}