How I built a remote-control switch for my boost pump using Raspberry-pi and Node.js: Part 1
The first step is often the most important and, by far, the most difficult. There are problems that seem very difficult from the outside, until you come closer.

This is a rather long article, so I have broken it down into multiple parts.
About me
I was trained a mechanical engineer (super-secret: never graduated), but I’ve had very keen interest in electronics since I was a child, an interest which ultimately drove me into software engineering. I have no training on electronics except one course I took in the university (into to electronic engineering, featuring RLC circuits and the likes). Turns out, with a little more curiosity and digging, that is enough.
A little background
In 2016, around June, I moved to a new house in Lekki Gardens Phase 2. Lekki Gardens is a serviced and managed estate. However, soon, I found out that “managed” does not always have the same meaning everywhere. The estate has a central water supply, but it turns out that it is woefully insufficient. At first, water was available intermittently, so we had to fill our buckets and big containers when there’s water in preparation for the rest of the day (or the rest of the next two day to one week) when there may not be any water. We’re not allowed to drill our own borehole or a well, neither are we allowed to install storage tanks. With luck and some eloquence (lie!), we were able to convince the security to let us install an external storage tank. This made life easier, as all we had to do was open the tap and we have water (we installed ball valves and non-return valves to ensure we never have to worry about when the tank is full or when the estate water has been cut off).
Well, all was rosy, until more people started packing into the estate. First, the frequency started reducing drastically. We saw water once in two days, and it runs only for an hour, barely enough to fill the 1500l (combined) tanks. Then, the pressure started reducing. It got to a point where the pressure was not enough to push the water into the tanks anymore. That was how we decided to buy a boost pump.
Our boost pump made things much easier. We could now fill our tanks in less than 45 minutes with our high-pressure 1hp pump (the tank is high, more than 7m off the ground). The pump worked quite well, but there was one problem. The pump is supposed to cut off automatically when the pressure gets too high (indicating there are no open faucets or valves, thus no water flow). However, we found out our piping was leaking somewhere. For all we know, it could be anywhere along the 20m underground (beneath interlocks and concrete flooring) piping running around the house, but we had enough evidence that it was leaking. So, this meant we had to turn on and turn off the pump manually. The pump switch was downstairs, AND outside. The house has no front fence, and no privacy, so we had to dress up to go put on or put off the pump. It was incredibly inconveniencing!
Then, a thought came to me. Why not design something that would allow us to switch on and switch off the pump remotely? I told my wife that I could build something for her that would let her control the pump from her phone, from anywhere in the world. She first laughed me to scorn, then she believed me.
Meet Raspump

Raspump, as I called it (Raspberry Pump), is a raspberry-pi-based on-off switch. It’s one of the simplest Raspberry Pi projects you can hope to build (after a led switch). However, things got complicated very fast after I decided that I wanted the app to work not only within our home wifi, but from anywhere in the world. Turned out switching the pump on was the easiest part of the project.
Raspump is made up of four (4) parts: Raspump Remote Server, Raspump Local Server, Raspump Pi, and Raspump App. In this article, I will focus on the Raspump Pi, and the electronics surrounding it.
The tools I used
I used Raspberry Pi model 3, which has a lot of usable GPIO pins, much more than I needed (I needed only two). I intended to buy a Pi 3 for development and testing, and a Pi Zero W for the final product. However, Pi Zero and Zero W proved very difficult to obtain.
I also bought a pack of NPN resistors (2N2222), an assortment of metal film resistors, a 10A relay, a push switch, a set of male to female jumper wires, and set of LEDs. I also bought a wire stripper, and a digital multimeter, both of which are not required, but make things easier. I bought a Raspberry Pi Zewo casing (before I realised I could not buy the Pi Zero W), and a Pi battery pack (including a charge controller and a 3800mAH Li-Po battery). I already have lots of 5V phone chargers and even more USB-A to USB Micro-B cables.
The circuit
This is the circuit diagram of what I planned.

This is a simple enough circuit diagram. It’s important to point out that the relay is a single circuit, providing 3 circuit pins (GND, Vcc, IN), and 3 high load pins (NO, NC, COM). The transistor and diode are both part of that circuit.
- L1 is the power LED. It indicates when the system is on (note that this will come on once the Pi is on, not when it is ready).
- L2 is the status LED. It indicates when the pump is on.
- GPIO19 is connected to the GPIO19 pin.
- GPIO12 is connected to the GPIO12 pin.
- S1 is a physical switch to turn the pump on/off when it is more convenient.
- R1 is 70Ω. R5 is 60Ω. R2 is 100Ω. Q2 is 2N2222 NPN.
- Every other resistor is 1kΩ.
However, when I tested this circuit, I was very unpleasantly surprised. It happened that the relay I bought was a LOW TRIGGER relay. That is, the relay switches on when the signal pin is connected to ground, instead of Vcc. I had to design around this (so proud of myself) using my little understanding of electronics. This is what I ended up with.

The only difference between this and the original design is the introduction of an additional transistor and supporting resistors. R7 (10kΩ) is a pull-up resistor. That is, when the transistor is open (no current through the transistor), it forces the signal going into the relay to become Vcc (relay will be off). When there is signal from the GPIO pin, the transistor closes, and current starts flowing. Because R8 (1kΩ) is smaller than R7, the voltage going into the relay (~+0.45v) is so close to GND that the relay interprets it as GND and comes on. In a more sensitive application, we would either lower R8 or increase R7 to make the voltage much closer to GND.
Now when I apply signal to GPIO19, L2 comes ON, and the relay closes, turning the pump on. Well, that was simple enough.
Pressing the contact switch S1 will send 3.3v to GPIO12, which we’re going to detect in our app and act accordingly.
Architecture
Following are the different parts that make up this project.
- Raspump Pi — This is the Raspberry pi driver. It is the software that is installed inside the Pi itself to make it work.
- Raspump Remote — This is the remote server, hosted on the Internet. This is the server that ensures that the Pi can be controlled from anywhere in the world.
- Raspump Local — This is a local server (resides in my computer :D). This is the primary control server. This server syncs with the remote server.
- Raspump App — This is the user-facing app that is used to control the pump. I converted it into a Cordova application for easier access, but also hosted it online in case I find myself without my phone.
Raspump Pi
Now to the exciting things. Wiring the Pi turned out to be the easiest and, by far, the least time-consuming part of the whole project.
Raspump Pi, as I called it, is the Raspberry pi component of the 4-part control software. It runs on Node.js v8. I chose Typescript for the project because I have fallen in love with Typescript. The first time I used Typescript on a project, I wondered how I had been able to use plain JS all these while without type checks.
I will not attempt to explain every line of code. I will only mention the important ones, and the ones that need explaining. You can view the whole code at the Github repo linked above.
Tech Stack
Raspump uses Socket.io for real-time signalling, and onoff (https://www.npmjs.com/package/onoff) for detecting interrupts (this is important for detecting when the push button is pressed). Initially, I wanted to do without the library, but I needed to detect interrupts, which are impossible to detect using JavaScript alone, so I had to use onoff instead.
Operating principle
There are only two things that the app ever needs to do.
- Detect when the pump has been switched (on or off) and act accordingly.
- Detect when the on/off physical button has been pressed and act accordingly.
Connecting
When the driver starts, it tries to connect to the local server and the remote server simultaneously. If it makes contact with the local server, it will disconnect the remote server.
The servers are written to be somewhat secure and to be scalable. Therefore, upon making contact, the application first needs to authenticate with the server. It will send an “auth” event with a username and password (see the login method in src/socket.ts).
If authentication goes wrong, we really don’t have anything else we’re doing. We kill the app.
After authentication, we send a “subscribe” event with our device ID (this device is “boostpump”). This tells the servers that we want to be notified of any changes to the status of “boostpump”.
Detecting remote control
When the pump is switched remotely, one of the servers sends a signal to the pump driver. The code that controls the connection to the server can be found in src/socket.ts. When there is a change on the app, the servers send a signal to the Pi driver.
When there is a change, pump.switchPump is called with the new status, and the date of the switch (the code that controls the pump is found in src/pump.ts). The date is important, as it ensures that if there is a network delay, the last signal (and thus the most recent and probably the correct one) is what is processed. If the date is earlier than the last switch date, the change is not applied.
Detecting button press
When the physical button is pressed, a signal is sent through GPIO pin 12. This change is detected as an interrupt, using onoff, and triggers an event.
The pump is switched (line 8 above), and a pushButton event is dispatched, which is detected (in src/index.ts) and a socket event is sent to the server (socket.setStatus(deviceId, status);). This updates the servers and every other observer (including all control apps).
Switching the pumps
The easiest part of the whole thing is switching on the pump. Switching on the pump is as simple as writing “1” to the file /sys/class/gpio/gpio19/value. Switching it off is as simple as writing “0” to the same file.
Setting up the Raspberry pi
This not all plug and play. We need to do one or two things to get our pi up and running.
First, I installed Raspbian on an SD Card. I connected the Pi to my TV via HDMI to set up the network (you can also use the ethernet port to connect directly to a network if you have nowhere to plug the Pi). Setting up the network allowed me to SSH into the Pi and do the rest of my configuration there. I also needed to configure the Pi to allow SSH in the first place. Being lazy to change the default password (and remember the new password), I simply disabled password login via SSH. All these are beyond the scope of this article. A simple Google search will return a lot of results on setting up a Pi for SSH access.
I installed Node.js. Note that downloading Node.js from the node homepage will not work. You need to specifically download ARMv7 builds of Node.js. You can find one at https://nodejs.org/en/download/current/.
I cloned the code into /home/pi/raspump-pi and ran npm install --prod to install dependencies. You will need to run this command on the Pi, with the specific version of node installed. If you install another version of node, you will need to npm install --prod again (because onoff needs to compile Epoll for the specific version of node).
Making the GPIO pins available for node
Before you can access the GPIO pins, you need to export the pins. Since our application needs GPIO19 and GPIO12, we need to export those two pins. To do that, we write 19 and 12 to /sys/class/gpio/export:
echo '12' > /sys/class/gpio/export
echo '19' > /sys/class/gpio/exportNote that these are not ordinary files. They are special files. So, you can’t for example run cat /sys/class/gpio/export. You will get IO error.
Starting up the driver on system startup
Since this is Nigeria, and there is no guarantee of electricity, even with the backup battery, there could be darkness long enough for the battery to die, I had to find a way to start the service once the system boots up. This is rather very easy. There are many ways to achieve this, but I chose to use crontab. In the terminal, I ran crontab -e to bring up the crontab editor. I wrote the following line:
@reboot /usr/local/bin/node /home/pi/raspump-pi/src/index.js > /home/pi/raspump-pi/raspump.logThis writes all output to raspump.log.
That is all that makes up the first part of the application. In part 2 of the article, I will write about the servers and the control app.
