mirror of
				https://github.com/NotAShelf/air-quality-monitor.git
				synced 2025-10-31 03:02:38 +00:00 
			
		
		
		
	python cleanup
remove unaccessed imports
This commit is contained in:
		
					parent
					
						
							
								7a978853a8
							
						
					
				
			
			
				commit
				
					
						047447dce1
					
				
			
		
					 3 changed files with 96 additions and 88 deletions
				
			
		|  | @ -1,45 +0,0 @@ | ||||||
| import json |  | ||||||
| import os |  | ||||||
| import time |  | ||||||
| import datetime |  | ||||||
| import serial |  | ||||||
| import redis |  | ||||||
| import aqi |  | ||||||
| 
 |  | ||||||
| redis_client = redis.StrictRedis(host=os.environ.get('REDIS_HOST'), port=6379, db=0) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class AirQualityMonitor(): |  | ||||||
| 
 |  | ||||||
|     def __init__(self): |  | ||||||
|         self.ser = serial.Serial(os.environ.get('SERIAL_DEVICE','/dev/ttyUSB0')) |  | ||||||
| 
 |  | ||||||
|     def get_measurement(self): |  | ||||||
|         self.data = [] |  | ||||||
|         for index in range(0,10): |  | ||||||
|             datum = self.ser.read() |  | ||||||
|             self.data.append(datum) |  | ||||||
|         self.pmtwo = int.from_bytes(b''.join(self.data[2:4]), byteorder='little') / 10 |  | ||||||
|         self.pmten = int.from_bytes(b''.join(self.data[4:6]), byteorder='little') / 10 |  | ||||||
|         myaqi = aqi.to_aqi([(aqi.POLLUTANT_PM25, str(self.pmtwo)), |  | ||||||
|                             (aqi.POLLUTANT_PM10, str(self.pmten))]) |  | ||||||
|         self.aqi = float(myaqi) |  | ||||||
| 
 |  | ||||||
|         self.meas = { |  | ||||||
|             "timestamp": datetime.datetime.now(), |  | ||||||
|             "pm2.5": self.pmtwo, |  | ||||||
|             "pm10": self.pmten, |  | ||||||
|             "aqi": self.aqi, |  | ||||||
|         } |  | ||||||
|         return { |  | ||||||
|             'time': int(time.time()), |  | ||||||
|             'measurement': self.meas |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|     def save_measurement_to_redis(self): |  | ||||||
|         """Saves measurement to redis db""" |  | ||||||
|         redis_client.lpush('measurements', json.dumps(self.get_measurement(), default=str)) |  | ||||||
| 
 |  | ||||||
|     def get_last_n_measurements(self): |  | ||||||
|         """Returns the last n measurements in the list""" |  | ||||||
|         return [json.loads(x) for x in redis_client.lrange('measurements', 0, -1)] |  | ||||||
							
								
								
									
										89
									
								
								src/app.py
									
										
									
									
									
								
							
							
						
						
									
										89
									
								
								src/app.py
									
										
									
									
									
								
							|  | @ -1,87 +1,90 @@ | ||||||
| import os | import os | ||||||
| import time | import time | ||||||
| from flask import Flask, request, jsonify, render_template |  | ||||||
| from AirQualityMonitor import AirQualityMonitor |  | ||||||
| from apscheduler.schedulers.background import BackgroundScheduler |  | ||||||
| import redis |  | ||||||
| import atexit | import atexit | ||||||
|  | 
 | ||||||
|  | from flask import Flask, jsonify, render_template | ||||||
|  | from monitor import AirQualityMonitor | ||||||
|  | from apscheduler.schedulers.background import BackgroundScheduler | ||||||
| from flask_cors import CORS, cross_origin | from flask_cors import CORS, cross_origin | ||||||
| 
 | 
 | ||||||
|  | # initialize Flask and CORS | ||||||
| app = Flask(__name__) | app = Flask(__name__) | ||||||
| cors = CORS(app) | cors = CORS(app) | ||||||
| app.config['CORS_HEADERS'] = 'Content-Type' | app.config["CORS_HEADERS"] = "Content-Type" | ||||||
| aqm = AirQualityMonitor() |  | ||||||
| 
 | 
 | ||||||
|  | # initialize AirQualityMonitor and scheduler | ||||||
|  | aqm = AirQualityMonitor() | ||||||
| scheduler = BackgroundScheduler() | scheduler = BackgroundScheduler() | ||||||
| scheduler.add_job(func=aqm.save_measurement_to_redis, trigger="interval", seconds=60) | scheduler.add_job(func=aqm.save_measurement_to_redis, trigger="interval", seconds=60) | ||||||
| scheduler.start() | scheduler.start() | ||||||
| atexit.register(lambda: scheduler.shutdown()) | 
 | ||||||
| 
 | 
 | ||||||
| def pretty_timestamps(measurement): | def pretty_timestamps(measurement): | ||||||
| 	timestamps = [] |     """Convert timestamps to a more readable format.""" | ||||||
| 	for x in measurement: |     return [x["measurement"]["timestamp"].split(".")[0] for x in measurement] | ||||||
| 		timestamp = x['measurement']['timestamp'] | 
 | ||||||
| 		timestamps += [timestamp.split('.')[0]] |  | ||||||
| 	return timestamps |  | ||||||
| 
 | 
 | ||||||
| def reconfigure_data(measurement): | def reconfigure_data(measurement): | ||||||
|     """Reconfigures data for chart.js""" |     """Reconfigures data for chart.js""" | ||||||
|     current = int(time.time()) |     measurement = measurement[:30][::-1] | ||||||
|     measurement = measurement[:30] |  | ||||||
|     measurement.reverse() |  | ||||||
|     return { |     return { | ||||||
|         'labels': pretty_timestamps(measurement), |         "labels": pretty_timestamps(measurement), | ||||||
|         'aqi': { |         "aqi": { | ||||||
|             'label': 'aqi', |             "label": "aqi", | ||||||
|             'data': [x['measurement']['aqi'] for x in measurement], |             "data": [x["measurement"]["aqi"] for x in measurement], | ||||||
|             'backgroundColor': '#181d27', |             "backgroundColor": "#181d27", | ||||||
|             'borderColor': '#181d27', |             "borderColor": "#181d27", | ||||||
|             'borderWidth': 3, |             "borderWidth": 3, | ||||||
|         }, |         }, | ||||||
|         'pm10': { |         "pm10": { | ||||||
|             'label': 'pm10', |             "label": "pm10", | ||||||
|             'data': [x['measurement']['pm10'] for x in measurement], |             "data": [x["measurement"]["pm10"] for x in measurement], | ||||||
|             'backgroundColor': '#cc0000', |             "backgroundColor": "#cc0000", | ||||||
|             'borderColor': '#cc0000', |             "borderColor": "#cc0000", | ||||||
|             'borderWidth': 3, |             "borderWidth": 3, | ||||||
|         }, |         }, | ||||||
|         'pm2': { |         "pm2": { | ||||||
|             'label': 'pm2.5', |             "label": "pm2.5", | ||||||
|             'data': [x['measurement']['pm2.5'] for x in measurement], |             "data": [x["measurement"]["pm2.5"] for x in measurement], | ||||||
|             'backgroundColor': '#42C0FB', |             "backgroundColor": "#42C0FB", | ||||||
|             'borderColor': '#42C0FB', |             "borderColor": "#42C0FB", | ||||||
|             'borderWidth': 3, |             "borderWidth": 3, | ||||||
|         }, |         }, | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @app.route('/') | 
 | ||||||
|  | @app.route("/") | ||||||
| def index(): | def index(): | ||||||
|     """Index page for the application""" |     """Index page for the application""" | ||||||
|     context = { |     context = { | ||||||
|         'historical': reconfigure_data(aqm.get_last_n_measurements()), |         "historical": reconfigure_data(aqm.get_last_n_measurements()), | ||||||
|     } |     } | ||||||
|     return render_template('index.html', context=context) |     return render_template("index.html", context=context) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @app.route('/api/') | @app.route("/api/") | ||||||
| @cross_origin() | @cross_origin() | ||||||
| 
 |  | ||||||
| def api(): | def api(): | ||||||
|     """Returns historical data from the sensor""" |     """Returns historical data from the sensor""" | ||||||
|     context = { |     context = { | ||||||
|         'historical': reconfigure_data(aqm.get_last_n_measurements()), |         "historical": reconfigure_data(aqm.get_last_n_measurements()), | ||||||
|     } |     } | ||||||
|     return jsonify(context) |     return jsonify(context) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @app.route('/api/now/') | @app.route("/api/now/") | ||||||
| def api_now(): | def api_now(): | ||||||
|     """Returns latest data from the sensor""" |     """Returns latest data from the sensor""" | ||||||
|     context = { |     context = { | ||||||
|         'current': aqm.get_measurement(), |         "current": aqm.get_measurement(), | ||||||
|     } |     } | ||||||
|     return jsonify(context) |     return jsonify(context) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
|     app.run(debug=True, use_reloader=False, host='0.0.0.0', port=int(os.environ.get('PORT', '8000'))) |     app.run( | ||||||
|  |         debug=True, | ||||||
|  |         use_reloader=False, | ||||||
|  |         host="0.0.0.0", | ||||||
|  |         port=int(os.environ.get("PORT", "8000")), | ||||||
|  |     ) | ||||||
|  |  | ||||||
							
								
								
									
										50
									
								
								src/monitor.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/monitor.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | ||||||
|  | import json | ||||||
|  | import os | ||||||
|  | import time | ||||||
|  | import datetime | ||||||
|  | import serial | ||||||
|  | import redis | ||||||
|  | import aqi | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | REDIS_HOST = os.environ.get("REDIS_HOST", "localhost") | ||||||
|  | REDIS_PORT = int(os.environ.get("REDIS_PORT", 6379)) | ||||||
|  | REDIS_DB = int(os.environ.get("REDIS_DB", 0)) | ||||||
|  | redis_client = redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT, db=REDIS_DB) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class AirQualityMonitor: | ||||||
|  |     SERIAL_DEVICE = os.environ.get("SERIAL_DEVICE", "/dev/ttyUSB0") | ||||||
|  | 
 | ||||||
|  |     def __init__(self): | ||||||
|  |         self.ser = serial.Serial(self.SERIAL_DEVICE) | ||||||
|  | 
 | ||||||
|  |     def get_measurement(self): | ||||||
|  |         """Fetches a measurement from the sensor and returns it.""" | ||||||
|  |         data = [self.ser.read() for _ in range(10)] | ||||||
|  |         pmtwo = int.from_bytes(b"".join(data[2:4]), byteorder="little") / 10 | ||||||
|  |         pmten = int.from_bytes(b"".join(data[4:6]), byteorder="little") / 10 | ||||||
|  |         aqi_value = aqi.to_aqi( | ||||||
|  |             [ | ||||||
|  |                 (aqi.POLLUTANT_PM25, str(pmtwo)), | ||||||
|  |                 (aqi.POLLUTANT_PM10, str(pmten)), | ||||||
|  |             ] | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         measurement = { | ||||||
|  |             "timestamp": datetime.datetime.now(), | ||||||
|  |             "pm2.5": pmtwo, | ||||||
|  |             "pm10": pmten, | ||||||
|  |             "aqi": float(aqi_value), | ||||||
|  |         } | ||||||
|  |         return {"time": int(time.time()), "measurement": measurement} | ||||||
|  | 
 | ||||||
|  |     def save_measurement_to_redis(self): | ||||||
|  |         """Saves measurement to redis db""" | ||||||
|  |         redis_client.lpush( | ||||||
|  |             "measurements", json.dumps(self.get_measurement(), default=str) | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |     def get_last_n_measurements(self): | ||||||
|  |         """Returns the last n measurements in the list""" | ||||||
|  |         return [json.loads(x) for x in redis_client.lrange("measurements", 0, -1)] | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue