simplifying to temp launch
This commit is contained in:
parent
f66f705e58
commit
b7f9bacfa1
8
TODO
Normal file
8
TODO
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
Logic Goal:
|
||||||
|
|
||||||
|
1. Start Script & Web Server
|
||||||
|
2. Await a command from the user.
|
||||||
|
3. Startup enables auger
|
||||||
|
4. If auger is enabled, run the cycle command.
|
||||||
|
5. Once per cycle, read then rewrite the config file for interoperability
|
||||||
|
6. Set feed rate based on config.
|
@ -1 +1 @@
|
|||||||
{"debugMode":true,"status":{"igniter":0,"blower":0,"auger":0,"igniterFinished":true,"shutdown":1,"vacuum":0,"pof":0},"timestamps":{"procStart":1672761393394,"blowerOn":1672761445945,"blowerOff":1672761459451,"igniterOn":1672761445946,"igniterOff":1672761447442},"intervals":{"augerOn":500,"augerOff":1500,"pause":3000,"igniterStart":5000,"blowerStop":5000},"web":{"port":8080,"ip":"0.0.0.0"}}
|
{"debugMode":true,"status":{"igniter":0,"blower":0,"auger":0,"igniterFinished":false,"shutdown":0,"vacuum":0,"pof":0},"timestamps":{"procStart":1673037430589,"blowerOn":0,"blowerOff":0,"igniterOn":0,"igniterOff":0},"intervals":{"augerOn":"700","augerOff":"1300","igniterStart":5000,"blowerStop":5000},"web":{"port":8080,"ip":"0.0.0.0"}}
|
422
functions.js
422
functions.js
@ -3,16 +3,12 @@
|
|||||||
// TODO: Move these to config
|
// TODO: Move these to config
|
||||||
// Physical Pin numbers for GPIO
|
// Physical Pin numbers for GPIO
|
||||||
const augerPin = 26; // Pin for controlling the relay for the pellet auger motor.
|
const augerPin = 26; // Pin for controlling the relay for the pellet auger motor.
|
||||||
const igniterPin = 13; // Pin for controlling the relay for the igniter.
|
|
||||||
const blowerPin = 15; // Pin for controlling the relay for the combustion blower/exhaust.
|
|
||||||
const pofPin = 16; // Pin for sensing the status (open/closed) of the Proof of Fire switch.
|
|
||||||
// const tempPin = 18; // Pin for receiving data from a DS18B20 OneWire temperature sensor.
|
|
||||||
const vacuumPin = 22; // Pin for sensing the status (open/closed) of the vacuum switch.
|
|
||||||
|
|
||||||
// Require the package for pulling version numbers
|
// Require the package for pulling version numbers
|
||||||
const package = require('./package.json');
|
const package = require('./package.json');
|
||||||
// Import the config file
|
// Import the config file
|
||||||
var config = require('./config.json');
|
var config = require('./config.json');
|
||||||
|
config.timestamps.procStart = Date.now();
|
||||||
|
|
||||||
// Get environment variables
|
// Get environment variables
|
||||||
const dotenv = require('dotenv').config();
|
const dotenv = require('dotenv').config();
|
||||||
@ -20,6 +16,27 @@ const dotenv = require('dotenv').config();
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const { time } = require('console');
|
const { time } = require('console');
|
||||||
|
|
||||||
|
const main = (gpio) => {
|
||||||
|
// If the auger is enabled
|
||||||
|
if (config.status.auger == 1) {
|
||||||
|
// Run a cycle of the auger
|
||||||
|
functions.auger.cycle(gpio).then(res => {
|
||||||
|
if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
|
||||||
|
// Recursion ecursion cursion ursion rsion sion ion on n
|
||||||
|
main(gpio);
|
||||||
|
}).catch(err => {
|
||||||
|
if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] E: ${err}`);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// If the auger is disabled
|
||||||
|
functions.commands.pause().then(res => {
|
||||||
|
main(gpio);
|
||||||
|
}).catch(err => {
|
||||||
|
if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] E: ${err}`);
|
||||||
|
main(gpio);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The functions we'll export to be used in other files
|
// The functions we'll export to be used in other files
|
||||||
const functions = {
|
const functions = {
|
||||||
@ -80,7 +97,7 @@ const functions = {
|
|||||||
// Log action if in debug mode
|
// Log action if in debug mode
|
||||||
// if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
|
// if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
|
||||||
// Resolve the promise, letting the main script know the cycle is complete
|
// Resolve the promise, letting the main script know the cycle is complete
|
||||||
resolve("Auger cycled.");
|
resolve(`Auger cycled (${config.intervals.augerOn}/${config.intervals.augerOff})`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -88,71 +105,16 @@ const functions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
blower: {
|
|
||||||
blocksShutdown() {
|
|
||||||
// If the current time is past the blowerOff timestamp, we can turn finish shutting down the stove
|
|
||||||
if ((config.timestamps.blowerOff > 0) && (Date.now() > config.timestamps.blowerOff)) {
|
|
||||||
return false;
|
|
||||||
// Otherwise, return true because we're not ready to shutdown yet
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
files: {
|
|
||||||
// Check for a preset-list of files in the root directory of the app
|
|
||||||
check() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
// Check for pause file existing
|
|
||||||
if (fs.existsSync('./pause')) {
|
|
||||||
// Resolve the promise, letting the main script know what we found
|
|
||||||
resolve("pause");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for reload file existing
|
|
||||||
if (fs.existsSync('./reload')) {
|
|
||||||
// Resolve the promise, letting the main script know what we found
|
|
||||||
resolve("reload");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for quit file existing
|
|
||||||
if (fs.existsSync('./quit')) {
|
|
||||||
// Resolve the promise, letting the main script know what we found
|
|
||||||
resolve("quit");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for ignite file existing
|
|
||||||
if (fs.existsSync('./ignite')) {
|
|
||||||
resolve('ignite');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for start file existing
|
|
||||||
if (fs.existsSync('./start')) {
|
|
||||||
resolve('start');
|
|
||||||
}
|
|
||||||
// Resolve the promise, letting the main script know what we found (nothing)
|
|
||||||
resolve("none");
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
commands: {
|
commands: {
|
||||||
// Prepare the stove for starting
|
// Prepare the stove for starting
|
||||||
startup (gpio) {
|
startup () {
|
||||||
fs.unlink('./start', (err) => {
|
// Basic startup just enables the auger
|
||||||
if (err) throw err;
|
config.status.auger = 1;
|
||||||
});
|
return;
|
||||||
return new Promise((resolve, reject) => {
|
},
|
||||||
if (process.env.ONPI == 'true') {
|
shutdown() {
|
||||||
// Turn the combustion blower on
|
// Basic shutdown only needs to disable the auger
|
||||||
functions.power.blower.on(gpio).then(res => {
|
config.status.auger = 0;
|
||||||
resolve(`I: Combustion blower has been enabled.`);
|
|
||||||
}).catch(rej => {
|
|
||||||
reject(`E: There was a problem starting the combustion blower: ${rej}`);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
resolve(`I: Simulated combustion blower turned on.`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
// Pauses the script for the time defined in env variables
|
// Pauses the script for the time defined in env variables
|
||||||
pause() {
|
pause() {
|
||||||
@ -181,263 +143,23 @@ const functions = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
// Shutdown the script gracefully
|
refreshConfig(newSettings) {
|
||||||
quit() {
|
// When the reload button is pressed, the call to this function will contain new config values
|
||||||
// TODO add quit file detection, not always going to be quitting from files
|
// {
|
||||||
// Delete the quit file
|
// augerOff: 500,
|
||||||
fs.unlink('./quit', (err) => {
|
// augerOn: 1500,
|
||||||
if (err) throw err;
|
// pause: 5000
|
||||||
if (config.debugMode) console.log('Removed quit file.');
|
// }
|
||||||
});
|
if (newSettings != undefined) {
|
||||||
// Print out that the script is quitting
|
config.intervals.augerOff = newSettings.augerOff;
|
||||||
console.log('Quitting...');
|
config.intervals.augerOn = newSettings.augerOn;
|
||||||
// Quit the script
|
config.intervals.pause = newSettings.pause;
|
||||||
process.exit();
|
|
||||||
},
|
|
||||||
ignite(gpio) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
// Check if we got here from a file, then delete it.
|
|
||||||
if (fs.existsSync('./ignite')) fs.unlink('./ignite', (err) => { if (err) throw err; });
|
|
||||||
functions.power.blower.on(gpio).then(res => {
|
|
||||||
if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
|
|
||||||
// Turn on the igniter
|
|
||||||
functions.power.igniter.on(gpio).then(res => {
|
|
||||||
if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
|
|
||||||
// Enable the auger
|
|
||||||
config.status.auger = 1;
|
|
||||||
if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: Auger enabled.`);
|
|
||||||
|
|
||||||
resolve('Ignition sequence started successfully.');
|
|
||||||
}).catch(err => {
|
|
||||||
reject(err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
shutdown(gpio) {
|
|
||||||
// Only run if a shutdown isn't already started
|
|
||||||
if (config.status.shutdown == 0) {
|
|
||||||
// set shutdown flag to 1
|
|
||||||
config.status.shutdown = 1;
|
|
||||||
// Check if this was invoked from a 'quit' file, if so, delete the file
|
|
||||||
if (fs.existsSync('./quit')) fs.unlink('./quit', (err) => { if (err) throw err; });
|
|
||||||
// If the auger is enabled, disable it
|
|
||||||
if (config.status.auger == 1) {
|
|
||||||
config.status.auger = 0;
|
|
||||||
if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: Auger disabled.`);
|
|
||||||
}
|
|
||||||
// If the igniter is on, shut it off.
|
|
||||||
if (config.status.igniter == 1) {
|
|
||||||
functions.power.igniter.off(gpio).then(res => {
|
|
||||||
if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
|
|
||||||
}); // TODO catch an error here
|
|
||||||
}
|
|
||||||
// TODO Change this so it gives a delay after shutting down so smoke doesn't enter the house
|
|
||||||
if (config.status.blower == 1) {
|
|
||||||
// Set the timestamp to turn the blower off at
|
|
||||||
config.timestamps.blowerOff = Date.now() + config.intervals.blowerStop;
|
|
||||||
}
|
|
||||||
return "Shutdown has been initiated.";
|
|
||||||
} else {
|
|
||||||
// blower.blocksShutdown() returns false only if the blower shutdown has
|
|
||||||
// been initiated AND the specified cooldown time has passed
|
|
||||||
if(!(functions.blower.blocksShutdown())) {
|
|
||||||
if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: Blower can be turned off.`);
|
|
||||||
functions.power.blower.off(gpio).then(res => {
|
|
||||||
// Since the blower shutting off is the last step in the shutdown, we can quit.
|
|
||||||
// TODO eventually we don't want to ever quit the program, so it can be restarted remotely
|
|
||||||
// functions.commands.quit();
|
|
||||||
config.status.shutdown = 0;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return "A shutdown has already been initiated and the blower is preventing shutdown.";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
writeConfig() {
|
|
||||||
fs.writeFile('./config.json', JSON.stringify(config), (err) => {
|
fs.writeFile('./config.json', JSON.stringify(config), (err) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tests: {
|
|
||||||
vacuum(gpio) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
if (config.status.blower == 1) {
|
|
||||||
if (process.env.ONPI == 'true') {
|
|
||||||
gpio.read(vacuumPin, (err, status) => {
|
|
||||||
if (err) reject(err);
|
|
||||||
config.status.vacuum = status;
|
|
||||||
resolve(status);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
switch (config.status.vacuum) {
|
|
||||||
case 0:
|
|
||||||
resolve(false);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
resolve(true);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
reject('Unable to determine vacuum status.');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// If the blower isn't on, the vacuum doesn't matter so always return true
|
|
||||||
resolve(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
},
|
|
||||||
pof(gpio) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
if (process.env.ONPI == 'true') {
|
|
||||||
gpio.read(pofPin, (err, status) => {
|
|
||||||
if (err) reject(err);
|
|
||||||
config.status.pof = status;
|
|
||||||
resolve(status);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
switch (config.status.pof) {
|
|
||||||
case 0:
|
|
||||||
resolve(false);
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
resolve(true);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
reject('Unable to determine proof of fire status.');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
igniter(gpio) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
// Create a blank string to store the status message in as we build it
|
|
||||||
var statusMsg = "";
|
|
||||||
// Determine if the igniter is on
|
|
||||||
if (config.status.igniter == 1) {
|
|
||||||
statusMsg += "The igniter is on. ";
|
|
||||||
} else if (config.status.igniter == 0) {
|
|
||||||
statusMsg += "The igniter is off. ";
|
|
||||||
} else {
|
|
||||||
reject("Unable to determine igniter status.");
|
|
||||||
}
|
|
||||||
// Run this if the igniter has been turned on
|
|
||||||
if (config.timestamps.igniterOn > 0) {
|
|
||||||
if (Date.now() < config.timestamps.igniterOff && config.status.igniter == 1) {
|
|
||||||
statusMsg += `Started: ${functions.time(config.timestamps.igniterOn)}. `;
|
|
||||||
statusMsg += `Stopping: ${functions.time(config.timestamps.igniterOff)}. `;
|
|
||||||
}
|
|
||||||
// Shut the igniter off if it's past the waiting period
|
|
||||||
if ((Date.now() > config.timestamps.igniterOff) && (config.status.igniter == 1)) {
|
|
||||||
// if (process.env.ONPI == 'true') {
|
|
||||||
// gpio.write(igniterPin, false, (err) => {
|
|
||||||
// if (err) throw(err);
|
|
||||||
// config.status.igniter = 0;
|
|
||||||
// statusMsg += `${new Date().toISOString()} I: Turned off igniter.`;
|
|
||||||
// functions.tests.pof(gpio).then(res => {
|
|
||||||
// if (res) {
|
|
||||||
// config.status.seenFire = true;
|
|
||||||
// } else {
|
|
||||||
// reject(`E: No Proof of Fire after igniter shut off.`);
|
|
||||||
// }
|
|
||||||
// }).catch(rej => {
|
|
||||||
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// } else {
|
|
||||||
// config.status.igniter = 0;
|
|
||||||
// statusMsg += `${new Date().toISOString()} I: Simulated igniter turned off.`;
|
|
||||||
// }
|
|
||||||
// TODO I think this needs to be moved elsewhere, it doesn't finish resolving before the resolve call on line 354 is called (344+10=354)
|
|
||||||
functions.power.igniter.off(gpio).then(res => {
|
|
||||||
if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
|
|
||||||
});
|
|
||||||
} else if ((Date.now() > config.timestamps.igniterOff) && (config.status.igniter == 0)) {
|
|
||||||
statusMsg += `The igniter was turned off at ${new Date(config.timestamps.igniterOff).toISOString()}.`;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
statusMsg += 'The igniter hasn\'t been started yet.';
|
|
||||||
}
|
|
||||||
resolve(statusMsg);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
blowerOffDelay() {
|
|
||||||
|
|
||||||
},
|
|
||||||
},
|
|
||||||
power: {
|
|
||||||
igniter: {
|
|
||||||
on(gpio) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
config.timestamps.igniterOn = Date.now();
|
|
||||||
config.timestamps.igniterOff = Date.now() + config.intervals.igniterStart;
|
|
||||||
if (process.env.ONPI == 'true') {
|
|
||||||
gpio.write(igniterPin, true, (err) => {
|
|
||||||
if (err) reject(err);
|
|
||||||
config.status.igniter = 1;
|
|
||||||
resolve('Igniter turned on.');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
config.status.igniter = 1;
|
|
||||||
resolve('Igniter turned on.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
off(gpio) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
config.timestamps.igniterOff = Date.now();
|
|
||||||
config.status.igniterFinished = true;
|
|
||||||
if (process.env.ONPI == 'true') {
|
|
||||||
gpio.write(igniterPin, false, (err) => {
|
|
||||||
if (err) reject(err);
|
|
||||||
config.status.igniter = 0;
|
|
||||||
resolve('Igniter turned off.');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
config.status.igniter = 0;
|
|
||||||
resolve('Igniter turned off.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
blower: {
|
|
||||||
on(gpio) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
config.timestamps.blowerOn = Date.now();
|
|
||||||
if (process.env.ONPI == 'true') {
|
|
||||||
gpio.write(blowerPin, true, (err) => {
|
|
||||||
if (err) reject(err);
|
|
||||||
config.status.blower = 1;
|
|
||||||
resolve('Blower turned on.');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
config.status.blower = 1;
|
|
||||||
resolve('Blower turned on.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
off(gpio) {
|
|
||||||
config.timestamps.blowerOff = Date.now();
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
if (process.env.ONPI == 'true') {
|
|
||||||
gpio.write(blowerPin, false, (err) => {
|
|
||||||
if (err) reject(err);
|
|
||||||
config.status.blower = 0;
|
|
||||||
resolve('Blower turned off.');
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
config.status.blower = 0;
|
|
||||||
resolve('Blower turned off.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// Sleeps for any given milliseconds
|
// Sleeps for any given milliseconds
|
||||||
sleep(ms) {
|
sleep(ms) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
@ -481,34 +203,8 @@ const functions = {
|
|||||||
gpio.setup(augerPin, gpio.DIR_OUT, (err) => {
|
gpio.setup(augerPin, gpio.DIR_OUT, (err) => {
|
||||||
if (err) reject(err);
|
if (err) reject(err);
|
||||||
if (config.debugMode) console.log('== Auger pin initialized.');
|
if (config.debugMode) console.log('== Auger pin initialized.');
|
||||||
// Init the igniter pin
|
// Resolve the promise now that all pins have been initialized
|
||||||
gpio.setup(igniterPin, gpio.DIR_OUT, (err) => {
|
resolve('== GPIO Initialized.');
|
||||||
if (err) reject(err);
|
|
||||||
if (config.debugMode) console.log('== Igniter pin initialized.');
|
|
||||||
// Init the blower pin
|
|
||||||
gpio.setup(blowerPin, gpio.DIR_OUT, (err) => {
|
|
||||||
if (err) reject(err);
|
|
||||||
if (config.debugMode) console.log('== Combustion blower pin initialized.');
|
|
||||||
// Init the Proof of Fire pin
|
|
||||||
gpio.setup(pofPin, gpio.DIR_IN, (err) => {
|
|
||||||
if (err) reject(err);
|
|
||||||
if (config.debugMode) console.log('== Proof of Fire pin initialized.');
|
|
||||||
// Init the Vacuum Switch pin
|
|
||||||
gpio.setup(vacuumPin, gpio.DIR_IN, (err) => {
|
|
||||||
if (err) reject(err);
|
|
||||||
if (config.debugMode) console.log('== Vacuum Switch pin initialized.');
|
|
||||||
// Resolve the promise now that all pins have been initialized
|
|
||||||
resolve('== GPIO Initialized.');
|
|
||||||
});
|
|
||||||
// Init the Temp Sensor pin
|
|
||||||
// gpio.setup(tempPin, gpio.DIR_IN, (err) => {
|
|
||||||
// if (err) reject(err);
|
|
||||||
// if (config.debugMode) console.log('== Temperature pin initialized.');
|
|
||||||
|
|
||||||
// });
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// Resolve the promise
|
// Resolve the promise
|
||||||
@ -522,5 +218,35 @@ const functions = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup for use with the Pi's GPIO pins
|
||||||
|
switch (process.env.ONPI) {
|
||||||
|
case 'true':
|
||||||
|
console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] == Running on a Raspberry Pi.`);
|
||||||
|
var gpio = require('rpi-gpio');
|
||||||
|
functions.init(gpio).then((res) => {
|
||||||
|
console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
|
||||||
|
main(gpio);
|
||||||
|
}).catch(rej => {
|
||||||
|
console.error(`[${(Date.now() - config.timestamps.procStart)/1000}] E: Error during initialization: ${rej}`);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'false':
|
||||||
|
console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: Not running on a Raspberry Pi.`);
|
||||||
|
var gpio = 'gpio';
|
||||||
|
functions.init(gpio).then(res => {
|
||||||
|
console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
|
||||||
|
main(gpio);
|
||||||
|
}).catch(rej => {
|
||||||
|
console.error(`[${(Date.now() - config.timestamps.procStart)/1000}] E: Error during initialization: ${rej}`);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.error(`[${Date.now() - config.timestamps.procStart}] E: Problem with ENV file.`);
|
||||||
|
process.exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Export the above object, functions, as a module
|
// Export the above object, functions, as a module
|
||||||
module.exports = { functions };
|
module.exports = { functions };
|
165
main.js
165
main.js
@ -1,165 +0,0 @@
|
|||||||
/* Pellet Stove Control Panel
|
|
||||||
* Written by Skylar Grant
|
|
||||||
* v0.2
|
|
||||||
*
|
|
||||||
* TODO:
|
|
||||||
* Update documentation
|
|
||||||
* Move some of these functions to the functions file so they can be called from the web server
|
|
||||||
* Or move the web server here and remove the first init
|
|
||||||
* Or just remove the first init call and start the init elsewhere after main() is called
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Custom functions module to keep main script clean
|
|
||||||
const fn = require('./functions.js').functions;
|
|
||||||
|
|
||||||
// Config File
|
|
||||||
const config = require('./config.json');
|
|
||||||
config.timestamps.procStart = Date.now();
|
|
||||||
|
|
||||||
// Environment Variables Importing
|
|
||||||
const dotenv = require('dotenv').config();
|
|
||||||
|
|
||||||
// Setup for use with the Pi's GPIO pins
|
|
||||||
if (process.env.ONPI == 'true') {
|
|
||||||
console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] == Running on a Raspberry Pi.`);
|
|
||||||
const gpio = require('rpi-gpio');
|
|
||||||
fn.init(gpio).then((res) => {
|
|
||||||
console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
|
|
||||||
main(fn, gpio);
|
|
||||||
}).catch(rej => {
|
|
||||||
console.error(`[${(Date.now() - config.timestamps.procStart)/1000}] E: ${rej}`);
|
|
||||||
});
|
|
||||||
} else if (process.env.ONPI == 'false') {
|
|
||||||
console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: Not running on a Raspberry Pi.`);
|
|
||||||
const gpio = 'gpio';
|
|
||||||
fn.init(gpio).then(res => {
|
|
||||||
console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
|
|
||||||
main(fn, gpio);
|
|
||||||
}).catch(rej => {
|
|
||||||
console.error(rej);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error(`[${Date.now() - config.timestamps.procStart}] E: Problem with ENV file.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Add logic for other sensors
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Main function, turns the auger on, sleeps for the time given in environment variables, then turns the auger off, sleeps, repeats.
|
|
||||||
async function main(fn, gpio) {
|
|
||||||
// Check for the existence of certain files
|
|
||||||
fn.files.check().then((res,rej) => {
|
|
||||||
// Log the result of the check if in debug mode
|
|
||||||
// if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: File Check: ${res}`);
|
|
||||||
// Choose what to do depending on the result of the check
|
|
||||||
switch (res) {
|
|
||||||
case "pause":
|
|
||||||
// Pause the script
|
|
||||||
fn.commands.pause().then(() => {
|
|
||||||
// Rerun this function once the pause has finished
|
|
||||||
main(fn, gpio);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "reload":
|
|
||||||
// Reload the environment variables
|
|
||||||
fn.commands.reload().then(() => {
|
|
||||||
// Rerun this function once the reload has finished
|
|
||||||
main(fn, gpio);
|
|
||||||
}).catch(rej => {
|
|
||||||
console.error(`[${(Date.now() - config.timestamps.procStart)/1000}] E: ${rej}`);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "quit":
|
|
||||||
// Quit the script
|
|
||||||
console.log(fn.commands.shutdown(gpio));
|
|
||||||
statusCheck(fn, gpio);
|
|
||||||
break;
|
|
||||||
case "ignite":
|
|
||||||
// Start the ignite sequence
|
|
||||||
fn.commands.ignite(gpio).then(res => {
|
|
||||||
if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
|
|
||||||
|
|
||||||
statusCheck(fn, gpio);
|
|
||||||
}).catch(rej => {
|
|
||||||
console.error(`[${(Date.now() - config.timestamps.procStart)/1000}] E: ${rej}`);
|
|
||||||
fn.commands.shutdown(gpio);
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "start":
|
|
||||||
// Start the stove
|
|
||||||
fn.commands.startup(gpio).then(res => {
|
|
||||||
statusCheck(fn, gpio);
|
|
||||||
}).catch(rej => {
|
|
||||||
// TODO
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case "none":
|
|
||||||
// If no special files are found, cycle the auger normally
|
|
||||||
if (config.status.auger == 1) {
|
|
||||||
fn.auger.cycle(gpio).then((res) => {
|
|
||||||
// Log the auger cycle results if in debug mode.
|
|
||||||
// if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
|
|
||||||
// Run the status check function
|
|
||||||
statusCheck(fn, gpio);
|
|
||||||
// Rerun this function once the cycle is complete
|
|
||||||
// main(fn, gpio);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: Auger Status: ${config.status.auger}`);
|
|
||||||
|
|
||||||
fn.commands.pause().then(res => {
|
|
||||||
statusCheck(fn, gpio);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// If we don't get a result from the file check, or for some reason it's an unexpected response, log it and quit the script.
|
|
||||||
console.error(`[${(Date.now() - config.timestamps.procStart)/1000}] E: No result was received, something is wrong.\nres: ${res}`);
|
|
||||||
fn.commands.quit();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function statusCheck(fn, gpio) {
|
|
||||||
// Once per cycle, write the config variable to the file so it can be read by the web server
|
|
||||||
fn.commands.writeConfig();
|
|
||||||
if (config.status.shutdown == 1) {
|
|
||||||
console.log(fn.commands.shutdown(gpio) || 'Shutting down...');
|
|
||||||
main(fn, gpio);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (config.status.igniter == 1) {
|
|
||||||
fn.tests.igniter(gpio).then((res) => {
|
|
||||||
if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: ${res}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the vacuum switch, if the test returns true, the vacuum is sensed
|
|
||||||
// if it returns false, we will initiate a shutdown
|
|
||||||
// TODO this is messed up
|
|
||||||
fn.tests.vacuum(gpio).then(vacStatus => {
|
|
||||||
if (!vacStatus) {
|
|
||||||
console.error('No vacuum detected, beginning shutdown procedure.');
|
|
||||||
console.log(fn.commands.shutdown(gpio));
|
|
||||||
main(fn, gpio);
|
|
||||||
} else {
|
|
||||||
// Check the Proof of Fire Switch
|
|
||||||
fn.tests.pof(gpio).then(pofStatus => {
|
|
||||||
// If the igniter has finished running and no proof of fire is seen, shutdown the stove
|
|
||||||
if (config.status.igniterFinished && (!pofStatus)) {
|
|
||||||
console.error('No Proof of Fire after the igniter shut off, beginning shutdown procedure.');
|
|
||||||
console.log(fn.commands.shutdown(gpio));
|
|
||||||
main(fn, gpio);
|
|
||||||
} else {
|
|
||||||
// if (config.debugMode) console.log(`[${(Date.now() - config.timestamps.procStart)/1000}] I: Vacuum and Proof of Fire OK.`);
|
|
||||||
main(fn, gpio);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = main;
|
|
13
websvr.js
13
websvr.js
@ -14,9 +14,7 @@ const server = http.createServer(app);
|
|||||||
const config = require('./config.json');
|
const config = require('./config.json');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
// const bodyParser = require('body-parser');
|
// const bodyParser = require('body-parser');
|
||||||
const core = require('./main.js');
|
|
||||||
const fn = require('./functions.js').functions;
|
const fn = require('./functions.js').functions;
|
||||||
const gpio = require('rpi-gpio');
|
|
||||||
|
|
||||||
app.use(express.urlencoded());
|
app.use(express.urlencoded());
|
||||||
|
|
||||||
@ -38,10 +36,17 @@ app.post('/', (req, res) => {
|
|||||||
// console.log(JSON.parse(data));
|
// console.log(JSON.parse(data));
|
||||||
res.render('index', JSON.parse(data));
|
res.render('index', JSON.parse(data));
|
||||||
if (req.body.start != undefined) {
|
if (req.body.start != undefined) {
|
||||||
fn.commands.ignite(gpio);
|
fn.commands.startup();
|
||||||
}
|
}
|
||||||
if (req.body.shutdown != undefined) {
|
if (req.body.shutdown != undefined) {
|
||||||
fn.commands.shutdown(gpio);
|
fn.commands.shutdown();
|
||||||
|
}
|
||||||
|
if (req.body.reload != undefined) {
|
||||||
|
fn.commands.refreshConfig({
|
||||||
|
augerOff: req.body.augerOff,
|
||||||
|
augerOn: req.body.augerOn,
|
||||||
|
pause: req.body.pause
|
||||||
|
});
|
||||||
}
|
}
|
||||||
// res.send(200);
|
// res.send(200);
|
||||||
});
|
});
|
||||||
|
@ -16,9 +16,9 @@
|
|||||||
<input class="button-unselected" type="submit" id="ignite" value="Start" name="start"><input class="button-unselected" type="submit" id="shutdown" value="Shutdown" name="shutdown"><input class="button-unselected" type="submit" id="reload" value="Reload" name="reload"><br>
|
<input class="button-unselected" type="submit" id="ignite" value="Start" name="start"><input class="button-unselected" type="submit" id="shutdown" value="Shutdown" name="shutdown"><input class="button-unselected" type="submit" id="reload" value="Reload" name="reload"><br>
|
||||||
</div>
|
</div>
|
||||||
<!-- Set feed rates -->
|
<!-- Set feed rates -->
|
||||||
<!-- <label for="augerOn">Auger On Interval: </label><input type="number" id="auger-on" name="augerOn" min="500" max="1000" value="<%= intervals.augerOn %>">ms<br> -->
|
<label for="augerOn">Auger On Interval: </label><input type="number" id="auger-on" name="augerOn" min="500" max="1000" step="100" value="<%= intervals.augerOn %>">ms<br>
|
||||||
<!-- <label for="augerOff">Auger Off Interval: </label><input type="number" id="auger-off" name="augerOff" min="1000" max="2000" value="<%= intervals.augerOff %>">ms<br> -->
|
<label for="augerOff">Auger Off Interval: </label><input type="number" id="auger-off" name="augerOff" min="1000" max="2000" step="100" value="<%= intervals.augerOff %>">ms<br>
|
||||||
<!-- <label for="pauseInt">App Pause Interval: </label><input type="number" id="pause-int" name="pauseInt" min="1000" max="600000" value="<%= intervals.pause %>">ms<br> -->
|
<label for="pauseInt">App Pause Interval: </label><input type="number" id="pause-int" name="pauseInt" min="1000" max="600000" step="1000" value="<%= intervals.pause %>">ms<br>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="subheading">
|
<div class="subheading">
|
||||||
|
Loading…
Reference in New Issue
Block a user