Publishing Sensor data with MQTT (Exercise)
MQTT Sensor
##################################################################################
import network # mqtt needs network connection #
import framebuf # we also connect a display #
from umqtt.simple import MQTTClient # MQTT library #
from SH1107_OLED import OLED # our driver for the OLED display #
from BME280 import BME280 # our library for the BME280 sensor (T,P) #
from utils import Config # to read a configurattion file #
from machine import Pin, I2C # API for the I2C interfaces #
import time # standard package for timing #
import json # we publish our data in json format #
##################################################################################
##################################################################################
def wifi_connect(oled):
##################################################################################
# Here connect to the wifi network. You should give feedback to the user
# by displaying some information on the display.
# short break to read the display before we move on
time.sleep(2)
##################################################################################
##################################################################################
def mqtt_connect(client_id, mqtt_server, oled):
##################################################################################
# Now set up the connection to the MQTT Broker
print("connecting to %s" % mqtt_server)
fb = oled.getFramebuffer()
client = MQTTClient(client_id, mqtt_server, keepalive=3600)
if oled:
fb.fill(0)
fb.text( "mqtt connect...", 0,10 )
oled.copyFramebuf()
try:
client.connect()
except Exception as e:
print(e)
if oled:
fb.text("...failed...", 0,20 )
fb.text("check broker!", 0,30 )
fb.text("cont. wo MQTT!", 0,45 )
oled.copyFramebuf()
time.sleep(5)
fb.fill(0)
return False
else:
return False
if oled:
fb.text("mqtt broker :", 0,30 )
fb.text(mqtt_server, 0,40 )
oled.copyFramebuf()
time.sleep( 4 )
return client
##################################################################################
####################### Here the main programme starts ###########################
# read the configuration file: The variable config is in the global scope of the
# program and hence also known in the subroutines above. The configuration file
# should contains parameters for network connection (wifi name and password) and
# the mqtt server hostname (or ip address), the clienId for the MQTT connection,
# the topic name to which we pusblish ("sensors/{yourName}": check that nobody
# else has this topic name !) and the publish interval. Finally we need to the
# altitude of Padova in the config file since we want to normalise the pressure
# to 0 height altitude (this normalised value is reported in weather services
# since it allow you to compare air-pressure values at different locations)
config = Config( "config_mqttSensor.json" )
# Initialise and configure the first I2C port of the ESP32
# We put both sensors and the display on the same I2C bus.
# The frequency is the I2C default frequency. You can try
# and go higher. At some point things will stop working...
i2c =
# Instantiate the classes for the 2 sensors we have on board
bme =
# Setup our super I2C OLED display; we want to use it in landscape.
oled =
# get the framebuffer from the OLED display since we need it below
# to write stuff on the screen.
fb =
# Setup the network connection via the built in WIFI (use a subroutine)
...
# Connect to MQTT broker (use a subroutine: see above)
mqtt =
# Now we start out endless loop.
# We take measurements with the sensors and update the display
# However, the publishing to the MQTT Broker we do less often.
# It is not super interesting to monitor these values which only
# vary very slowly, with high frequency. (For practical purposes
# the publishing frequency in this example is stil nuch too high.
# But we want to see "something moving" in the MQTT network...)
#
# The absolute altitude can only be roughly estimated. For a precise
# absolute altitude we need to calibrate the formulas, however, this
# requires the knowledge of the absolute altitude. But we can measure
# measure very precisely altitude differences. Therefore we take the mean
# of the first 10 altitude measurements as the reference hight and
# from then on we display the difference to this height. Remember not
# to move the Sensor during these 10 first measurements.
ltime = time.time()
alt_ref = 0
i_measure = 0
while True:
# Get the latest greatest sensor values:
# Both sensors deliver temperature values. We read both of them.
[temp, press, hum] = bme.doMeasure()
alt = bme.getAltitude()
# convert pressure to see level
# For this we use the altitude given as a constant to the programme.
# This normalised altitude is used to compare pressure values
# measured at different places with different (but known!) altitudes.
alt0 = config.get("alt0")
p0 = press*((1-0.0065*alt0/(temp+0.0065*alt0+273.15))**-5.257)
# Don't forget to clear the framebuffer before you write something new
# on the screen
...
# Now check if we need to publish to MQTT by inspecting the time
# since the last update.
# Now do the measurements and publish the sensor values to the MQTT topic.
# You should format the message contents in json. For this you can create
# a simple python dictionary with the keys "temperature", "pressure", and
# "humidity" and use the json.dumps method to create a json string. This is
# then the payload for the message to be published.
# To publish the topic you use the "publish" message on your mqtt object
# which you have created when you connected to the network.
# Pay attention that you only publish to the mqtt network every n seconds
# where n is defined in the configuration file. We want to measure and display
# measurements every second more or less, but the publishing to the MQTT
# network should be much less often (e.g. every 10 seconds).
# Display the values on the OLED
# Next update in a second.
time.sleep_ms(1000)