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)