Merge branch 'v2-back' of https://git.vfsh.dev/voidf1sh/hestia into v2-back
This commit is contained in:
commit
178bc1e115
12
TODO.md
12
TODO.md
@ -1,10 +1,14 @@
|
|||||||
# In Progress
|
# In Progress
|
||||||
1. Strip to bones
|
1. ~~Strip to bones~~
|
||||||
2. Better commenting
|
2. Better commenting
|
||||||
|
2. Add startup and shutdown logic (start half implemented, not tested)
|
||||||
|
|
||||||
# Immediate To-Do
|
# Done
|
||||||
|
1. GPIO Interface
|
||||||
1. Duplicate and adapt `HestiaClasses` from branch `v2-front`
|
1. Duplicate and adapt `HestiaClasses` from branch `v2-front`
|
||||||
|
|
||||||
|
# Immediate To-Do
|
||||||
|
1. Connect to MQTT
|
||||||
|
|
||||||
# Roadmap
|
# Roadmap
|
||||||
1. Add control logic for automatic start and stop
|
1. Add wiring and sensors for safeties
|
||||||
2. Add wiring and sensors for safeties
|
|
@ -1,29 +1,81 @@
|
|||||||
export class State {
|
export class State {
|
||||||
constructor(config) {
|
constructor(config) {
|
||||||
config.mqtt.subscriptions.forEach(subscription => {
|
this.igniter = {
|
||||||
this[subscription.name] = {
|
|
||||||
on: false,
|
on: false,
|
||||||
topic: subscription.topic,
|
name: "igniter",
|
||||||
publisher: 'back',
|
topic: config.mqtt.topics.igniter,
|
||||||
|
publisher: 'front',
|
||||||
power: (communicator) => {
|
power: (communicator) => {
|
||||||
// This *should* toggle the state, asks if state is true, if it is set it false, otherwise set it true
|
// This *should* toggle the state, asks if state is true, if it is set it false, otherwise set it true
|
||||||
this[subscription.name].on ? this[subscription.name].on = false : this[subscription.name].on = true;
|
this.igniter.on ? this.igniter.on = false : this.igniter.on = true;
|
||||||
communicator.send(subscription.name, JSON.stringify(this));
|
communicator.send(config.mqtt.topics.igniter, JSON.stringify(this.igniter));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
|
||||||
|
this.exhaust = {
|
||||||
|
on: false,
|
||||||
|
name: "exhaust",
|
||||||
|
topic: config.mqtt.topics.exhaust,
|
||||||
|
publisher: 'front',
|
||||||
|
power: (communicator) => {
|
||||||
|
// This *should* toggle the state, asks if state is true, if it is set it false, otherwise set it true
|
||||||
|
this.exhaust.on ? this.exhaust.on = false : this.exhaust.on = true;
|
||||||
|
communicator.send(config.mqtt.topics.exhaust, JSON.stringify(this.exhaust));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.auger = {
|
||||||
|
on: false,
|
||||||
|
name: "auger",
|
||||||
|
feedRate: 500,
|
||||||
|
topic: config.mqtt.topics.auger,
|
||||||
|
publisher: 'front',
|
||||||
|
power: (communicator) => {
|
||||||
|
// This *should* toggle the state, asks if state is true, if it is set it false, otherwise set it true
|
||||||
|
this.auger.on ? this.auger.on = false : this.auger.on = true;
|
||||||
|
communicator.send(config.mqtt.topics.auger, JSON.stringify(this.auger));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
console.log(`State initialized.`)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Communicator {
|
export class Communicator {
|
||||||
constructor(state) {
|
constructor(state) {
|
||||||
// Connect to the MQTT Broker
|
this.publisher = state.publisher;
|
||||||
this.client = mqtt.connect(config.mqtt.address);
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
init(state, config) {
|
||||||
|
// Connect to the MQTT Broker
|
||||||
|
console.log(`Attempting MQTT connection to broker: ${config.mqtt.address}, with username: ${config.mqtt.username}`);
|
||||||
|
this.client = mqtt.connect(config.mqtt.address, {
|
||||||
|
username: config.mqtt.username,
|
||||||
|
password: config.mqtt.password
|
||||||
|
});
|
||||||
|
const { client } = this;
|
||||||
|
|
||||||
|
client.on('connect', () => {
|
||||||
|
console.log('Connected to MQTT broker');
|
||||||
// Subscribe to status topics
|
// Subscribe to status topics
|
||||||
config.mqtt.subscriptions.forEach(subscription => {
|
config.states.elements.forEach(element => {
|
||||||
this.client.subscribe(subscription.topic);
|
client.subscribe(state[element].topic, (err) => {
|
||||||
state[subscription.name].topic = subscription.topic;
|
if (!err) {
|
||||||
|
console.log(`Subscribed to ${state[element].topic}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle when the Broker sends us a message
|
||||||
|
client.on('message', (topic, message) => {
|
||||||
|
const msgStr = message.toString();
|
||||||
|
const msgJson = JSON.parse(msgStr);
|
||||||
|
console.log(`Message received on topic ${topic}: ${msgStr}`);
|
||||||
|
console.log(msgJson);
|
||||||
|
state[msgJson.name].on = msgJson.on;
|
||||||
|
window.refreshState(window.document, state);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,9 +84,9 @@ export class Communicator {
|
|||||||
// Publish with retain flag set to true
|
// Publish with retain flag set to true
|
||||||
this.client.publish(topic, message, { retain: true }, (err) => {
|
this.client.publish(topic, message, { retain: true }, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
console.error('Failed to publish message:', err);
|
||||||
} else {
|
} else {
|
||||||
// TODO: Pass back a success message
|
console.log('Message published and retained on topic:', topic);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -50,5 +50,15 @@
|
|||||||
"bcm": 25,
|
"bcm": 25,
|
||||||
"mode": "IN"
|
"mode": "IN"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"power": {
|
||||||
|
"start": {
|
||||||
|
"exhaustDelay": 30000,
|
||||||
|
"augerDelay": 60000,
|
||||||
|
"fireCheckDelay": 420000
|
||||||
|
},
|
||||||
|
"stop": {
|
||||||
|
"exhaustDelay": 600000
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -2,6 +2,11 @@ const dotenv = require('dotenv').config();
|
|||||||
const debug = process.env.DEBUG === "TRUE";
|
const debug = process.env.DEBUG === "TRUE";
|
||||||
const { pins } = require('./config.json');
|
const { pins } = require('./config.json');
|
||||||
const gpio = require('./VoidGPIO.js');
|
const gpio = require('./VoidGPIO.js');
|
||||||
|
const pinMap = new Map();
|
||||||
|
|
||||||
|
for (const pin of pins) {
|
||||||
|
pinMap.set(pin.key, pin);
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
log(message) {
|
log(message) {
|
||||||
@ -13,14 +18,32 @@ module.exports = {
|
|||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
return new Promise(resolve => setTimeout(resolve, ms));
|
||||||
},
|
},
|
||||||
gpio: {
|
gpio: {
|
||||||
|
setDefaults() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let stateChanges = [];
|
||||||
|
for (const pin of pins) {
|
||||||
|
if (pin.mode === 'OUT') {
|
||||||
|
gpio.setPin(pin.board, pin.defaultState, (err) => {
|
||||||
|
if (err) reject(err);
|
||||||
|
stateChanges.push( `Set ${pin.key} pin to ${pin.defaultState}.`);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve(stateChanges.join('\n'));
|
||||||
|
});
|
||||||
|
},
|
||||||
// Boot up sanity check during debug mode
|
// Boot up sanity check during debug mode
|
||||||
async debugInit() {
|
debugInit() {
|
||||||
module.exports.log('Resetting all output pins.');
|
module.exports.log('Resetting all output pins.');
|
||||||
pins.forEach(async (pin) => {
|
module.exports.gpio.setDefaults().then(changes => {
|
||||||
|
module.exports.log(changes);
|
||||||
|
}).catch(e => console.error(e));
|
||||||
|
|
||||||
|
pins.forEach(pin => {
|
||||||
if (pin.mode === 'OUT') {
|
if (pin.mode === 'OUT') {
|
||||||
gpio.setPin(pin.board, pin.defaultState, err => {
|
gpio.setPin(pin.board, pin.defaultState, err => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
module.exports.log(`Set ${pin.key} pin to ${pin.defaultState}.`);
|
module.exports.log();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -48,5 +71,45 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
power: {
|
||||||
|
start: {
|
||||||
|
init() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// Check pin states
|
||||||
|
|
||||||
|
// Set pins to default states
|
||||||
|
module.exports.gpio.setDefaults().then(changes => {
|
||||||
|
module.exports.log(changes);
|
||||||
|
}).catch(e => console.error(e));
|
||||||
|
// Power on igniter
|
||||||
|
gpio.setPin(pinMap.igniter.board, 1, (err) => {
|
||||||
|
if (err) reject(err);
|
||||||
|
})
|
||||||
|
// Wait for igniter preheat
|
||||||
|
|
||||||
|
// Start exhaust
|
||||||
|
|
||||||
|
// Finish igniter preheat
|
||||||
|
|
||||||
|
// Check for vacuum
|
||||||
|
|
||||||
|
// Start auger
|
||||||
|
|
||||||
|
// Wait for fire
|
||||||
|
|
||||||
|
// Check for fire
|
||||||
|
|
||||||
|
// Power off igniter
|
||||||
|
|
||||||
|
// Report successful ignition
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
stop: {
|
||||||
|
init() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user