]>
zdv2.bktei.com Git - EVA-2020-02-2.git/blob - examples/mqtt-all.py
26f46bb3d84b3989f24edaf91d41524c49b05ba3
   2 Run mqtt broker on localhost: sudo apt-get install mosquitto mosquitto-clients 
   4 Example run: python3 mqtt-all.py --broker 192.168.1.164 --topic enviro 
  11 from bme280 
import BME280
 
  12 from pms5003 
import PMS5003
, ReadTimeoutError
 
  13 from enviroplus 
import gas
 
  16     # Transitional fix for breaking change in LTR559 
  17     from ltr559 
import LTR559
 
  23 from subprocess 
import PIPE
, Popen
, check_output
 
  24 from PIL 
import Image
, ImageDraw
, ImageFont
 
  25 from fonts
.ttf 
import RobotoMedium 
as UserFont
 
  28 import paho
.mqtt
.client 
as mqtt
 
  29 import paho
.mqtt
.publish 
as publish
 
  32     from smbus2 
import SMBus
 
  34     from smbus 
import SMBus
 
  37 DEFAULT_MQTT_BROKER_IP 
= "localhost" 
  38 DEFAULT_MQTT_BROKER_PORT 
= 1883 
  39 DEFAULT_MQTT_TOPIC 
= "enviroplus" 
  42 def on_connect(client
, userdata
, flags
, rc
): 
  43     print(f
"CONNACK received with code {rc}") 
  47         print("Bad connection Returned code=", rc
) 
  50 def on_publish(client
, userdata
, mid
): 
  51     print("mid: " + str(mid
)) 
  54 # Read values from BME280 and PMS5003 and return as dict 
  55 def read_values(bme280
, pms5003
): 
  56     # Compensation factor for temperature 
  60     cpu_temp 
= get_cpu_temperature() 
  61     raw_temp 
= bme280
.get_temperature()  # float 
  62     comp_temp 
= raw_temp 
- ((cpu_temp 
- raw_temp
) / comp_factor
) 
  63     values
["temperature"] = int(comp_temp
) 
  64     values
["pressure"] = round( 
  65         int(bme280
.get_pressure() * 100), -1 
  66     )  # round to nearest 10 
  67     values
["humidity"] = int(bme280
.get_humidity()) 
  69         pm_values 
= pms5003
.read()  # int 
  70         values
["pm1"] = pm_values
.pm_ug_per_m3(1) 
  71         values
["pm25"] = pm_values
.pm_ug_per_m3(2.5) 
  72         values
["pm10"] = pm_values
.pm_ug_per_m3(10) 
  73     except ReadTimeoutError
: 
  75         pm_values 
= pms5003
.read() 
  76         values
["pm1"] = pm_values
.pm_ug_per_m3(1) 
  77         values
["pm25"] = pm_values
.pm_ug_per_m3(2.5) 
  78         values
["pm10"] = pm_values
.pm_ug_per_m3(10) 
  80     values
["oxidised"] = int(data
.oxidising 
/ 1000) 
  81     values
["reduced"] = int(data
.reducing 
/ 1000) 
  82     values
["nh3"] = int(data
.nh3 
/ 1000) 
  83     values
["lux"] = int(ltr559
.get_lux()) 
  87 # Get CPU temperature to use for compensation 
  88 def get_cpu_temperature(): 
  89     process 
= Popen(["vcgencmd", "measure_temp"], stdout
=PIPE
, universal_newlines
=True) 
  90     output
, _error 
= process
.communicate() 
  91     return float(output
[output
.index("=") + 1 : output
.rindex("'")]) 
  94 # Get Raspberry Pi serial number to use as ID 
  95 def get_serial_number(): 
  96     with 
open("/proc/cpuinfo", "r") as f
: 
  98             if line
[0:6] == "Serial": 
  99                 return line
.split(":")[1].strip() 
 102 # Check for Wi-Fi connection 
 104     if check_output(["hostname", "-I"]): 
 110 # Display Raspberry Pi serial and Wi-Fi status on LCD 
 111 def display_status(disp
, mqtt_broker
): 
 112     # Width and height to calculate text position 
 117     font 
= ImageFont
.truetype(UserFont
, font_size
) 
 119     wifi_status 
= "connected" if check_wifi() else "disconnected" 
 120     text_colour 
= (255, 255, 255) 
 121     back_colour 
= (0, 170, 170) if check_wifi() else (85, 15, 15) 
 122     id = get_serial_number() 
 123     message 
= "{}\nWi-Fi: {}\nmqtt-broker: {}".format(id, wifi_status
, mqtt_broker
) 
 124     img 
= Image
.new("RGB", (WIDTH
, HEIGHT
), color
=(0, 0, 0)) 
 125     draw 
= ImageDraw
.Draw(img
) 
 126     size_x
, size_y 
= draw
.textsize(message
, font
) 
 127     x 
= (WIDTH 
- size_x
) / 2 
 128     y 
= (HEIGHT 
/ 2) - (size_y 
/ 2) 
 129     draw
.rectangle((0, 0, 160, 80), back_colour
) 
 130     draw
.text((x
, y
), message
, font
=font
, fill
=text_colour
) 
 135     parser 
= argparse
.ArgumentParser(description
="Publish enviroplus values over mqtt") 
 137         "--broker", default
=DEFAULT_MQTT_BROKER_IP
, type=str, help="mqtt broker IP", 
 140         "--port", default
=DEFAULT_MQTT_BROKER_PORT
, type=int, help="mqtt broker port", 
 143         "--topic", default
=DEFAULT_MQTT_TOPIC
, type=str, help="mqtt topic" 
 145     args 
= parser
.parse_args() 
 148         """mqtt-all.py - Reads temperature, pressure, humidity, 
 149     PM2.5, and PM10 from Enviro plus and sends data over mqtt. 
 155     Press Ctrl+C to exit! 
 158             args
.broker
, args
.port
, args
.topic
 
 162     mqtt_client 
= mqtt
.Client() 
 163     mqtt_client
.on_connect 
= on_connect
 
 164     mqtt_client
.on_publish 
= on_publish
 
 165     mqtt_client
.connect(args
.broker
, port
=args
.port
) 
 169     # Create BME280 instance 
 170     bme280 
= BME280(i2c_dev
=bus
) 
 172     # Create LCD instance 
 173     disp 
= ST7735
.ST7735( 
 174         port
=0, cs
=1, dc
=9, backlight
=12, rotation
=270, spi_speed_hz
=10000000 
 180     # Create PMS5003 instance 
 184     device_serial_number 
= get_serial_number() 
 185     id = "raspi-" + device_serial_number
 
 187     # Display Raspberry Pi serial and Wi-Fi status 
 188     print("Raspberry Pi serial: {}".format(get_serial_number())) 
 189     print("Wi-Fi: {}\n".format("connected" if check_wifi() else "disconnected")) 
 190     print("MQTT broker IP: {}".format(args
.broker
)) 
 192     time_since_update 
= 0 
 193     update_time 
= time
.time() 
 195     # Main loop to read data, display, and send over mqtt 
 196     mqtt_client
.loop_start() 
 199             time_since_update 
= time
.time() - update_time
 
 200             values 
= read_values(bme280
, pms5003
) 
 201             values
["serial"] = device_serial_number
 
 203             mqtt_client
.publish(args
.topic
, json
.dumps(values
)) 
 204             if time_since_update 
> 145: 
 205                 update_time 
= time
.time() 
 206             display_status(disp
, args
.broker
) 
 207         except Exception as e
: 
 211 if __name__ 
== "__main__":