Reader small image

You're reading from  Practical Python Programming for IoT

Product typeBook
Published inNov 2020
Reading LevelIntermediate
PublisherPackt
ISBN-139781838982461
Edition1st Edition
Languages
Right arrow
Getting Started with Python and IoT

In Chapter 1Setting Up Your Development Environment, we went through the essentials of the Python ecosystem, virtual environments, and package management and set up your Raspberry Pi for development and GPIO interfacing. In this chapter, we will begin our journey in Python and IoT.

What we cover in this chapter will lay the foundations and give us a working point of reference for the more advanced content that we'll cover in later chapters. We will learn to create a simple electrical circuit with a button, resistor, and LED (or light-emitting diode) and explore alternative ways to interact with the button and LED with Python. We will then proceed to create and discuss a complete end-to-end IoT program to control the LED over the internet and complete this chapter by looking at ways that you can extend the program.

In this...

Technical requirements

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

  • Raspberry Pi 4 Model B. A 1 GB RAM version will be adequate to run our examples. If you are working directly on your Raspberry Pi versus a Secure Shell (SSH) session; for example, more RAM is recommended to improve the Raspbian Desktop experience and responsiveness.
  • You will need Raspbian OS Buster (with desktop and recommended software).
  • You will need 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, Raspberry Pi Zero W, 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 chapter02 folder in the GitHub repository available at the following URL: https://github.com/PacktPublishing...

Creating a breadboard prototype circuit

Throughout this book, we will be building many electrical circuits, and we will do this using an electronic breadboard. In the initial chapters, I will present many of the circuits with both a breadboard layout similar to that illustrated toward the end of this section in Figure 2.7 and with a schematic diagram as shown in Figure 2.8.

As we progress through this book and you gain more experience building breadboard circuits, I will cease with the breadboard layouts for the simpler circuits; however, I will still present them for the more complex circuits so you have something to compare your builds against.

Please note that the proceeding circuit examples and discussions are only brief. At this stage of this book, we intend to build a simple electronic circuit that will be the basis for our Python examples in this chapter and Chapter 3, Networking with RESTful APIs and Web Sockets Using Flask, and Chapter...

Understanding the breadboard

An electronic breadboard, as illustrated in Figure 2.1is a prototyping board that helps you to electrically connect components and wires quickly and easily. In this section, we will discuss the general properties of a breadboard in preparation for connecting components and wires together in the following sections:

Figure 2.1 – Breadboard

Breadboards come in many different sizes, and our illustrated breadboard is a half-sized breadboard. Irrespective of their size, however, their basic layout and electrical connectivity are similar—with one small exception that I'll mention later.

Real breadboards may, or may not, have the row and column numbers markings on them. They have been included in the illustration to assist with the following discussion and explanations.

The holes in the breadboard are where you place electrical components and wires to electrically connect them. The holes are electrically connected in the following ways...

Positioning and connecting the push button

We are using a simple on/off button, also commonly known as an Single Pole, Single Throw (SPST) momentary switch. An example is shown in Figure 2.2:

Figure 2.2 A push button and schematic symbol

On the left-hand side of Figure 2.2 is a photograph of a momentary push button, while the right-hand side shows the schematic symbol for a momentary push button. We'll see this symbol and discuss schematic diagrams where these types of symbols appear in the next section.

Push buttons come in many shapes and sizes; however, their general operation is the same. This specific push button pictured on the left-hand side is known as a tactile push button. They are small and well suited for use with a breadboard.

Figure 2.3 illustrates the push button connection we need to create on our breadboard. Please refer to this as you follow the forthcoming steps:

Figure 2.3 – Connecting...

Positioning and connecting the LED

An LED is a small, yet bright, light made of a tiny crystal that emits a color when electricity is connected to it.

A typical LED is shown in  Figure 2.4. The left-hand side of the diagram shows a physical representation of a LED, while the right-hand side shows the schematic symbol for a LED:

 Figure 2.4 – LED and schematic symbol

LEDs need to be connected the correct way around into a circuit, otherwise, they will not work. If you look closely at your LED, you will notice a flat side on the LED casing. The leg on this side is the cathode, which connects to the negative or ground side of a power source. The cathode leg will also be the shorter of the LED's legs. The other leg is known as the anode and connects to the positive side of a power source. If you examine the LED symbol, you will notice that the cathode side of the LED has a line drawn across the tip of the triangle...

Positioning and connecting the resistor

A resistor is an electronic component used to limit (that is, resist) current flow and divide voltage and they are a very common electrical component.

Shown in Figure 2.6 are a physical resistor (left-hand side) and two schematic symbols (right-hand side). There is no practical difference between the schematic symbols pictured. They represent different documentation standards, and you will find that the author of a schematic diagram will choose and stick with one type of symbol. We'll be using the zig-zag symbol throughout this book:

Figure 2.6 Resistor and schematic symbols

Resistors come in many shapes, sizes, and colors. As a general guide, their physical shape and size relate to their physical properties and capabilities, while the color of their casing is usually insignificant, at least as far as their properties are concerned. The colored bands on a resistor, however, are very significant as they identify...

Reading an electronic schematic diagram

In the last section, we built our first circuit on a breadboard by following a series of illustrated steps. In this section, we will learn about schematic diagrams, which is a formal way of documenting and describing an electrical circuit. These are the diagrams you find in electronic texts and datasheets.

We will learn how to read a simple schematic diagram and how it relates back to the breadboard layout we just created. Understanding how the two relate, and especially being able to create a breadboard layout from a schematic diagram, is an important skill you will need to develop as you continue your electronics and IoT journey.

The electronic circuits and schematic diagrams we will be seeing and working with throughout this book will be relatively simple as far as schematic diagrams are concerned. We will address important concepts and component symbols as we encounter them on a case-by-case basis. For our...

Reading the push button schematic connection

I've combined the breadboard layout and schematic diagram (with a few additional labels) as follows:

Figure 2.9 Combined breadboard and schematic diagram, part 1 of 2

Here is how to read the pushbutton connection. The following step numbers match the numbered black circles in Figure 2.9:

  1. Start at the breadboard with the wire labeled wire 1. If we look at the ends of this wire, we see that one end is connected to GPIO 23 on the Raspberry Pi, while the other end (at hole A10connects to a row shared by the push button.

  2. Looking at the schematic diagram, this breadboard connection is depicted diagrammatically by the line labeled wire 1. You will notice one end of the line is labeled GPIO23, while the other end leads into one side of the button symbol.

The color of a wire's casing has no inherent meaning. The color is simply a visual aid to help to distinguish different wires and...

Reading the LED and resistor schematic connection

Continuing from the previous section, where we learned how to read and understand the push button part of the schematic diagram, next we complete our explanation by covering the LED and resistor connections, as shown here:

Figure 2.10 – Combined breadboard and schematic diagram, part 2 of 2

Here is how to read the LED and resistor connection. The following step numbers match the numbered black circles in Figure 2.10:

  1. Start at the wire labeled wire 2 on the breadboard. This wire connects GPIO 21 on the Raspberry Pi into the row shared by one end of the resistor (hole A25).
  2. The wire 2 connection is depicted by the line also labeled wire 2 on the schematic diagram.
  3. On the breadboard, the other end of the resistor is connected to the anode leg of the LED (hole E15). Remember, the resistor and anode leg of the LED are electrically connected because they share the same row of holes in the same bank on the breadboard...

Introducing ground connections and symbols

Electrical circuits all require a common electrical point of reference, and we call this point ground. This is why we see the push button and LED sharing a common connection on both the breadboard and schematic diagram (as a reminder, refer to Figure 2.10.

For the simple circuits presented throughout this book and when working with your Raspberry Pi's GPIO pins, it will be practical to consider the terms negative and ground as interchangeable. This is because the negative side of a power source will be our common point of electrical reference (and yes, GPIO pins are a source of power, which we will explore more in Chapter 6, Electronics 101 for the Software Engineer).

As mentioned previously in the Reading the push button schematic connection section, in step 4, we diagrammed the ground point using an arrow symbol. Our ground symbol (made out of line segments) is one common variation...

Exploring two ways to flash an LED in Python

In this section, we will investigate two alternative GPIO libraries and ways to make an LED flash in Python, including the following:

  • The GPIOZero library: An entry-level GPIO library
  • The PiGPIO library: An advanced GPIO library

As we learn to use these two libraries, we will see how they approach GPIO control differently and discover their relative strengths and weaknesses.

After completing this section (and the following section, Exploring two ways to integrate a push button in Python), you will have explored and compared two very different approaches to GPIO control—the high-level (using GPIOZero) and a lower-level (using PiGPIO)and have a good introductory grasp of when and how you would choose between the alternative when building an electronic interfacing program.

Let's start our practical exercises by making the LED blink using GPIOZero.

Blinking with GPIOZero

We are now ready to investigate our first blinking method using the GPIOZero library. You will find the code we are about to cover in the chapter02/led_gpiozero.py file. Please review this file before proceeding.

In the Further reading section, you will find relevant links to the GPIOZero API documentation for the specific features of this library that we use in this section.

We will start by running our example code.

Run the program using the following command, remembering that you need to be in the activated virtual environment (if you need a refresher on how to activate a Python virtual environment, see Chapter 1Setting Up Your Development Environment):

(venv) $ python led_gpiozero.py

If the LED is connected correctly, it should blink.

If you receive an error about PiGPIO when you run the program, make sure you have enabled the pigpio daemon as outlined in Chapter 1, Setting Up Your Development Environment. We'll...

Imports

We will start our code exploration by looking at the external libraries we are importing in our Python program. They appear near the top of the source file, as shown here:

from gpiozero import Device, LED                # (1)
from gpiozero.pins.pigpio import PiGPIOFactory # (2)
from time import sleep

 The imports of interest are the following:

  • At line (1), we import the Device and LED classes from the GPIOZero package.
  • At line (2), we are importing a GPIOZero Pin Factory. This is used together with the Device class, which we'll see next.

Next, we see how to set the GPIOZero Pin Factory implementation.

Pin Factory configuration

A Pin Factory is used in GPIOZero specify which concrete GPIO library GPIOZero will use to perform the actual GPIO work. We will discuss Pin Factories in more detail when we compare the GPIOZero and PiGPIO examples later in this chapter in the Comparing the GPIOZero and PiGPIO examples section:

Device.pin_factory = PiGPIOFactory()  # (3)

On line (3), we are telling GPIOZero to use PiGPIO as its Pin Factory using the Device and PiGPIOFactory imports

Now that we've seen how a Pin Factory is set up, let's look at the code that makes our LED blink.

Blinking the LED

Here, we see the LED class at line (4) in the following is created and assigned to the led variable. The parameter to LED is the GPIO pin that the physical LED is connected to, as per the breadboard in Figure 2.1:

GPIO_PIN = 21 
led = LED(GPIO_PIN) # (4)
led.blink(background=False) # (5)

On line (5), we start the LED blinking. The background=False parameter to blink() is needed to run the LED on the main thread so the program does not exit (an alternative of background=True would be to use signal.pause(). We'll see an example of this in the next section).

GPIOZero makes it very easy to interface with common electronic components such as an LED. Next, we will perform the same exercise, only this time using the PiGPIO library.

Blinking with PiGPIO

Now that we have seen how to blink our LED using the GPIOZero library, let's look at an alternative method using the PiGPIO library.

The code we are about to walk through is contained in the chapter02/led_pigpio.py fileTerminate the previous example if it is still running, and run led_pigpio.py. The LED should blink again.

In the Further reading section, you will find relevant links to the PiGPIO API documentation for the specific features of this library that we are using in this section.

Let's walk through the PiGPIO version of our LED blinking code.

Imports

Starting at the top of the file, we have the import section of the source file:

import pigpio           # (1)
from time import sleep

This time around, on line (1), we only need to import the PiGPIO module.

Next, we will see how to configure PiGPIO and set the I/O mode on the GPIO pin that is connected to our LED.

PiGPIO and pin configuration

Let's look at the code that configures PiGPIO and the LED's GPIO pin:

GPIO_PIN = 21
pi = pigpio.pi() # (2)
pi.set_mode(GPIO_PIN, pigpio.OUTPUT) # (3)

We create an instance of PiGPIO on line (2) and assign it to the pi variable. We use this variable to interact with the PiGPIO library from this point forward in the code.

On line (3), we configure GPIO pin 21 to be an output pin. Configuring a pin as output means we want to use that pin to control something connected to it from our Python code. In this example, we want to control the LED. Later in this chapter, we'll see an example of an input pin used to respond to button presses.

Now that we have imported our required libraries and configured PiGPIO and the out GPIO pin, let's now see how we are making the LED blink.

Blinking the LED

Finally, we make our LED blink:

while True:
pi.write(GPIO_PIN, 1) # 1 = High = On # (4)
sleep(1) # 1 second
pi.write(GPIO_PIN, 0) # 0 = Low = Off # (5)
sleep(1) # 1 second

We achieve the blinking with PiGPIO using a while loop. As the loop executes, we are toggling GPIO pin 21— our output pin—on and off (lines (4) and (5)), with a short sleep() function in between, hence making the LED appear to blink.

Next, we will compare our two libraries and their different approaches to blinking the LED.

Comparing the GPIOZero and PiGPIO examples

If you look at the code for the GPIOZero example, it's pretty obvious we're making an LED blinkit's pretty explicit in the code. But what about the PiGPIO example? There is no mention of LEDs or blinking. In truth, it could be doing anythingit's just we know an LED is connected to GPIO 21.

Our two blinking examples reveal important aspects of GPIOZero and PiGPIO:

  • GPIOZero is a higher-level wrapper library. On the surface, it abstracts common electronic components such as LEDs into simple-to-use classes while, underneath, it is delegating the actual interfacing work to a concrete GPIO library.

  • PiGPIO is a lower-level GPIO library where you work with, control, and access GPIO pins directly.

The "zero" in GPIOZero refers to a naming convention for zero boilerplate code libraries where all of the complex internals are abstracted away to make it easier for beginners to get started...

Exploring two ways to integrate a push button in Python

In the previous section, we explored two different approaches to making our LED blinkone using the GPIOZero library and the other with the PiGPIO library. In this section, we will integrate the push button from the circuit in Figure 2.1 with Python and see how we can integrate the button using both the GPIOZero and PiGPIO libraries.

We will start by making our LED turn on and off with a button that is integrated using the GPIOZero library.

Responding to a button press with GPIOZero

The code we are about to cover is included in the chapter02/button_gpiozero.py filePlease review and run this file. The LED should turn on and off as you press the button. As per the circuit in Figure 2.1, the LED is still connected to GPIO 21, while our button is connected to GPIO 23.

As mentioned previously in the Creating a breadboard circuit section, if your button has four legs (two sets will be electrically joined) and your circuit does not work, try rotating the button in the breadboard 90 degrees.

Let's walk through the significant parts of the code, noting that we are skipping sections of code that we've already covered.

Imports

Starting at the top of the source file, you will find the section of code where we import external libraries, as shown here:

from gpiozero import Device, LED, Button         # (1)
from gpiozero.pins.pigpio import PiGPIOFactory
import signal # (2)

For this example, we have also imported the GPIOZero Button class (1) and the Python signal module (2).

Now that you have seen that we are importing the Button class, let's look at the handler function that will be called when the button is pressed.

Button pressed handler

We are using a callback handler to respond to button presses, defined in the pressed() function:

def pressed():
led.toggle() # (3)
state = 'on' if led.value == 1 else 'off' # (4)
print("Button pressed: LED is " + state) # (5)

On line (3), our LED is turned on and off each time pressed() is invoked using the toggle() method of led. On line (4), we query the value property of led to determine whether the LED is on (value == 1) or off (value == 0) and store it in the state variable, which we print to the Terminal on line (5).

You can also control the LED with the led.on(), led.off(), and led.blink() methods. You can also directly set the LED on/off state by setting led.value, for example, led.value = 1 will turn the LED on.

Let's continue and see how to create and configure a Button class instance and register the pressed() function so it is called when...

Button configuration

Following are the lines used to configure the push button. On line (6), the class we use is Button. In GPIOZero, we use a Button class for any input device that can be either on or off, such as buttons and switches:

button = Button(BUTTON_GPIO_PIN, 
pull_up=True, bounce_time=0.1) # (6)

button.when_pressed = pressed # (7)

On line (7), we register the pressed() callback handler with our button instance.

Here are the meanings of the parameters to the Button constructor on line (6):

  • The first parameter is the button's GPIO pin (BUTTON_GPIO_PIN == 23).
  • The second parameter, pull_up=Trueenables an internal pull-up resistor for GPIO 23. Pull-up and pull-down resistors are an important concept in digital electronics. We're are going to skip over this concept for now because we will be covering the importance and use of pull-up and pull-down resistors in greater detail in Chapter 6, Electronics...

Preventing the main thread from terminating

It's common to see the use of signal.pause() or an equivalent construct in GPIO examples and programs: 

signal.pause() # Stops program from exiting.  # (8)

Line (8) prevents the main program thread from reaching its natural end, which under normal circumstances is where the program terminates.

Forgetting to add signal.pause() to the end of a GPIO-interfacing Python program is a common and often confusing mistake when starting out. If your program exits immediately after it's started, try adding signal.pause() at the end of your program as a first step.

We didn't need signal.pause() with our previous LED flashing examples. Here is why:

  • Our GPIOZero example (chapter02/led_gpiozero.py) used background=False in the LED constructor. This prevented our program from exiting by keeping the LED's thread in the foreground.
  • In the PiGPIO example (chapter02/led_pigpio.py), it's the while loop that...

Responding to a button press with PiGPIO

We will now replicate the same functionality as our previous GPIOZero example to turn our LED on and off with a button press, only this time using the PiGPIO library. The code for our PiGPIO example can be found in the chapter02/button_pigpio.py file. Please review and run this file now, and confirm that the LED responds to your button presses.

Let's unravel the interesting parts of the code, starting with the GPIO pin configuration for the push button (again, noting that we're skipping sections of code that we've already covered).

Button pin configuration

Starting on line (1), we configure GPIO pin 23 (BUTTON_GPIO_PIN == 23) as an input pin:

pi.set_mode(BUTTON_GPIO_PIN, pigpio.INPUT)           # (1)
pi.set_pull_up_down(BUTTON_GPIO_PIN, pigpio.PUD_UP) # (2)
pi.set_glitch_filter(BUTTON_GPIO_PIN, 10000) # (3)

Next, on line (2), we enable an internal pull-up resistor for pin 23. In PiGPIO, we debounce the push button on line (3) using the pi.set_glitch_filter() method. This method takes the parameter in milliseconds.

Notice, in PiGPIO, we needed to configure each property for our button (pin input mode, a pull-up resistor, and debouncing) as a discrete method call, whereas in the previous GPIOZero example this all occurred on a single line when we created an instance of the GPIOZero LED class.

Button pressed handler

Our button callback handler is defined at starting on line (4) and is more involved than the previous GPIOZero handler:

def pressed(gpio_pin, level, tick):                         # (4)
# Get current pin state for LED.
led_state = pi.read(LED_GPIO_PIN) # (5)

if led_state == 1: # (6)
# LED is on, so turn it off.
pi.write(LED_GPIO_PIN, 0) # 0 = Pin Low = Led Off
print("Button pressed: Led is off")
else: # 0
# LED is off, so turn it on.
pi.write(LED_GPIO_PIN, 1) # 1 = Pin High = Led On
print("Button pressed: Led is on")

# Register button handler.
pi.callback(BUTTON_GPIO_PIN, pigpio.FALLING_EDGE, pressed) # (7)

Notice the signature of pressed(gpio_pin, level, tick). Our previous GPIOZero version has no parameters while PiGPIO has three mandatory parameters. Our simple one-button example does not use these parameters; however, for completeness...

Creating your first IoT program

We are about to create a Python program to integrate with a service called dweet.io. This is how their website describes the service: "it's like Twitter for social machines."

We will create simple dweets, which are the dweet.io equivalent of a tweet, by pasting a URL into a web browser.

Our program will monitor and receive our dweets by polling a dweet.io RESTful API endpoint for data. As data is received, it will be parsed to find an instruction specifying whether our LED should be turned on or off or made to blink. Based on this instruction, our LED state will be changed using the GPIOZero library. We'll have a look at data format received from dweet.io when we discuss the program's code in a subsequent section titled Understanding the server code.

We're using the free public dweet.io service where all information is publicly accessible, so do not publish any sensitive data. There is...

Running and testing the Python server

In this section, we will run and interact with a Python server program that will let us control our LED from a web browser by copying and pasting links. Once we have used the program to control our LED, we'll then delve into the mechanics of the code and how it works in the next section.

Here are the steps to follow:

  1. Run the chapter02/dweet_led.py program. You should see output similar to the following:
(venv) $ python dweet_led.py
INFO:main:Created new thing name a8e38712 # (1)
LED Control URLs - Try them in your web browser:
On : https://dweet.io/dweet/for/a8e38712?state=on # (2)
Off : https://dweet.io/dweet/for/a8e38712?state=off
Blink : https://dweet.io/dweet/for/a8e38712?state=blink

INFO:main:LED off
Waiting for dweets. Press Control+C to exit.

On line (1), the program has created a unique name for our thing to use with dweet.io. You'll notice this name in the URLs starting on...

Understanding the server code

In this section, we will step through the major parts of the dweet_led.py program and discover how it works, starting with the imports.

Imports

First, at the start of the source code file, we see the Python imports:

...truncated...
import requests # (1)

There is one specific import I want to draw your attention to. On line (1), we are importing the request module (this was installed earlier in this chapter when you ran pip install -r requirements.txt). requests is a high-level library for making HTTP requests in Python. Our program uses this module to communicate with the dweet.io APIs, which we'll see shortly.

Now that we understand that we are importing and will later use the requests library, let's cover the global variables used in our program.

Variable definitions

Next, we define several global variables. For now, review the following comments for their purposes. You'll see them being used as we progress through the code:

LED_GPIO_PIN = 21                  # LED GPIO Pin
THING_NAME_FILE = 'thing_name.txt' # Thing name file
URL = 'https://dweet.io' # Dweet.io service API
last_led_state = None # "on", "off", "blinking"
thing_name = None # Thing name
led = None # GPIOZero LED instance

As you read through the master source file, following these variable definitions, you'll also notice that we are using the Python logging system instead of print() statements:

logging.basicConfig(level=logging.WARNING)
logger = logging.getLogger('main') # Logger for this module
logger.setLevel(logging.INFO) # Debugging for this file. # (2)

If you need to turn on debugging for the program to diagnose a problem or to see...

The resolve_thing_name() method

The resolve_thing_name() method is responsible for loading or creating a unique name for our thing for use with dweet.io.

Our intention when using this method is to always reuse a name so that our dweet URLs for controlling our LED remain the same between the program restarts:

def resolve_thing_name(thing_file):
"""Get existing, or create a new thing name"""
if os.path.exists(thing_file): # (3)
with open(thing_file, 'r') as file_handle:
name = file_handle.read()
logger.info('Thing name ' + name +
' loaded from ' + thing_file)
return name.strip()
else:
name = str(uuid1())[:8] # (4)
logger.info('Created new thing name ' + name)

with open(thing_file, 'w') as f: # (5)
f.write(name)

return name

On line...

The get_lastest_dweet() method

get_lastest_dweet() queries the dweet.io service to retrieve the latest dweet (if any) made for our thing. Following is an example of the JSON response we expect to receive. It is the content.state property on line (1) that we are ultimately interested in:

{
this: "succeeded",
by: "getting",
the: "dweets",
with: [
{
thing: "a8e38712-9886-11e9-a545-68a3c4974cd4",
created: "2019-09-16T05:16:59.676Z",
content: {
state: "on" # (1)
}
}
]
}

Looking at the following code, we see, on line (6), the creation of the resource URL used to query the dweet.io service. A call to this URL will return us a JSON similar to that shown in the preceding. You will find a link in the Further reading section to the complete dweet.io API reference.

Next, on line (7), the requests module...

The poll_dweets_forever() method

poll_dweets_forever() is a long-running function that periodically calls on line (11) the get_lastest_dweet() method we just covered. When a dweet is available, it is handled on line (12) by process_dweet(), which we will discuss shortly:

def poll_dweets_forever(delay_secs=2):
"""Poll dweet.io for dweets about our thing."""
while True:
dweet = get_last_dweet() # (11)
if dweet is not None:
process_dweet(dweet) # (12)

sleep(delay_secs) # (13)

We sleep for a default delay of 2 seconds on line (13) before continuing the loop. Practically, this means there will be up to an approximate 2-second delay between using one of the dweeting URLs to request a LED state change and the LED altering its state.

At this point in the master source file, you will come across a function named stream_dweets_forever...

The process_dweet() method

As we saw previously when poll_dweets_forever() (similar to stream_dweets_forever()) gets a dweet, it parses out the content property from the dweet's JSON. This is then passed to process_dweet() for handling, where we extract the state child property from the content property:

def process_dweet(dweet):
"""Inspect the dweet and set LED state accordingly"""
global last_led_state

if not 'state' in dweet:
return

led_state = dweet['state'] # (14)

if led_state == last_led_state: # (15)
return; # LED is already in requested state.

On line (15) (and (17) in the subsequent code block), we test for and maintain the LED's last known state and avoid interacting with the LED if it's already in the requested state. This will avoid potential visual glitching of the LED that can occur if it's repeatedly put into...

The main program entry point

At the end of the source file, we have the following code:

# Main entry point
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal_handler) # Capture CTRL + C
print_instructions() # (18)

# Initialize LED from last dweet.
latest_dweet = get_latest_dweet() # (19)
if (latest_dweet):
process_dweet(latest_dweet)

print('Waiting for dweets. Press Control+C to exit.')

#Only use one of the following.
#stream_dweets_forever() # Stream dweets real-time.
poll_dweets_forever() # Get dweets by polling. # (20)

On line (8), print_instructions()  is responsible for printing the sweet URLs to the Terminal, while on line (19), we see a call to get_latest_dweet(). This call initializes our LED to the last dweeted state when the program starts. Finally, on line (20), we start polling the dweet.io service to access the latest dweets...

Extending your IoT program

The following two files in the chapter02 folder complement what we have covered in this chapter by combining the concepts we have learned. As the overall code and approach are similar to what we have already covered, we will not go through the code in detail:

  • dweet_button.py provides an implementation showing how to use a push button to create a dweet with the dweet.io service. This will let you change your LED state with the press of a button.
  • pigpio_led_class.py provides a code-level example of how a low-level library like PiGPIO relates to a high-level library like GPIOZero.

We'll start by discussing dweet_button.py.

Implementing a dweeting button

This program in dweet_button.py integrates the GPIOZero push button example with dweet.io. Earlier in this chapter, in the section titled Running and testing the Python server, we copied and pasted URLs into a web browser to control our LED.

When you run dweet_button.pyeach time you press the button, this program cycles through the dweet.io URLs to change the LED's state. To configure this program, find and update the following line with the thing name you are using with dweet_led.py:

thing_name = '**** ADD YOUR THING NAME HERE ****'

Remember, that you'll also need the dweet_led.py program to be running in a Terminal, otherwise, the LED will not respond to your button presses.

Next, we see how to mimic GPIOZero using PiGPIO and a Python class.

PiGPIO LED as a class

In the pigpio_led_class.py file, we have a Python class that is a re-engineering of the PiGPIO LED example to wrap it as a class that mimics the GPIOZero LED class. It demonstrates the basic principle of how GPIOZero abstracts away lower-level GPIO complexity. This re-engineered class can be used as a drop-in replacement for the GPIOZero LED examples in this chapter, as shown here. See the header comments in pigpio_led_class.py for more information:

""" chapter02/dweet_led.py """
...
# from gpiozero import LED # Comment out import
from pigpio_led_class import PiGPIOLED as LED # Add new import

I hope you find these two bonus files interesting, and that by exploring the PiGPIO LED as a class example, you can better appreciate how the higher-level GPIOZero library and lower-level PiGPIO library relate to one another.

At this stage of your journey, if you are a little unclear about what's happening...

Summary

Through this chapter, you've just created a real functional IoT application using a Raspberry Pi and Python. We saw two alternative ways to flash a LED and read a button press in Python using both the GPIOZero and PiGPIO GPIO libraries. We also compared the use of these libraries and saw that GPIOZero takes a higher-level and more abstract approach to coding and GPIO control than does the lower-level PiGPIO library. We also connected the LED to the internet using the online dweet.io service. Using simple URLs, we were able to turn on and off and blink the LED by simply visiting the URLs in a web browser.

As you proceed through the subsequent chapters in this book, we'll be building on and going deeper into the core knowledge you have learned in this chapter about GPIO interfacing, electronic circuits, and controlling a circuit over the internet. We will learn alternative approaches to building an application to those we have covered in this chapter...

Questions 

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. You don't have the correct resistor value. Can you just substitute another value resistor that you have lying around? 
  2. The GPIOZero package is a compete GPIO library. Is it all you'll ever need?
  3. Should you always use the built-in Python packages for networking wherever possible?
  4. True or false: an LED is unbiased, meaning it can be plugged into a circuit any way around and still work. 
  5. You are building an IoT application that interacts with other existing networked devices and it times out. What could be the problem?
  6. What Python module and function can be used to stop a program exiting?

Further reading

We connected our LED to the internet using the dweet.io service and called its RESTful APIs, which are documented at the following:

You may wish to familiarize yourself with the GPIOZero library briefly to get an idea about what it can do. It's well documented with heaps of examples. Here are a couple of useful links to relevant parts of the API documentation that we've covered so far:

Regarding PiGPIO, here are the relevant parts of its API documentation. You'll notice that PiGPIO is a more advanced GPIO library with less verbose documentation.

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Practical Python Programming for IoT
Published in: Nov 2020Publisher: PacktISBN-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.
undefined
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