Menu

Expand
Rate this page:

Extend the Getting Started with Programmable Wireless and Raspberry Pi Code

Once you have worked through our Getting Started with Programmable Wireless, you may like to spend some time exploring how the sample app you built in the guide enables MQTT communication. This will help you understand the app better so that you can more readily adapt it to your own, more complex use case. This article describes the parts of the app’s functionality that you may choose to change.

The app you use in the Quick Start guide is a Python script called telemetry.py. It contains all of the logic required for

  • Interfacing with the Grove temperature and humidity sensor.
  • Operating the Grove display.
  • Sending MQTT messages.
  • Processing inbound MQTT messages.

If you haven’t installed telemetry.py on your Raspberry Pi, you should do so by running this command:

wget https://twilio-deved-content-prod.s3.amazonaws.com/quest/programmable_wireless/broadband/telemetry.py

Control the temperature sensor

To control the temperature and humidity sensor, we use Seeed’s grove library. In the app code, look for the line:

class GroveTemperatureHumiditySensorSHT3x(object):

This is where the sensor class is defined.

The script creates an instance of this class which is identified by the name sensor, and the code calls sensor.read()* whenever it needs to take temperature and humidity readings. For example, the function twilio_telemetry_loop() repeatedly takes the temperature and humidity at the time and stores it in a JSON structure:

while True:
    celsius_temperature, humidity = sensor.read()
    fahrenheit_temperature = (celsius_temperature * 1.8) + 32
    celsius_temperature = float("{0:.2f}".format(celsius_temperature))
    fahrenheit_temperature = float("{0:.2f}".format(fahrenheit_temperature))
    humidity = float("{0:.2f}".format(humidity))

The function goes on to display these values and to create the payload of the MQTT message that will be sent:

msg_txt_formatted = json.dumps({
    'deviceId': MQTT_CLIENT_ID,
    'temperatureFahrenheit': fahrenheit_temperature,
    'temperatureCelsius': celsius_temperature,
    'displayedTemperatureUnits': UNITS,
    'humidity': humidity,
    'shenanigans': "none",
})

print(msg_txt_formatted)
client.publish(MQTT_PUBLISH_TOPIC, msg_txt_formatted)

Drive the display

To interface with the display, we use the Luma LCD library. Wherever you see the function draw.text(), it is being used to send strings to the display at a specific pixel location on the screen.

For example, the following function called when you load the script will show the splash screen:

with canvas(device) as draw:
    draw.rectangle(device.bounding_box, outline="white", fill="black")
    draw.text((5, 10), "Twilio Trust Onboard", fill="white")
    draw.text((42, 40), "presents", fill="white")
    draw.text((44, 65), "M Q T T", fill="white")
    draw.text((12, 80), "T E L E M E T R Y", fill="white")

Images are slightly more complicated since they may be larger than the screen (128 x 128 pixels). To deal with this, we use the Pillow library to scale down an image’s dimensions to fit the display.

For example, this code resizes an image (identified by URI) and displays it:

def update_image_on_display(url):
    global CURRENT_LOGO
    if url != "":
        try:
            logo = Image.open(
                urllib2.urlopen(url)
            ).convert("RGBA")

            width, height = logo.size
            if width > 128 or height > 128:
                logo.thumbnail(device.size)

            if logo:
                CURRENT_LOGO = logo

        except:
            pass

    background = Image.new("RGBA", device.size, "white")
    posn = ((device.width - CURRENT_LOGO.width) // 2, 0)

    background.paste(CURRENT_LOGO, posn)
    device.display(background.convert(device.mode))

Handle MQTT messages

We set up a callback function for MQTT messages in the state topic right at the entry point of the app:

##############################################
# Called from the command line               #
##############################################
if __name__ == '__main__':
    time.sleep(5)
    print ("Starting the Twilio Broadband MQTT Demo...")

    client.on_message = on_message
    client.subscribe(MQTT_STATE_TOPIC)
    twilio_telemetry_loop()

The crucial line is the third from the bottom in the snippet above: we tell the MQTT message handler, client, to call out function on_message() whenever there is a message process. Take a look at this function to see how we handle incoming messages. We try to extract certain keys and values from the JSON, and then act upon those that we recognize:

def on_message(client, userdata, message):
    global UNITS
    global DISPLAY_TYPE
    print("Message received ", str(message.payload.decode("utf-8")))
    print("Message topic=", message.topic)
    print("Message qos=", message.qos)
    print("Message retain flag=", message.retain)

    try:
        msg = json.loads(str(message.payload.decode("utf-8")))
        print(msg)

        if 'units' in msg and \
                msg['units'] in ('fahrenheit', 'celsius'):
            UNITS = msg['units']

        if 'display' in msg:
            if msg['display'] == "image":
                DISPLAY_TYPE = 'image'
                if 'displayUrl' in msg:
                    update_image_on_display(msg['displayUrl'])
                update_image_on_display("")
            if msg['display'] == "temperature":
                DISPLAY_TYPE = 'temperature'
    except:
        # Probably wasn't JSON
        pass

Together, the functions discussed above provide you with tools to publish and subscribe to MQTT topics. You can also change the behavior of the device from the cloud, and send fun images back to the board.

You’re now ready to build your own, more complex use case. We can’t wait to see what you build next!

Rate this page:

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd by visiting Twilio's Community Forums or browsing the Twilio tag on Stack Overflow.

Thank you for your feedback!

We are always striving to improve our documentation quality, and your feedback is valuable to us. How could this documentation serve you better?

Sending your feedback...
🎉 Thank you for your feedback!
Something went wrong. Please try again.

Thanks for your feedback!

Refer us and get $10 in 3 simple steps!

Step 1

Get link

Get a free personal referral link here

Step 2

Give $10

Your user signs up and upgrade using link

Step 3

Get $10

1,250 free SMSes
OR 1,000 free voice mins
OR 12,000 chats
OR more