EBC Exercise 32 gpio via flask

This is an introduction to how to control the Beagle via the Web using Flask. Much of this is from https://towardsdatascience.com/python-webserver-with-flask-and-raspberry-pi-398423cc6f5d.

Installing Flask
Flask should already be installed on the Bone. But if not:

bone$ sudo apt update bone$ sudo apt install python3-flask

All the examples are in the class repo bone$ git clone https://github.com/MarkAYoder/BeagleBoard-exercises.git examples bone$ cd examples/flask/server

First Flask - hello, world
Our first example is helloWorld.py

from flask import Flask app = Flask(__name__) @app.route('/') def index: return 'hello, world' if __name__ == '__main__': app.run(debug=True, port=8081, host='0.0.0.0')
 * 1) !/usr/bin/env python3
 * 2) From: https://towardsdatascience.com/python-webserver-with-flask-and-raspberry-pi-398423cc6f5d

The first line loads the Flask module into your Python script. The second line creates a Flask object called app. The third line is where the action is, it says to run the index function when someone accesses the root URL (‘/’) of the server. In this case, send the text “hello, world” to the client’s web browser via return.

The last line says to “listen” on port 8081, reporting any errors.

Now on your host computer, browse to 192.168.7.2:8081 an you should see.



Adding a template
Let’s improve our “hello, world” application, creating an HTML template and a CSS file for styling our page.

Templates
Create an HTML file that will be located in the “templates” sub-folder, we can use separate files with placeholders for spots where you want dynamic data to be inserted. So, we will create a file named index1.html, that will be saved on /templates.

OK, let’s create templates/index1.html:



(Sorry about using an image here, it kept formatting the HTML tags. Go to the git repo to get the code.)

Note: a style sheet (style.css) is also included. This will be populated later.

Observe that anything in double curly braces within the HTML template is interpreted as a variable that would be passed to it from the Python script via the render_template function. Now, let’s create a new Python script. We will name it app1.py: from flask import Flask, render_template import datetime app = Flask(__name__) @app.route("/") def hello: now = datetime.datetime.now timeString = now.strftime("%Y-%m-%d %H:%M") templateData = { 'title' : 'HELLO!', 'time': timeString }   return render_template('index1.html', **templateData) if __name__ == "__main__": app.run(host='0.0.0.0', port=8081, debug=True) Note that we create a formatted string("timeString") using the date and time from the "now" object, that has the current time stored on it.
 * 1) Code created by Matt Richardson
 * 2) for details, visit:  http://mattrichardson.com/Raspberry-Pi-Flask/inde...

Next important thing on the above code, is that we created a dictionary of variables (a set of keys, such as the title that is associated with values, such as HELLO!) to pass into the template. On “return”, we will return the index.html template to the web browser using the variables in the templateData dictionary.

Execute the Python script: bone$ .\app1.py Open any web browser and browse to 192.168.7.2:8081. You should see:



Note that the page’s content changes dynamically any time that you refresh it with the actual variable data passed by Python script. In our case, “title” is a fixed value, but “time” change it every second.

Adding Hardware
Wire a button to P9_11 and have the web page display the value of the button.

Let’s create a new Python script and named it app2.py.

import gpiod CHIP = '0'		# P9_11 offsets=[30] from flask import Flask, render_template app = Flask(__name__) chip = gpiod.Chip(CHIP) lines = chip.get_lines(offsets) lines.request(consumer="app2.py", type=gpiod.LINE_REQ_DIR_IN) @app.route("/") def index: # Read Button Status vals = lines.get_values templateData = { 'title' : 'GPIO input Status!', 'button' : vals, } 	return render_template('index2.html', **templateData) if __name__ == "__main__": app.run(host='0.0.0.0', port=8081, debug=True)
 * 1) !/usr/bin/env python3
 * 2) From: https://towardsdatascience.com/python-webserver-with-flask-and-raspberry-pi-398423cc6f5d
 * 1) Set button as an input

Look at what we are doing is defining the button on P9_11 as input, reading its value and storing it in vals. Inside the function index, we will pass that value to our web page through “button” that is part of our variable dictionary: templateData.

Let’s also create a new index2.html to show the GPIO status:



Run it with: bone$ ./app2.py Press the button and refresh the page.



Controlling GPIOs
Now that we know how to “read” GPIO Status, let’s change them. What we will do will control via the web page the LED. We have an LED connected to P9_14. Controlling remotely we will change its status from LOW to HIGH and vice-versa.

The python script Let’s create a new Python script and named it app3.py

import gpiod import sys from flask import Flask, render_template, request app = Flask(__name__) CHIP='1' setoffests=[18] # P9_14, red LED ledRed = "P9_14" ledRedSts = 0 chip = gpiod.Chip(CHIP) setlines = chip.get_lines(setoffests) setlines.request(consumer="app3.py", type=gpiod.LINE_REQ_DIR_OUT) setlines.set_values([0]) @app.route("/") def index: # Read Sensors Status ledRedSts = '0' templateData = { 'title' : 'GPIO output Status!', 'ledRed' : ledRedSts, } 	return render_template('index3.html', **templateData) @app.route("// ") def action(deviceName, action): if deviceName == 'ledRed': actuator = ledRed if action == "on": setlines.set_values([1]) ledRedSts = '1' if action == "off": setlines.set_values([0]) ledRedSts = '0' templateData = { 'ledRed' : ledRedSts, } 	return render_template('index3.html', **templateData) if __name__ == "__main__": app.run(host='0.0.0.0', port=8081, debug=True)
 * 1) !/usr/bin/env python3
 * 2) From: https://towardsdatascience.com/python-webserver-with-flask-and-raspberry-pi-398423cc6f5d
 * 1) import Adafruit_BBIO.GPIO as GPIO
 * 1) define LED GPIOs
 * 1) initialize GPIO status variable
 * 1) Define led pins as output
 * 1) turn led OFF

What we have new on above code is the new “route”: @app.route("// ") From the webpage, calls will be generated with the format: http://192.168.7.2:8081/ledRed/on or http://192.168.7.2:8081/ledRed/off For the above example, ledRed is the “deviceName” and on or off are examples of possible “action”. Those routes will be identified and properly “worked”. The main steps are: The integer variable ledRed is equivalent to P9_14. We store this value on variable “actuator” If “action = on” for example, we must use the command: GPIO.output(actuator, GPIO.HIGH)
 * Convert the string “ledRED”, for example, on its equivalent GPIO pin.
 * For each actuator, we will analyze the “action”, or “command” and act properly.
 * Update the status of each actuator
 * Update the variable library
 * Return the data to index.html

Let’s now create an index.html to show the GPIO status of each actuator and more important, create “buttons” to send the commands:



Run with: bone$ ./app3.py



Combining
The git repo has a forth example, ./app4.py that combines the previous two examples into one app.