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__":