pimoroni / enviro

MIT License
101 stars 79 forks source link

Support for MQTT over SSL for destinations #122

Closed dave-ct closed 1 year ago

dave-ct commented 1 year ago

For internal use on your own wifi network using MQTT over an insecure connection is fine but if you want the sensor outside of you own internal wifi it would be better to connect over SSL so you can expose the mqtt broker port more securly. This is a suggested enhancement. Would only need the ca.crt file to be added to the enviro device that was generated from the mqtt broker.

1 > Make change to config.py and add the file location of ca_crt that you would need to copy to the pico in that location, we could then use this to check if we want to use SSL or not: mqtt_broker_ca_file = 'ca.crt'

2 > Update the destintaions file mqtt.py to check if mqtt_broker_ca_file is True and if so set the connection with SSL, otherwise use mqtt without SSL: Sample approach that I tested which seems to work OK for mqtt.py.

from enviro import logging
from enviro.constants import UPLOAD_SUCCESS, UPLOAD_FAILED
from enviro.mqttsimple import MQTTClient
import ujson
import config

def log_destination():
  logging.info(f"> uploading cached readings to MQTT broker: {config.mqtt_broker_address}")

def upload_reading(reading):
  server = config.mqtt_broker_address
  username = config.mqtt_broker_username
  password = config.mqtt_broker_password
  nickname = reading["nickname"]

  try:
    # attempt to publish reading

    ##### SSL Change Start
    # two options, with or without SSL
    if config.mqtt_broker_ca_file:
      f = open("ca.crt")
      ssl_data = f.read()
      f.close()
      mqtt_client = MQTTClient(reading["uid"], server, user=username, password=password, keepalive=60,
                               ssl=True, ssl_params={'cert': ssl_data})
    else:
    ##### SSL Change not set so do insecure connection
      mqtt_client = MQTTClient(reading["uid"], server, user=username, password=password, keepalive=60)
    # Now continue with connection and upload
    mqtt_client.connect()
    mqtt_client.publish(f"enviro/{nickname}", ujson.dumps(reading), retain=True)
    mqtt_client.disconnect()
    return UPLOAD_SUCCESS
  except:
    logging.debug(f"  - an exception occurred when uploading")

  return UPLOAD_FAILED