Search icon
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Practical Python Programming for IoT

You're reading from  Practical Python Programming for IoT

Product type Book
Published in Nov 2020
Publisher Packt
ISBN-13 9781838982461
Pages 516 pages
Edition 1st Edition
Languages
Author (1):
Gary Smart Gary Smart

Table of Contents (20) Chapters

Preface Section 1: Programming with Python and the Raspberry Pi
Setting Up your Development Environment Getting Started with Python and IoT Networking with RESTful APIs and Web Sockets Using Flask Networking with MQTT, Python, and the Mosquitto MQTT Broker Section 2: Practical Electronics for Interacting with the Physical World
Connecting Your Raspberry Pi to the Physical World Electronics 101 for the Software Engineer Section 3: IoT Playground - Practical Examples to Interact with the Physical World
Turning Things On and Off Lights, Indicators, and Displaying Information Measuring Temperature, Humidity, and Light Levels Movement with Servos, Motors, and Steppers Measuring Distance and Detecting Movement Advanced IoT Programming Concepts - Threads, AsyncIO, and Event Loops IoT Visualization and Automation Platforms Tying It All Together - An IoT Christmas Tree Assessments Other Books You May Enjoy
Networking with RESTful APIs and Web Sockets Using Flask

In Chapter 2Getting Started with Python and IoT, we created a networked IoT application based on dweet.io where you controlled an LED connected to your Raspberry Pi over the internet. Our first IoT application was driven purely by making API requests.

In this chapter, we will turn our attention to alternative approaches to creating networked services in Python that can be accessed by both Python and non-Python clients. We will be looking at how to build a RESTful API server and a Web Socket server in Python and applying the electronic interfacing techniques we learned in the previous chapter to make them interact with our LED.

After completing this chapter, you will have an understanding of two different approaches to building servers with Python, complete with accompanying web pages that interact with the...

Technical requirements

To perform the exercises in this chapter, you will need the following:

  • Raspberry Pi 4 Model B
  • Raspbian OS Buster (with desktop and recommended software)
  • A minimum of Python version 3.5

These requirements are what the code examples in this book are based on. It's reasonable to expect that the code examples should work without modification on a Raspberry Pi 3 Model B or a different version of Raspbian OS as long as your Python version is 3.5 or higher.

You will find this chapter's source code in the chapter03 folder in the GitHub repository available here: https://github.com/PacktPublishing/Practical-Python-Programming-for-IoT.

You will need to execute the following commands in a Terminal to set up a virtual environment and install Python libraries required for the code in this chapter:

$ cd chapter03              # Change into this chapter's folder
$ python3 -m venv venv # Create Python Virtual Environment
$ source venv/bin...

Introducing the Flask microservices framework

Flask is a popular and mature microservices framework for Python that you can use for creating APIs, websites, and just about any other networked service you can imagine. Flask is certainly not the only option available for Python, even though its maturity, range of add-ons, and extensions plus the availability of quality documentation and tutorials make it an excellent choice.

We could conceivably do all of the following coding exercises in this chapter using just the core Flask framework; however, there are quality extensions that will make our life much easier. These extensions are Flask-RESTful for creating RESTful API services and Flask-SocketIO for building Web Socket services. 

The official API documentation for Flask-RESTful and Flask-SocketIO (or any Flask extension for that matter) generally assume existing knowledge of the core Flask framework, classes, and terminology. If you can't seem to find answers to your questions...

Creating a RESTful API service with Flask-RESTful

In this section, we will explore our first Python-based server, which will be a RESTful API server implemented using the Flask-RESTful framework for Python.

A RESTful API (REST stands for Representational State Transfer) is a software design pattern used for building web service APIs. It's a flexible pattern that is both technology- and protocol-independent. Its technology independence helps to promote interoperability between different technologies and systems, including different programming languages. And although it does promote protocol independence, it's frequently and almost always by default (or, at the least, assumed to be) built on top of the HTTP protocol used by web servers and web browsers.

RESTful APIs are the most common technique used today for building web services and APIs. In fact, it's so common that many people learn about them and use the design pattern without ever understanding what they are...

Running and testing the Python server

You will find the code in the chapter03/flask_api_server.py filePlease review this file before proceeding to get an overall idea about what it contains before you proceed.

We are running our Flask examples using Flask's built-in HTTP server. This is more than adequate for development purposes; however, it's not recommended for production usage. Consult the Flask documentation section titled Deployment Options for information on how to deploy a Flask application with production-quality web servers. You'll find a link in the Further reading section to the official Flask website and documentation.

To test the Python server perform the following steps:

  1. Run our RESTful API server with the following command:
(venv) $ python flask_api_server.py
... truncated ...
NFO:werkzeug: * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
... truncated ...

The second to last line in the preceding code block indicates that...

Understanding the server code

In this section, we will walk through our RESTful API server's source code and discuss the core parts to help you to understand how the server is coded and operates. Please keep in mind that we're about to cover many code-level artifacts that are specific to the Flask and Flask-RESTful frameworks, so don't get worried if, at first, some concepts do not make immediate sense.

Once you have an understanding of the foundations and an overall idea of how our sever works, you'll be in an excellent position to deepen your understanding of Flask and Flask-RESTful by consulting their respective websites (you will find links in the Further reading section). Furthermore, you will have a solid reference RESTful API server that you can rework and use as a starting point for your own future projects.

Please note that as we discuss the code, we will skip over any code and concepts that we covered in earlier chapters, such as GPIOZero.

We will start...

Imports

At the top of the source code file, we see the following imports:

import logging
from flask import Flask, request, render_template # (1)
from flask_restful import Resource, Api, reqparse, inputs # (2)
from gpiozero import PWMLED, Device # (3)
from gpiozero.pins.pigpio import PiGPIOFactory

The Flask-related imports we see on lines (1) and (2) are all of the classes and functions of Flask and Flask-RESTful that we will require in our server. You will notice on line (3), we're importing PWMLED not LED as we have done in previous chapters. In this example, we're going to change the brightness of our LED rather than just turning it on and off. We'll cover more about PWM and  PWMLED as we proceed with this chapter.

Next, in our source code, we start to work with Flask and the Flask-RESTful extension.

Flask and Flask-RESTful API instance variables

In the following, on line (4), we create an instance of our core Flask app and assign it to the app variable. The parameter is the name of our Flask application, and it's a common convention to use __name__ for the root Flask app (we only have a root Flask app in our example). Anytime we need to work with the core Flask framework, we will use the app variable:

app = Flask(__name__) # Core Flask app.            # (4)
api = Api(app) # Flask-RESTful extension wrapper # (5)

On line (5), we wrap the core Flask app with the Flask-RESTful extension and assign it to the api variable, and as we will see shortly, we use this variable anytime we are working with the Flask-RESTful extension. Following our app and api variables, we define additional global variables.

Global variables

The following global variables are used throughout our server. First, we have the GPIO pin and an led variable, which will later be assigned a GPIOZero PWMLED instance for controlling our LED: 

# Global variables
LED_GPIO_PIN = 21
led = None # PWMLED Instance. See init_led()
state = { # (6)
'level': 50 # % brightness of LED.
}

On line (6), we have a state dictionary structure that we will use to track the brightness level of our LED. We could have used a simple variable instead but have opted for a dictionary structure since it's a more versatile option because it will be marshaled into JSON to send back to a client, as we will see later on.

Next, we create and initialize our led instance.

The init_led() method

The init_led() method simply creates a GPIOZero PWMLED instance and assigns it to the global led variable that we saw previously: 

def init_led():
"""Create and initialize an PWMLED Object"""
global led
led = PWMLED(LED_GPIO_PIN)
led.value = state['level'] / 100 # (7)

We explicitly set the LED's brightness to match the value of our server's brightness state on line (7) to ensure the server's managed state and the LED are in sync when the server starts. We are dividing by 100 because led.value expects a float value in the range of 0-1, while our API will be using an integer in the range 0-100.

Next, we start to see the code that defines our server and its service endpoints, starting with the code that serves the web page we visited earlier.

Serving a web page

Starting on line (8), we use the Flask  @app.route() decorator to define a callback method that is invoked when the server receives an HTTP GET request from a client to the root URL /, that is, a request to http://localhost:5000:

# @app.route applies to the core Flask instance (app).
# Here we are serving a simple web page.
@app.route('/', methods=['GET']) # (8)
def index():
"""Make sure index_api_client.html is in the templates folder
relative to this Python file."""
return render_template('index_api_client.html',
pin=LED_GPIO_PIN) # (9)

On line (9), render_template('index_api_client.html', pin=LED_GPIO_PIN) is a Flask method use to return a templated page to the requesting client. The pin=LED_GPIO_PIN parameter is an example of how to pass a variable from Python to the HTML page template for rendering. We will...

The LEDControl class

In Flask-RESTful, API resources are modeled as Python classes that extend the Resource class, and on line (10) in the following snippet, we see the LEDControl(Resource) class defined that will contain the logic used to control our LED. Later on, we will see how we register this class with Flask-RESTful so that it responds to client requests:

class LEDControl(Resource):                                    # (10)
def __init__(self):
self.args_parser = reqparse.RequestParser() # (11)
self.args_parser.add_argument(
name='level', # Name of arguement
required=True, # Mandatory arguement
type=inputs.int_range(0, 100), # Allowed 0..100 # (12)
help='Set LED brightness level {error_msg}',
default=None)

On line (11), we create an instance of RequestParser() and assign it to the args_parser variable...

The get() class method

The get() class method handles HTTP GET requests for our LEDControl resource. It's what handled our URL request when we tested the API previously with the following command:

$ curl -X GET http://localhost:5000/led

get() simply returns, on line (13), the global state variable:

    def get(self):
""" Handles HTTP GET requests to return current LED state."""
return state # (13)

Flask-RESTful returns JSON responses to clients, and that's why we return the state variable. In Python, state is a dictionary structure that can be mapped directly into a JSON format. We saw the following JSON example previously when we make a GET request using curl:

{ "level": 50 }

This class-as-a-resource (for example, LEDControl) and method-to-HTTP-method mapping (for example, LEDControl.get()) is an example of how the Flask-RESTful extension makes RESTful API development...

The post() class method

The post() class method handles HTTP POST requests made to the LEDControl resource. It is this post() method that received and processed our curl POST request when we made the following request earlier when we tested our server:

curl -X POST -d '{"level": 100}' \
-H "Content-Type: application/json" \
http://localhost:5000/led

post() is more complex than our get() method. It is here where we change the brightness of our LED in response to a requesting client's input:

    def post(self):
"""Handles HTTP POST requests to set LED brightness level."""
global state # (14)

args = self.args_parser.parse_args() # (15)

# Set PWM duty cycle to adjust brightness level.
state['level'] = args.level # (16)
led.value = state['level'] / 100 ...

LEDController registration and starting the server

After calling the init_led() method to initiate and default out GPIOZero led instance, we then see how to register our LEDControl resource with api.add_resource() on line (19).  Here, we are mapping the URL endpoint, /led, with our controller.

Notice, in the code block on line (19), we have api.add_resource(...). The presence of the api variable means we are using and configuring the Flask-RESTful extension here.

Finally, on line (20), our server is started (in debug mode) and is ready to receive client requests. Notice that we use the core Flask instance in the app variable to start the server:

# Initialize Module.
init_led()
api.add_resource(LEDControl, '/led') # (19)

if __name__ == '__main__':
app.run(host="0.0.0.0", debug=True) # (20)

Well done! We've just covered the build of a simple, yet, functional RESTful API server in Python...

Introduction to PWM

In the proceeding example, we used PWMLED, not LED, from GPIOZero. PWMLED allows us to control the brightness of the LED using a technique known as Pulse Width Modulation, commonly abbreviated as PWM.

PWM is a technique used to create a lower the average voltage from a source signal, which can be a 3.3-volt GPIO pin. We will be covering PWM and GPIO pin voltages in detail in Chapter 6Electronics 101 for the Software Engineer.

For our current example, briefly (and somewhat oversimplified), PWM pulses the LED on and off really, really fast, and our eyes observe different pulse durations (that are creating different voltages) manifesting as different brightness levels of the LED. We changed this pulse duration (known as the duty-cycle) using the value property of a PWMLED instance, that is, led.value = state["level"] in LEDControl.post()In Chapter 5Connecting Your Raspberry Pi to the Physical World, we will explore...

Adding a RESTful API client web page

The web page we are about to discuss is the one you interacted with previously to change the brightness of your LED when you visited http://localhost:5000 in your web browser. A screenshot of the web page is shown in Figure 3.1.

As we proceed through this section, we will be learning how to build this basic web page using HTML and JavaScript. We will discover how to make the HTML range component interact with the Flask-RESTful API server that we created in the previous section, so that when we change the range control (that is, slide the slider), our LED's brightness also changes.

You will find the page's code in the chapter03/templates/index_api_client.html filePlease review this file before proceeding to get an overall idea about what it contains.

The templates folder is a special Flask folder where template files are kept. An HTML page is considered a template in the Flask ecosystem. You will also find a...

Understanding the client-side code

This section's code is JavaScript, and we will be using the jQuery JavaScript library. An understanding of basic JavaScript and jQuery will be essential to understanding the code examples that follow. If you are not familiar with jQuery, you can find learning resources at jQuery.com.

JavaScript imports

We see in the following, on line (1), that we import the jQuery library that is contained in the static folder:

<!-- chapter03/templates/index_api_client.html -->
<!DOCTYPE html>
<html>
<head>
<title>Flask Restful API Example</title>
<script src="/static/jquery.min.js"></script> <!--(1)-->
<script type="text/javascript">

Next, we will start to cover the JavaScript functions in the file.

The getState() function

The primary purpose of getState() is to retrieve the LED's current state from the server. It uses the JQuery get() method to make an HTTP GET request to our API server's /led resource. We saw, in the previous section, that the URL path, /led, is mapped to the LEDControl Python class, and because we're making a GET request, it's LEDControl.get() that will receive and handle our request:

// GET request to server to retrieve LED state.
function getState() {
$.get("/led", function(serverResponse, status) { // (2)
console.log(serverResponse)
updateControls(serverResponse) // (3)
});
}

The server's response is contained in the serverResponse parameter on line (2), which is passed to the updateControls() function on line (3) to update the web page controls. We'll cover this method shortly.

While getState...

The postUpdate() function

postUpdate() changes the LED's brightness by performing an HTTP POST to the server. This time, it's the LEDControl.post() method in our API server that handled the request:

// POST Request to server to set LED state.
function postUpdate(payload) { // (4)
$.post("/led", payload, function(serverResponse, status) {
console.log(serverResponse)
updateControls(serverResponse); // (5)
});
}

On line (4), it receives and parses (remember arg_parser from LEDControl) the data in the payload parameter. payload is a JavaScript object with a state child property. We'll see this object constructed later in the web page slider's change event handler.

For consistency, we also update the controls on line (5) even though, in our case, the serverResponse variable will contain the same level value as the payload parameter...

The updateControls() function

updateControls() changes the visual appearance of the web page controls. This function receives JSON input as the data parameter, which is in the form: {"level":50}. Starting on line (6) and using jQuery selectors, we update the slider control and text on the web page to reflect the new level value:

function updateControls(data) {
$("input[type=range].brightnessLevel").val(data.level); // (6)
$("#brightnessLevel").html(data.level);
}

Next, we'll see how we use JQuery to create an event handler that responds when we or another user changes to the web page's slider component.

Registering event handlers with jQuery

We are following jQuery best practice and using the jQuery document ready function (that is, $(document).ready(...)) to register the event handlers for our web page's slider control and initialize our web page elements:

    $(document).ready(function() {
// Event listener for Slider value changes.
$("input[type=range].brightnessLevel")
.on('input', function() { // (7)
brightness_level = $(this).val(); // (8)
payload = { "level": brightness_level } // (9)
postUpdate(payload);
});

// Initialize slider value form state on server.
getState() // (10)
});
</script>
</head>

On line (7), we register an event handler for the slider controls input event. This handler function will be called when a user interacts with the slider on...

The web page HTML

Previously in our Python server, we had the line render_template('index_rest_api.html', pin=LED_GPIO_PIN). It's the pin parameter in this method call that is rendered on our web page on line (11), represented by the template variable, {{pin}}:

<body>
<h1>Flask RESTful API Example</h1>
LED is connected to GPIO {{pin}}<br> <!--(11)-->
Brightness: <span id="brightnessLevel"></span>%<br>
<input type="range" min="0" max="100" <!--(12)-->
value="0" class="brightnessLevel">
</body>
</html>

Finally, we see, on line (12), our HTML slider component is restricted to the range of 0-100. As we saw previously, it's the call to getState() in the document ready handler that updates the slider's value attribute to match the brightness level stored on the server after the web...

Creating a Web Socket service with Flask-SocketIO

We will now implement our second Python-based server. Our overall outcome in this section will be similar to our RESTful API server and client that we created in the previous sectionthat is, we will be able to control our LED from a web browser. Our objective this time around, however, will be to create our program using a different technological approach using Web Sockets as our transport layer. 

Web Sockets are a full-duplex communication protocol and are a common technology choice where real-time client/server interaction is required. Web Sockets are a technology that—in my opinion and experience—is best learned through doing rather than reading, especially if you are new to server development. A deep discussion of Web Sockets is beyond the scope of this chapter; however, you'll find two links in the Further reading section covering the basics.

If you are new to Web Sockets, I highly...

Running and testing the Python server

Let's start by having a quick look at our Python Web Socket server code and running the server to see it in operation. This will give us a broad idea of the code and a first-hand demonstration of how the code works before we discuss it in detail.

You will find the Web Socket server's code in the chapter03/flask_ws_server.py file. Please review this file before proceeding.

When you have looked through the code, we will run our server. Here are the steps to follow:

  1. Run the Web Socket server with the following command:
(venv) $ python flask_ws_server.py
... truncated ...
NFO:werkzeug: * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
... truncated ...

The preceding output is similar to what we saw when we ran the RESTful API server; however, you can expect more output messages on your Terminal for this server. The additional output you will see has been truncated from the preceding example.

If flask_ws_server.py ...

Server code walkthrough

In this section, we will walk through our Python server's source code and discuss the core parts. Again, we'll skip over any code and concepts that we covered in earlier chapters. First, let's see what we're importing.

Imports

Near the top of the source file, we have the following imports:

from flask import Flask, request, render_template
from flask_socketio import SocketIO, send, emit # (1)

The main difference concerning our preceding imports compared to the RESTful API imports are on line (1), where we now import classes and functions from Flask-SocketIO.

Next, in our source code, we start to work with Flask and the Flask-SocketIO extension.

Flask and Flask-RESTful API instance variables

On line (2), we create an instance of SocketIO and the Flask-SocketIO extension and assign it to the socketio variable. It's this variable that we will use throughout our server to access and configure our Web Socket service: 

# Flask & Flask Restful Global Variables.
app = Flask(__name__) # Core Flask app.
socketio = SocketIO(app) # Flask-SocketIO extension wrapper # (2)

Following the creation of our SocketIO instance, we once again will server a web page from the default URL endpoint, /.

Serving a web page

Similarly to the RESTful API example, we configure the core Flask framework to serve a web page from the root URL using the @app.route() decorator:

@app.route('/', methods=['GET'])
def index():
"""Make sure index_web_sockets.html is in the templates folder
relative to this Python file."""
return render_template('index_web_sockets.html', # (3)
pin=LED_GPIO_PIN)

For our Web Socket server, this time, we are serving the HTML file, index_web_sockets.html, which we will be covering shortly in the next section, Adding a Web Socket client web page.

Next, we start to see the code that sets up and handles Web Socket event messages.

Connecting and disconnecting handlers

From this point in code forward, we start to see the major differences between the RESTful API server and this Web Socket server:

# Flask-SocketIO Callback Handlers
@socketio.on('connect') # (4)
def handle_connect():
logger.info("Client {} connected.".format(request.sid)) # (5)

# Send initializating data to newly connected client.
emit("led", state) # (6)

We see, on line (4), how to register a message or event handler using the Python decorator notation. The parameter to each @socketio.on(<event_name>) is the name of an event our server will listen for. The connect and disconnect events (in the following) are two reserved events. These handlers are called whenever a client connects to or disconnects from the server.

You will notice, on line (5), we are logging whenever a client connects, along with...

LED handler

On line (8) in the following, we have another message handlerthis time using a custom event named led. Also notice on line (9) that this event handler has a data parameter, whereas the connect and disconnect handlers in the preceding section had no parameters. The data parameter contains data sent from the client, and we see, on line (10), the level child property of data. All data form clients are strings, so here we validate the data and cast it to an integer on the following line. There is no equivalent built-in argument validating and parsing utility with Flask-SocketIO, so we must perform validation checks manually, as shown starting on line (11):

@socketio.on('led')                                 # (8)
def handle_state(data): # (9)
"""Handle 'led' messages to control the LED."""
global state
logger.info("Update LED from client {}: {} "
.format(request...

Starting the server

Finally, we start the server on line (14). This time, we are using the Flask-SocketIO instance, socketio, rather than the core Flask app instance, as we did for the RESTful API server:

if __name__ == '__main__':
socketio.run(app, host="0.0.0.0", debug=True) # (14)

Well done! That's our Web Socket server complete.

We have now seen how we can build a Web Socket server using Python together with Flask-SocketIO. While the overall outcome of our Web Socket server implementation controls our LED similarly to our RESTful API server, what we have learned is a different approach to achieving the same end result. However, in addition to this, we demonstrated a feature provided by a Web Socket approach, which is how we can keep multiple web pages in sync!

You will find links in the Further reading section to the Flask-SocketIO documentation so you can further your knowledge even more.

Now that we have seen the Python server implementation of...

Adding a Web Socket client web page

In this section, we will review the HTML web page we used to control our LED from our Web Socket server. An example of this page as seen in Figure 3.2.

We will learn how to use the Socket.IO JavaScript library with our web page so we can send and receive messages (when we work in a Web Socket environment, we tend to refer to data as messages) to and from our Python Flask-SocketIO Web Socket server. Plus, as we explore the JavaScript and Socket.IO-related code, we'll discover how our client-side JavaScript code relates to our Python server-side code.

You will find the following web page's code in the chapter03/templates/index_ws_client.html file. Please review the contents of this file to get a broad overview of what it contains.

When you have reviewed our HTML file, we will continue and discuss the important parts of this file.

Understanding the client-side code

Now that you had a look through the chapter03/templates/index_ws_client.html file, it's time to discuss how this file is constructed and what it does. We will start our code walk-through with the additional JavaScript import we need for Web Socket support.

Imports

Our Web Socket client requires the Socket.IO JavaScript library, and we see this imported on line (1). You will find a link to the Socket.IO JavaScript library in the Further reading section if you want to learn more about this library and how it works:

<!-- chapter03/templates/index_ws_client.html -->
<!DOCTYPE html>
<html>
<head>
<title>Flask Web Socket Example</title>
<script src="/static/jquery.min.js"></script>
<script src="/static/socket.io.js"></script> <!-- (1) -->
<script type="text/javascript">

Following the imports, we will see next the JavaScript that integrates with our Python Web Socket server.

Socket.IO connect and disconnect handlers

In the <script> section of the file, on line (2), we create an instance of the io() class from the socket.io JavaScript library and assign it to the socket variable:

    var socket = io();                         // (2)

socket.on('connect', function() { // (3)
console.log("Connected to Server");
$("#connected").html("Yes");
});

socket.on('disconnect', function() { // (4)
console.log("Disconnected from the Server");
$("#connected").html("No");
});

On line (3), with socket.on('connect', ...), we register a connect event listener. This handler is called every time our web page client connects successfully to our Python server. This is the client-side equivalent of the Python server's on connect handler we defined with @socketio.on('connect').

On...

The on LED handler

On line (5), we have our led message handler, which is responsible for updating the HTML controls with the current brightness level of our LED:

socket.on('led', function(dataFromServer) {         // (5)
console.log(dataFromServer)
if (dataFromServer.level !== undefined) {
$("input[type=range].brightnessLevel").val(dataFromServer.level);
$("#brightnessLevel").html(dataFromServer.level);
}
});

If you review the Python server's @socketio.on('connect') handler, you will notice it contains the line emit("led", state). When a new client connects to the server, it emits back to the connecting client a message containing the current state of our LED. It's the JavaScript socket.on('led', ...) part on line (5) that consumes this message.

Next, we have the jQuery document ready callback.

The document ready function

The jQuery document ready callback is where we set up the event handler for the HTML slider:

        $(document).ready(function(){
// Event listener for Slider value changes.
$("input[type=range].brightnessLevel")
.on('input', function(){

level = $(this).val();
payload = {"level": level};
socket.emit('led', payload); // (6)
});
});
</script>
</head>

On line (6), we see how to emit a message in JavaScript. The call to socket.emit('led', payload) emits a message to the Python server with the brightness level we want to apply to our LED.

It's the Python @socketio.on('led') handler that receives this message and changes the LED's brightness.

If you review this Python handler, you will notice the line: emit("led", state, broadcast=True). This...

The web page HTML

The only difference to the RESTful API web page is the inclusion on line (7) of a message to indicate whether we have a connection to the Python server:

<body>
<h1>Flask Web Socket Example</h1>
LED is connected to GPIO {{pin}}<br>
Connected to server: <span id="connected">No</span> <!-- (7) -->
<br><br>
Brightness <span id="brightnessLevel"></span>:<br>
<input type="range" min="0" max="100"
value="0" class="brightnessLevel">
</body>
</html>

Congratulations! That's two Python servers and web page clients using two different transport layers you have just completed.

We have seen how to implement the same project to control an LED's brightness using both a RESTful API-based approach and a Web Sockets-based approach. These are two very common options for implementing web services and integrating...

Comparing the RESTful API and Web Socket servers

A RESTful-based API is conceptually similar to design, develop, and test, and are more commonly found across the internet where a one-way request/response data exchange is needed.

Here are some defining characteristics of this approach:

  • The communication protocol is built around HTTP methods with GET, POST, PUT, and DELETE being the most common.
  • The protocol is half-duplex in the form of request-response. The client makes a request and the server responds. The server cannot initiate a request to a client.
  • We have options including curl on the command line and GUI tools such as Postman to test and development RESTful APIs.
  • We can use a common web browser to test HTTP GET API endpoints
  • In Python, we can use the Flask-RESTful extension to help us to build a RESTful API server. We model endpoints as Python classes that have class methods such as .get() and .post() that match HTTP request methods.
  • For a web page client, we can use a library...

Summary

In this chapter, we have covered in two common methods for building networked services with PythonRESTful APIs and Web Socket services. We built these services in Python using the Flask microservices framework and the Flask-RESTful and Flask-SocketIO extensions. After we created each server, we also created web page clients. We learned how to use the JavaScript jQuery library to make a RESTful API request and the Socket.IO JavaScript library to perform Web Socket messaging and subscribing.

With this new knowledge, you now have the foundations and a simple end-to-end client-server framework built using Python, HTML, JavaScript, and jQuery that you can expand on and experiment with to create grander IoT applications. For example, as you proceed through Part 3 of this book, IoT Playground, and learn about different electronic sensors and actuators, you'll be in a position to expand and build upon this chapter's examples using different electronic...

Questions

As we conclude, here is a list of questions for you to test your knowledge regarding this chapter's material. You will find the answers in the Assessments section of the book:

  1. What feature of the Flask-RESTful extension can we use to help to validate a client's input data?
  2. What communication protocol can be used to provide real-time full-duplex communication between a client and a server?
  3. How do we perform request data validation with Flask-SocketIO?
  4. What is the Flask templates folder?
  5. When using jQuery, where should we create component event listeners and initialize our web page content?
  6. What command-line tool can be used to make requests to a RESTful API service?
  7. What happens to the physical LED when we change the value property of a PWMLED instance?

Further reading

We have mentioned the word "RESTful" a lot in this chapter, without any deep discussion of what it means exactly. If you want all of the details, a great introductory tutorial can be found on SitePoint.com:

Our RESTful API example barely even touches the basics of Flask and Flask-RESTful but provides a working example that you can build upon. I encourage you to read at a minimum the Flask Quick Start Guide, followed by the Flask RESTful Quick Start Guide to get a good grounding and understanding of these two frameworks:

As mentioned during the chapter in the section titled Introducing the Flask microservices framework, if you experience difficulties with Flask-RESTful and cannot find answers in its...

lock icon The rest of the chapter is locked
You have been reading a chapter from
Practical Python Programming for IoT
Published in: Nov 2020 Publisher: Packt ISBN-13: 9781838982461
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime}