Control a separate running script from a Web Server (python)- RPi

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

flaskupload3.JPG

Step 4: Run SignalReceiver.py

flaskupload4.JPG

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.

flaskupload5

Link to project: https://sourceforge.net/projects/pi-send-signals-to-scripts/