Issue
I've managed to successfully control a relay using my Raspberry Pi and Node JS with the following code;
const express = require("express");
const Gpio = require("onoff").Gpio;
const app = express();
const port = 3000;
const REL = new Gpio(21, "out");
app.get("/on", (req, res) => {
REL.writeSync(1);
res.send("REL is on");
});
app.get("/off", (req, res) => {
REL.writeSync(0);
res.send("REL is off");
});
However, I've been struggling to get the relay to only turn on if it's off, and only turn off if it's on.
I tried the following code to no avail;
const express = require("express");
const Gpio = require("onoff").Gpio;
const app = express();
const port = 3000;
const REL = new Gpio(21, "out");
var x = 0;
if (x === 0) {
app.get("/on", (req, res) => {
REL.writeSync(1);
res.send("Relay is on");
x = 1;
});
}
if (x === 1) {
app.get("/off", (req, res) => {
REL.writeSync(0);
res.send("Relay is off");
x = 0;
});
}
When I try and turn the relay on by accessing myip:3000/on, it works just like the first code I used, however, when I try and turn the relay off by accessing myip:3000/off, I'm given the error
Cannot GET /off
I'm not sure if this is maybe something to do with the local scope not updating the global variable.
Solution
Registering endpoints and handling incoming requests are two separate activities.
Think like registering endpoints (by calling app.get(path, callback)
) is happening before application start to listen for requests.
Next, when the application is running, Express tries to match incoming requests with registered endpoint handlers for further processing.
If Express won't find any matching endpoints it falls back to its default behavior and shows a page with Error information e.g.: Cannot GET /off
.
In your current code, you register endpoints conditionally. When you start your application only the /on
endpoint is registered. To fix this behavior move if
blocks to endpoint handlers or change code like @lfaruki advised. Remeber to add else
blocks or add next()
calls to prevent your app from hanging.
const express = require("express");
const Gpio = require("onoff").Gpio;
const app = express();
const port = 3000;
const REL = new Gpio(21, "out");
var x = 0;
app.get("/on", (req, res) => {
if (x === 0) {
REL.writeSync(1);
res.send("Relay is on");
x = 1;
}
else {
res.send("Relay is already running");
}
});
app.get("/off", (req, res) => {
if (x === 1) {
REL.writeSync(0);
res.send("Relay is off");
x = 0;
}
else {
res.send("Relay is already turned off");
}
});
Answered By - macborowy