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
, SerialTimeoutError
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"
40 DEFAULT_READ_INTERVAL
= 5
43 def on_connect(client
, userdata
, flags
, 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 return as dict
55 def read_bme280(bme280
):
56 # Compensation factor for temperature
59 cpu_temp
= get_cpu_temperature()
60 raw_temp
= bme280
.get_temperature() # float
61 comp_temp
= raw_temp
- ((cpu_temp
- raw_temp
) / comp_factor
)
62 values
["temperature"] = int(comp_temp
)
63 values
["pressure"] = round(
64 int(bme280
.get_pressure() * 100), -1
65 ) # round to nearest 10
66 values
["humidity"] = int(bme280
.get_humidity())
68 values
["oxidised"] = int(data
.oxidising
/ 1000)
69 values
["reduced"] = int(data
.reducing
/ 1000)
70 values
["nh3"] = int(data
.nh3
/ 1000)
71 values
["lux"] = int(ltr559
.get_lux())
75 # Read values PMS5003 and return as dict
76 def read_pms5003(pms5003
):
79 pm_values
= pms5003
.read() # int
80 values
["pm1"] = pm_values
.pm_ug_per_m3(1)
81 values
["pm25"] = pm_values
.pm_ug_per_m3(2.5)
82 values
["pm10"] = pm_values
.pm_ug_per_m3(10)
83 except ReadTimeoutError
:
85 pm_values
= pms5003
.read()
86 values
["pm1"] = pm_values
.pm_ug_per_m3(1)
87 values
["pm25"] = pm_values
.pm_ug_per_m3(2.5)
88 values
["pm10"] = pm_values
.pm_ug_per_m3(10)
92 # Get CPU temperature to use for compensation
93 def get_cpu_temperature():
95 ["vcgencmd", "measure_temp"], stdout
=PIPE
, universal_newlines
=True
97 output
, _error
= process
.communicate()
98 return float(output
[output
.index("=") + 1 : output
.rindex("'")])
101 # Get Raspberry Pi serial number to use as ID
102 def get_serial_number():
103 with
open("/proc/cpuinfo", "r") as f
:
105 if line
[0:6] == "Serial":
106 return line
.split(":")[1].strip()
109 # Check for Wi-Fi connection
111 if check_output(["hostname", "-I"]):
117 # Display Raspberry Pi serial and Wi-Fi status on LCD
118 def display_status(disp
, mqtt_broker
):
119 # Width and height to calculate text position
124 font
= ImageFont
.truetype(UserFont
, font_size
)
126 wifi_status
= "connected" if check_wifi() else "disconnected"
127 text_colour
= (255, 255, 255)
128 back_colour
= (0, 170, 170) if check_wifi() else (85, 15, 15)
129 device_serial_number
= get_serial_number()
130 message
= "{}\nWi-Fi: {}\nmqtt-broker: {}".format(
131 device_serial_number
, wifi_status
, mqtt_broker
133 img
= Image
.new("RGB", (WIDTH
, HEIGHT
), color
=(0, 0, 0))
134 draw
= ImageDraw
.Draw(img
)
135 size_x
, size_y
= draw
.textsize(message
, font
)
136 x
= (WIDTH
- size_x
) / 2
137 y
= (HEIGHT
/ 2) - (size_y
/ 2)
138 draw
.rectangle((0, 0, 160, 80), back_colour
)
139 draw
.text((x
, y
), message
, font
=font
, fill
=text_colour
)
144 parser
= argparse
.ArgumentParser(
145 description
="Publish enviroplus values over mqtt"
149 default
=DEFAULT_MQTT_BROKER_IP
,
151 help="mqtt broker IP",
155 default
=DEFAULT_MQTT_BROKER_PORT
,
157 help="mqtt broker port",
160 "--topic", default
=DEFAULT_MQTT_TOPIC
, type=str, help="mqtt topic"
164 default
=DEFAULT_READ_INTERVAL
,
166 help="the read interval in seconds",
168 args
= parser
.parse_args()
171 device_serial_number
= get_serial_number()
172 device_id
= "raspi-" + device_serial_number
175 f
"""mqtt-all.py - Reads Enviro plus data and sends over mqtt.
177 broker: {args.broker}
178 client_id: {device_id}
182 Press Ctrl+C to exit!
187 mqtt_client
= mqtt
.Client(client_id
=device_id
)
188 mqtt_client
.on_connect
= on_connect
189 mqtt_client
.on_publish
= on_publish
190 mqtt_client
.connect(args
.broker
, port
=args
.port
)
194 # Create BME280 instance
195 bme280
= BME280(i2c_dev
=bus
)
197 # Create LCD instance
198 disp
= ST7735
.ST7735(
199 port
=0, cs
=1, dc
=9, backlight
=12, rotation
=270, spi_speed_hz
=10000000
205 # Try to create PMS5003 instance
209 pm_values
= pms5003
.read()
211 print("PMS5003 sensor is connected")
212 except SerialTimeoutError
:
213 print("No PMS5003 sensor connected")
215 # Display Raspberry Pi serial and Wi-Fi status
216 print("RPi serial: {}".format(device_serial_number
))
217 print("Wi-Fi: {}\n".format("connected" if check_wifi() else "disconnected"))
218 print("MQTT broker IP: {}".format(args
.broker
))
220 # Main loop to read data, display, and send over mqtt
221 mqtt_client
.loop_start()
224 values
= read_bme280(bme280
)
226 pms_values
= read_pms5003(pms5003
)
227 values
.update(pms_values
)
228 values
["serial"] = device_serial_number
230 mqtt_client
.publish(args
.topic
, json
.dumps(values
))
231 display_status(disp
, args
.broker
)
232 time
.sleep(args
.interval
)
233 except Exception as e
:
237 if __name__
== "__main__":