Skip to content

Commit f7aca73

Browse files
Add files via upload
Drew's hacked version of the luftdaten file.
1 parent ad9a010 commit f7aca73

1 file changed

Lines changed: 167 additions & 0 deletions

File tree

luftdaten.py

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
#!/usr/bin/env python3
2+
3+
# This is the Drew hack v0.1 10/01/22 of the Pimoroni Enviro+ Code.
4+
# It ditches the screen and the temperature compensate.
5+
6+
import requests
7+
import time
8+
from bme280 import BME280
9+
from pms5003 import PMS5003, ReadTimeoutError, ChecksumMismatchError
10+
from subprocess import check_output
11+
12+
try:
13+
from smbus2 import SMBus
14+
except ImportError:
15+
from smbus import SMBus
16+
import logging
17+
18+
logging.basicConfig(
19+
format='%(asctime)s.%(msecs)03d %(levelname)-8s %(message)s',
20+
level=logging.INFO,
21+
datefmt='%Y-%m-%d %H:%M:%S')
22+
23+
logging.info("""luftdaten.py - Reads temperature, pressure, humidity,
24+
#PM2.5, and PM10 and sends data to Luftdaten / sensor.community,
25+
#the citizen science air quality project.
26+
27+
#Note: you'll need to register with Sensor Community at:
28+
#https://devices.sensor.community/ and enter your Raspberry Pi
29+
#serial number (from Terminal) before the data appears on the
30+
#Sensor Community map.
31+
32+
#Press Ctrl+C to exit!
33+
34+
#""")
35+
36+
bus = SMBus(1)
37+
38+
bme280 = BME280(i2c_dev=bus)
39+
pms5003 = PMS5003()
40+
41+
42+
# Read values from BME280 and PMS5003 and return as dict
43+
def read_values():
44+
values = {}
45+
raw_temp = bme280.get_temperature()
46+
comp_temp = raw_temp
47+
values["temperature"] = "{:.2f}".format(comp_temp)
48+
values["pressure"] = "{:.2f}".format(bme280.get_pressure() * 100)
49+
values["humidity"] = "{:.2f}".format(bme280.get_humidity())
50+
try:
51+
pm_values = pms5003.read()
52+
values["P2"] = str(pm_values.pm_ug_per_m3(2.5))
53+
values["P1"] = str(pm_values.pm_ug_per_m3(10))
54+
except(ReadTimeoutError, ChecksumMismatchError):
55+
logging.info("Failed to read PMS5003. Reseting and retrying.")
56+
pms5003.reset()
57+
pm_values = pms5003.read()
58+
values["P2"] = str(pm_values.pm_ug_per_m3(2.5))
59+
values["P1"] = str(pm_values.pm_ug_per_m3(10))
60+
return values
61+
62+
63+
# Get Raspberry Pi serial number to use as ID
64+
def get_serial_number():
65+
with open('/proc/cpuinfo', 'r') as f:
66+
for line in f:
67+
if line[0:6] == 'Serial':
68+
return line.split(":")[1].strip()
69+
70+
71+
# Check for Wi-Fi connection
72+
def check_wifi():
73+
if check_output(['hostname', '-I']):
74+
return True
75+
else:
76+
return False
77+
78+
79+
def send_to_luftdaten(values, id):
80+
pm_values = dict(i for i in values.items() if i[0].startswith("P"))
81+
temp_values = dict(i for i in values.items() if not i[0].startswith("P"))
82+
83+
pm_values_json = [{"value_type": key, "value": val} for key, val in pm_values.items()]
84+
temp_values_json = [{"value_type": key, "value": val} for key, val in temp_values.items()]
85+
86+
resp_pm = None
87+
resp_bmp = None
88+
89+
try:
90+
resp_pm = requests.post(
91+
"https://api.sensor.community/v1/push-sensor-data/",
92+
json={
93+
"software_version": "enviro-plus 0.0.1",
94+
"sensordatavalues": pm_values_json
95+
},
96+
headers={
97+
"X-PIN": "1",
98+
"X-Sensor": id,
99+
"Content-Type": "application/json",
100+
"cache-control": "no-cache"
101+
},
102+
timeout=5
103+
)
104+
except requests.exceptions.ConnectionError as e:
105+
logging.warning('Sensor.Community PM Connection Error: {}'.format(e))
106+
except requests.exceptions.Timeout as e:
107+
logging.warning('Sensor.Community PM Timeout Error: {}'.format(e))
108+
except requests.exceptions.RequestException as e:
109+
logging.warning('Sensor.Community PM Request Error: {}'.format(e))
110+
111+
try:
112+
resp_bmp = requests.post(
113+
"https://api.sensor.community/v1/push-sensor-data/",
114+
json={
115+
"software_version": "enviro-plus 0.0.1",
116+
"sensordatavalues": temp_values_json
117+
},
118+
headers={
119+
"X-PIN": "11",
120+
"X-Sensor": id,
121+
"Content-Type": "application/json",
122+
"cache-control": "no-cache"
123+
},
124+
timeout=5
125+
)
126+
except requests.exceptions.ConnectionError as e:
127+
logging.warning('Sensor.Community Climate Connection Error: {}'.format(e))
128+
except requests.exceptions.Timeout as e:
129+
logging.warning('Sensor.Community Climate Timeout Error: {}'.format(e))
130+
except requests.exceptions.RequestException as e:
131+
logging.warning('Sensor.Community Climate Request Error: {}'.format(e))
132+
133+
if resp_pm is not None and resp_bmp is not None:
134+
if resp_pm.ok and resp_bmp.ok:
135+
return True
136+
else:
137+
logging.warning('Sensor.Community Error. PM: {}, Climate: {}'.format(resp_pm.reason, resp_bmp.reason))
138+
return False
139+
else:
140+
return False
141+
142+
143+
# Raspberry Pi ID to send to Luftdaten
144+
id = "raspi-" + get_serial_number()
145+
146+
147+
# Log Raspberry Pi serial and Wi-Fi status
148+
logging.info("Raspberry Pi serial: {}".format(get_serial_number()))
149+
logging.info("Wi-Fi: {}\n".format("connected" if check_wifi() else "disconnected"))
150+
151+
time_since_update = 0
152+
update_time = time.time()
153+
154+
# Main loop to read data, display, and send to Luftdaten
155+
while True:
156+
try:
157+
values = read_values()
158+
time_since_update = time.time() - update_time
159+
if time_since_update > 145:
160+
logging.info(values)
161+
update_time = time.time()
162+
if send_to_luftdaten(values, id):
163+
logging.info("Sensor.Community Response: OK")
164+
else:
165+
logging.warning("Sensor.Community Response: Failed")
166+
except Exception as e:
167+
logging.warning('Main Loop Exception: {}'.format(e))

0 commit comments

Comments
 (0)