Logic and comms ready for testing
This commit is contained in:
parent
0c1c1483b1
commit
236faaefbe
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -11,7 +11,7 @@
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"program": "${workspaceFolder}/main.js"
|
||||
"program": "${workspaceFolder}/src/main.js"
|
||||
}
|
||||
]
|
||||
}
|
@ -5,11 +5,13 @@ module.exports = {
|
||||
// State class
|
||||
State: class State {
|
||||
constructor(config) {
|
||||
this.publisher = 'backend';
|
||||
|
||||
this.igniter = {
|
||||
on: false,
|
||||
name: "igniter",
|
||||
topic: config.mqtt.topics.igniter,
|
||||
publisher: 'backend',
|
||||
publisher: this.publisher,
|
||||
power: (communicator, pinState) => {
|
||||
// Set the power based on the desired pinState
|
||||
this.igniter.on = pinState === 1 ? true : false;
|
||||
@ -21,7 +23,7 @@ module.exports = {
|
||||
on: false,
|
||||
name: "exhaust",
|
||||
topic: config.mqtt.topics.exhaust,
|
||||
publisher: 'backend',
|
||||
publisher: this.publisher,
|
||||
power: (communicator, pinState) => {
|
||||
// Set the power based on the desired pinState
|
||||
this.exhaust.on = pinState === 1 ? true : false;
|
||||
@ -34,13 +36,37 @@ module.exports = {
|
||||
name: "auger",
|
||||
feedRate: 500,
|
||||
topic: config.mqtt.topics.auger,
|
||||
publisher: 'backend',
|
||||
publisher: this.publisher,
|
||||
power: (communicator, pinState) => {
|
||||
// Set the power based on the desired pinState
|
||||
this.auger.on = pinState === 1 ? true : false;
|
||||
communicator.send(config.mqtt.topics.auger, JSON.stringify(this.auger));
|
||||
}
|
||||
};
|
||||
|
||||
this.pof = {
|
||||
on: false,
|
||||
name: "pof",
|
||||
topic: config.mqtt.topics.pof,
|
||||
publisher: this.publisher,
|
||||
power: (communicator, pinState) => {
|
||||
// Set the power based on the desired pinState
|
||||
this.pof.on = pinState === 1 ? true : false;
|
||||
communicator.send(config.mqtt.topics.pof, JSON.stringify(this.pof));
|
||||
}
|
||||
};
|
||||
|
||||
this.vacuum = {
|
||||
on: false,
|
||||
name: "vacuum",
|
||||
topic: config.mqtt.topics.vacuum,
|
||||
publisher: this.publisher,
|
||||
power: (communicator, pinState) => {
|
||||
// Set the power based on the desired pinState
|
||||
this.vacuum.on = pinState === 1 ? true : false;
|
||||
communicator.send(config.mqtt.topics.vacuum, JSON.stringify(this.vacuum));
|
||||
}
|
||||
};
|
||||
console.log(`State initialized.`)
|
||||
};
|
||||
},
|
||||
@ -76,19 +102,20 @@ module.exports = {
|
||||
// Handle when the Broker sends us a message
|
||||
client.on('message', (topic, message) => {
|
||||
// Save the existing state
|
||||
const oldState = { ...state };
|
||||
const oldState = JSON.parse(JSON.stringify(state));
|
||||
// The message is a buffer which will need to be converted to string
|
||||
const msgStr = message.toString();
|
||||
// Since the message is a JSON object, we can parse it
|
||||
const msgJson = JSON.parse(msgStr);
|
||||
// Log the message
|
||||
console.log(`Message received on topic ${topic}:`);
|
||||
console.log(msgJson);
|
||||
// console.log(`Message received on topic ${topic}:`);
|
||||
// console.log(msgJson);
|
||||
// Check if the message is from the backend
|
||||
if (msgJson.publisher === this.publisher) {
|
||||
console.log('Message is from the backend, ignoring');
|
||||
// console.log('Message is from the backend, ignoring');
|
||||
return;
|
||||
}
|
||||
// console.log('Message is from the frontend, updating state');
|
||||
// Update the state
|
||||
state[msgJson.name].on = msgJson.on;
|
||||
// Emit the state change
|
||||
|
@ -1,20 +1,21 @@
|
||||
const { exec } = require('child_process');
|
||||
const config = require('./config.json');
|
||||
|
||||
module.exports = {
|
||||
// Calls the GPIO Interface script to toggle a pin's state opposite of its current state
|
||||
togglePin(pin) {
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(`python3 src/python/gpio_interface.py toggle ${pin}`, (error, stdout, stderr) => {
|
||||
if (error) reject(error);
|
||||
if (stderr) reject(new Error(stderr));
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
},
|
||||
// togglePin(pin) {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// exec(`python3 ${config.gpioScript} toggle ${pin}`, (error, stdout, stderr) => {
|
||||
// if (error) reject(error);
|
||||
// if (stderr) reject(new Error(stderr));
|
||||
// resolve();
|
||||
// });
|
||||
// });
|
||||
// },
|
||||
// Calls the GPIO Interface script to read a pin's state
|
||||
readPin(pin) {
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(`python3 src/python/gpio_interface.py read ${pin}`, (error, stdout, stderr) => {
|
||||
exec(`python3 ${config.gpioScript} read ${pin}`, (error, stdout, stderr) => {
|
||||
if (error) reject(error);
|
||||
if (stderr) reject(new Error(stderr));
|
||||
resolve(stdout.trim());
|
||||
@ -24,7 +25,7 @@ module.exports = {
|
||||
// Calls the GPIO Interface script to set a pin's state regardless of its current state
|
||||
setPin(pin, state) {
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(`python3 src/python/gpio_interface.py set ${pin} ${state}`, (error, stdout, stderr) => {
|
||||
exec(`python3 ${config.gpioScript} set ${pin} ${state}`, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
}
|
||||
|
@ -60,5 +60,6 @@
|
||||
"stop": {
|
||||
"exhaustDelay": 600000
|
||||
}
|
||||
}
|
||||
},
|
||||
"gpioScript": "src/python/gpio_interface.py"
|
||||
}
|
@ -38,33 +38,11 @@ module.exports = {
|
||||
}).catch(reject);
|
||||
});
|
||||
},
|
||||
// Boot up sanity check during debug mode
|
||||
async debugInit() {
|
||||
async init(communicator, state) {
|
||||
module.exports.log('Resetting all output pins.');
|
||||
module.exports.gpio.setDefaults().then((changes) => {
|
||||
module.exports.gpio.setDefaults(communicator, state).then((changes) => {
|
||||
module.exports.log(changes);
|
||||
}).catch(e => console.error(e));
|
||||
|
||||
for (const pin of pins) {
|
||||
switch (pin.mode) {
|
||||
case 'OUT':
|
||||
gpio.togglePin(pin.board).then(() => {
|
||||
module.exports.log(`Toggled ${pin.key}`);
|
||||
}).catch(e => console.error(e));
|
||||
// Wait 1000ms before toggling again.
|
||||
await module.exports.sleep(1000);
|
||||
gpio.togglePin(pin.board).then(() => {
|
||||
module.exports.log(`Toggled ${pin.key}`);
|
||||
}).catch(e => console.error(e));
|
||||
break;
|
||||
case 'IN':
|
||||
gpio.readPin(pin.board).then(state => {
|
||||
module.exports.log(`${pin.key} state: ${state}`);
|
||||
}).catch(e => console.error(e));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
power: {
|
||||
@ -155,6 +133,10 @@ module.exports = {
|
||||
return gpio.setPin(pin.board, 1).then(() => {
|
||||
console.log(`${pin.key} powered on.`);
|
||||
}).catch(e => console.error(e));
|
||||
} else {
|
||||
return gpio.setPin(pin.board, 0).then(() => {
|
||||
console.log(`${pin.key} powered off.`);
|
||||
}).catch(e => console.error(e));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -9,14 +9,19 @@ const comms = new Communicator(psState);
|
||||
|
||||
comms.init(psState, config);
|
||||
|
||||
fn.gpio.debugInit();
|
||||
fn.gpio.init(comms, psState);
|
||||
|
||||
// Sensor detection loop
|
||||
setInterval(() => {
|
||||
for (const pin of config.pins) {
|
||||
if (pin.mode === 'IN') {
|
||||
gpio.readPin(pin.board).then(state => {
|
||||
fn.log(`${pin.key}: ${state}`);
|
||||
const boolState = state === '1' ? true : false;
|
||||
if (boolState !== psState[pin.key].on) {
|
||||
psState[pin.key].on = boolState;
|
||||
comms.send(config.mqtt.topics[pin.key], JSON.stringify(psState[pin.key]));
|
||||
fn.log(`${pin.key}: ${state}`);
|
||||
}
|
||||
}).catch(e => console.error(e));
|
||||
}
|
||||
}
|
||||
|
75
src/python/fake_gpio.py
Normal file
75
src/python/fake_gpio.py
Normal file
@ -0,0 +1,75 @@
|
||||
import sys
|
||||
|
||||
# Define the state of the pins
|
||||
PIN_STATES = {
|
||||
7: 0,
|
||||
13: 0,
|
||||
15: 0,
|
||||
16: 0,
|
||||
22: 0
|
||||
}
|
||||
|
||||
# Define a function to get the pin state from the array
|
||||
def get_pin_state(pin):
|
||||
if pin in PIN_STATES:
|
||||
return PIN_STATES[pin]
|
||||
else:
|
||||
print(f"Invalid pin: {pin}")
|
||||
return -1
|
||||
|
||||
# Modify the read_pin function to use the get_pin_state function
|
||||
def read_pin(pin):
|
||||
try:
|
||||
# Read pin state
|
||||
state = get_pin_state(pin)
|
||||
# Return 1 if pin is HIGH, 0 if LOW
|
||||
return 1 if state == 1 else 0
|
||||
except Exception as e:
|
||||
# Handle errors
|
||||
print(f"Error reading pin {pin}: {e}")
|
||||
# Return -1 on error
|
||||
return -1
|
||||
|
||||
# Modify the set_pin_state function to return success always
|
||||
def set_pin_state(pin, state):
|
||||
try:
|
||||
# Set the pin state to either HIGH (1) or LOW (0)
|
||||
# Exit with 0 for success
|
||||
return 0
|
||||
except Exception as e:
|
||||
# Handle errors
|
||||
print(f"Error setting pin {pin} to state {state}: {e}")
|
||||
# Exit with 1 for failure
|
||||
return 1
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 3:
|
||||
print("Usage: python3 gpio_interface.py <command> <pin> [<state>]")
|
||||
sys.exit(1)
|
||||
|
||||
command = sys.argv[1].lower()
|
||||
pin = int(sys.argv[2])
|
||||
|
||||
if command == "toggle":
|
||||
result = toggle_pin(pin)
|
||||
sys.exit(result)
|
||||
elif command == "read":
|
||||
result = read_pin(pin)
|
||||
print(result)
|
||||
sys.exit(0 if result >= 0 else 1)
|
||||
elif command == "set":
|
||||
if len(sys.argv) < 4:
|
||||
print("Usage: python3 gpio_interface.py set <pin> <state>")
|
||||
sys.exit(1)
|
||||
state = int(sys.argv[3])
|
||||
if state not in [0, 1]:
|
||||
print("Invalid state. Use 0 for LOW or 1 for HIGH.")
|
||||
sys.exit(1)
|
||||
result = set_pin_state(pin, state)
|
||||
sys.exit(result)
|
||||
else:
|
||||
print("Invalid command. Use 'toggle', 'read', or 'set'.")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue
Block a user