Let’s say that you have a running Flask server and you want your user to control the state (on/off) of a motion sensor via the GPIO. The most complex way is to create a multi-threading script which handles the server and GPIO code.
Another approach is to separate the server script from the GPIO script. Thus having two layers of scripts. This has the advantage to debug in isolation. For this technique one has to use Unix Signals which can be used to send signals from one process to another.
When you execute a script on your UNIX system, the system creates a process id (pid) which is different every time. A signal is a software interrupt which notifies a process with a significant event or request.
The following table gives a list of the most common signals:
NAME | NUMBER | DESCRIPTION |
SIGHUP | 1 | Linux sends a process this signal when it becomes disconnected from a terminal. |
SIGINT | 2 | Linux sends a process this signal when the user tries to end it by
pressing CTRL+C. |
SIGILL | 4 | Linux sends a process this signal when it attempts to execute an illegal instruction. |
SIGABRT | 6 | Linux sends a process this signal to the process when the process calls the ‘abort ()’ function |
SIGFPE | 8 | Linux sends a process this signal when it has executed an invalid floating-point math instruction |
SIGKILL | 9 | Linux sends a process this signal to end it immediately |
SIGUSR1 | 10 | User programs can send this signal to other process |
SIGUSR2 | 12 | User programs can send this signal to other process |
SIGSEGV | 11 | Linux sends a process this signal when the program has attempted an invalid memory access |
SIGPIPE | 13 | Linux sends a process this signal when the program has attempted to access a broken data stream, such as a socket connection that has been already closed |
SIGALRM | 14 | A process can receive this signal from the Linux using the function alarm (), after a time period mentioned in its argument. |
SIGTERM | 15 | Linux sends a process this signal requesting it to terminate |
SIGCHLD | 17 | Linux sends a process this signal when a child process exits |
SIGXCPU | 24 | Linux sends a process this signal when it exceeds the limit of
CPU time that it can consume. |
SIGVTALRM | 26 | A process can receive this signal from the Linux using the function setitimer (), after a time period mentioned in its argument. |
We are interested in SIGUSR1 and SIGUSR2 which can be used to send user signals.
Step 1:
First create the server layer (app.py). Documentation about Flask server can be found here.
from flask import * import os import signal app = Flask(__name__) @app.route('/') def index(): return render_template('index.html') @app.route('/trigger1') def process1(): #read process id from text file fh=open("processid.txt","r") processId = int(fh.read()) fh.close() #send signal to process id os.kill(processId, signal.SIGUSR1) return render_template('trigger1.html') @app.route('/trigger2') def process2(): #read process id from text file fh=open("processid.txt","r") processId = int(fh.read()) fh.close() #send signal to process id os.kill(processId, signal.SIGUSR2) return render_template('trigger2.html') if __name__ == '__main__': app.run(debug=True,host='0.0.0.0')
Step 2:
Create the SignalReceiver.py script (you can modify this to control the GPIOs)
import os import signal import time fh=open("processid.txt","w") fh.write(str(os.getpid())) #get current process id and store in file fh.close() def handUSR1(signum,frame): print('triggered',signum) def handUSR2(signum,frame): print('triggered',signum) signal.signal(signal.SIGUSR1,handUSR1) #callback function for SIGUSR1 signal signal.signal(signal.SIGUSR2,handUSR2) #callback function for SIGUSR2 signal while(True): time.sleep(1) print("Waiting for signal")
Step 3: Run Server
Step 4: Run SignalReceiver.py
Step 5:
In the browser, click Trigger 1 and Trigger 2 hyperlink buttons. Notice that SignalReceiver.py outputs ‘triggered 10′ and ‘triggered 12′. This means that both signals were sent and received correctly.
Link to project: https://sourceforge.net/projects/pi-send-signals-to-scripts/
One thought on “Raspberry Pi – Control a separate running script from a Web Server”