Skip to content

Commit

Permalink
Add gpio control
Browse files Browse the repository at this point in the history
  • Loading branch information
martenmatrix committed Dec 22, 2021
1 parent 5afde27 commit 73f48ff
Show file tree
Hide file tree
Showing 23 changed files with 3,841 additions and 18 deletions.
22 changes: 19 additions & 3 deletions backend/raspberry.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
const gpio = require('onoff').Gpio;

//index +1 stands for pumpid
const relays = [
new gpio(11, 'out'),
new gpio(13, 'out'),
new gpio(19 , 'out'),
new gpio(17, 'out'),
new gpio(27, 'out'),
new gpio(22, 'out'),
new gpio(10, 'out'),
new gpio(9, 'out'),
]

function showOnDisplay(text, removeAfter = null) {

}

async function activatePump(pumpID, activateFor) {
console.log(`Activating pump ${pumpID} for ${activateFor} ms`);
const pumpArrayIndex = pumpID - 1;
const relay = relays[pumpArrayIndex];
relay.writeSync(1);
await new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, Math.floor(activateFor));
});
console.log(`Pump ${pumpID} disabled after ${activateFor} ms`);

relay.writeSync(0);
relay.unexport();
return true;
}

Expand Down
14 changes: 14 additions & 0 deletions buildBackend/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
NODE_ENV = 'development'
BACKEND_PORT = 4000
# frontend port must also be changed in frontend/src/requests.js
FRONTEND_PORT = 3000
SETTINGS_PASSWORD = 'cocktail'
# pump rates in ml per 1s
RATE_PUMP_1 = 100;
RATE_PUMP_2 = 100;
RATE_PUMP_3 = 100;
RATE_PUMP_4 = 100;
RATE_PUMP_5 = 100;
RATE_PUMP_6 = 100;
RATE_PUMP_7 = 100;
RATE_PUMP_8 = 100;
129 changes: 129 additions & 0 deletions buildBackend/backend/backend/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
const cors = require('cors');
const dotenv = require('dotenv');
const fs = require('fs');
const showOnDisplay = require('./raspberry').showOnDisplay;
const activatePump = require('./raspberry').activatePump;
const checkPassword = require('./misc').checkPassword;
const getTask = require('./currentTask').getTask;
const pumpsJSONPATH = './data/pumps.json';

const result = dotenv.config({
path: './.env'
});
if (result.error) {
throw result.error;
}
console.log(result.parsed);

const http = require('http');
const express = require('express');
const ip = require("ip");
const app = express();
app.use(express.json());
app.use(cors());

//import routes
const drinkRoute = require('./routes/drinks');
app.use('/drink', drinkRoute);
app.use(cors({origin: '*'}));

app.get('/status', (req, res) => {
const status = getTask();
res.status(200);
res.send({
task: status
});
});

app.get('/pumps', (req, res) => {
fs.readFile(pumpsJSONPATH, "utf8", (error, jsonString) => {
if (error) {
res.status(500);
res.send({ error: error.message });
return;
}
res.status(200);
res.send(jsonString);
});
});

app.patch('/setPump', (req, res) => {
const response = {
success: false,
}

const password = req.body.password;
const selectedPumpID = req.body.pump;
const newSelection = req.body.newSelection;

if (!(password || selectedPumpID || newSelection)) {
res.status(500);
const passedParameters = JSON.stringify({password, pump: selectedPumpID, newSelection});
res.send({ error: `Wrong parameters ${passedParameters}` });
return;
};

if(checkPassword(password).correct) {
const currentPumpStatus = JSON.parse(fs.readFileSync(pumpsJSONPATH, 'utf8'));
const newPumpsArray = currentPumpStatus.pumps.map(pump => {
if(pump.id === selectedPumpID) {
pump.select = newSelection;
}
return pump;
});

fs.writeFile(pumpsJSONPATH, JSON.stringify({pumps: newPumpsArray}), (error) => {
if (error) {
res.status(500);
res.send({ error: error.message });
return;
}
res.status(200);
response.success = true;
res.send(response);
});
} else {
res.status(401);
res.send(response);
}
});

app.post('/password', async (req, res) => {
const response = checkPassword(req.body.password);
res.status(200);
res.send(response);
});


let lastRequests = [
Promise.resolve(),
Promise.resolve(),
Promise.resolve(),
Promise.resolve(),
Promise.resolve(),
Promise.resolve(),
Promise.resolve(),
Promise.resolve(),
];

app.post('/startPump', async (req, res) => {
res.status(200);
res.send({success: true});
const pumpID = req.body.id;
const timeInMs = req.body.time;

const response = await Promise.race([lastRequests[pumpID - 1], 'loading']);
if (response === 'loading') return;

const promise = activatePump(pumpID, timeInMs);
lastRequests[pumpID - 1] = promise;
});

// get ip with -hostname I
// https://pimylifeup.com/raspberry-pi-static-ip-address/
const hostname = ip.address();
const port = process.env.BACKEND_PORT || 3000;

const server = app.listen(port, () => {
console.log('Server running at '+hostname+':'+port)
});
14 changes: 14 additions & 0 deletions buildBackend/backend/backend/currentTask.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
const task = {
task: 'Idle'
}

function setTask(newTask) {
task.task = newTask;
}

function getTask() {
return task.task;
}

module.exports.getTask = getTask;
module.exports.setTask = setTask;
129 changes: 129 additions & 0 deletions buildBackend/backend/backend/databaseHandler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
const sqlite3 = require('sqlite3').verbose();
const drinksDatabase = new sqlite3.Database('./data/database.db', (err) => {
if (err) {
console.error(err.message);
} else {
console.log('Connected to the drinks database.');
}
});

class DrinksDatabase {
static async createTables() {

const createDrinks = new Promise((resolve, reject) => {
drinksDatabase.run('CREATE TABLE IF NOT EXISTS drinks (id INTEGER PRIMARY KEY, name TEXT, hasAlcohol BOOLEAN)', (err) => {
if (err) {
reject(err);
}
resolve();
});
});
const createIngredients = new Promise((resolve, reject) => {
drinksDatabase.run('CREATE TABLE IF NOT EXISTS ingredients (id INTEGER, ingredient TEXT, categoryOfIngredient TEXT, amountOfIngredient REAL, unitOfMeasurement TEXT)', (err) => {
if (err) {
reject(err);
}
resolve();
});
});

return Promise.all([createDrinks, createIngredients]);
}

static getID() {
return Math.floor(+Date.now() + Math.random());
}

static async createDrink(name, hasAlcohol) {
const newID = this.getID();
return new Promise((resolve, reject) => {
drinksDatabase.run('INSERT INTO drinks (id, name, hasAlcohol) VALUES (?, ?, ?)', [newID, name, hasAlcohol], (err) => {
if (err) {
reject(err);
}
resolve(newID);
});
});
}

static async removeDrink(id) {
const deleteIngredients = new Promise((resolve, reject) => {
drinksDatabase.run('DELETE FROM ingredients WHERE id = ?', [id], (err) => {
if (err) {
reject(err);
}
resolve();
});
});

const deleteDrink = new Promise((resolve, reject) => {
drinksDatabase.run('DELETE FROM drinks WHERE id = ?', [id], (err) => {
if (err) {
reject(err);
}
resolve();
});
});

await Promise.all([deleteIngredients, deleteDrink]);
}

static async addIngredient(drinkID, ingredient, category, amount, unit) {
return new Promise((resolve, reject) => {
drinksDatabase.run('INSERT INTO ingredients (id, ingredient, categoryOfIngredient, amountOfIngredient, unitOfMeasurement) VALUES (?, ?, ?, ?, ?)', [drinkID, ingredient, category, amount, unit], (err) => {
if (err) {
reject(err);
}
resolve();
})
});
}

static async getIngredients(drinkID) {
return new Promise((resolve, reject) => {
drinksDatabase.all('SELECT * FROM ingredients WHERE id = ?', [drinkID], (err, rows) => {
if (err) {
reject(err);
}
resolve(rows);
});
});
}

static async getAllIngredientsCategories() {
return new Promise((resolve, reject) => {
drinksDatabase.all('SELECT DISTINCT categoryOfIngredient FROM ingredients', (err, rows) => {
if (err) {
reject(err);
}
resolve(rows);
});
});
}

static async getAllDrinks() {
return new Promise((resolve, reject) => {
drinksDatabase.all('SELECT * FROM DRINKS', (err, rows) => {
if (err) {
reject(err);
}
resolve(rows);
});
});
}

static async endConnection() {
return new Promise((resolve, reject) => {
drinksDatabase.close((err) => {
if (err) {
reject(err);
}
resolve();
})
});
}
}

DrinksDatabase.createTables();

module.exports = DrinksDatabase;
Empty file.
37 changes: 37 additions & 0 deletions buildBackend/backend/backend/misc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const ingredientsJSONPATH = './data/ingredients.json';
const fs = require('fs');

function checkPassword(password) {
const response = {
correct: false
}

const validPassword = process.env.SETTINGS_PASSWORD;

if (validPassword === password) {
response.correct = true;
}

return response;
}
module.exports.checkPassword = checkPassword;

async function getCategoryOfIngredient(ingredient) {
const currentIngredients = await fs.promises.readFile(ingredientsJSONPATH, "utf8"). catch((error) => {
res.status(500);
res.send({ error: error.message });
return;
});

let foundCategory = null;
Object.entries(JSON.parse(currentIngredients)).forEach(([category, ingredients]) => {
ingredients.forEach((ingredientInCategory) => {
if (ingredientInCategory === ingredient) {
foundCategory = category;
}
});
});

return foundCategory;
}
module.exports.getCategoryOfIngredient = getCategoryOfIngredient;
Empty file.
Loading

0 comments on commit 73f48ff

Please sign in to comment.