Last active
January 30, 2022 16:03
-
-
Save NicolaiSoeborg/3e97a6f6da87ab1e870a5237f4afcd29 to your computer and use it in GitHub Desktop.
Save and plot data from BME680 (Raspberry Pi)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| import json, os, sqlite3 | |
| from datetime import datetime | |
| from random import randint | |
| from time import time, sleep | |
| try: | |
| from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient # pip3 install azure-storage-blob | |
| except: pass | |
| def get_db(): | |
| conn = sqlite3.connect('sensor-data.db') | |
| conn.execute('''CREATE TABLE IF NOT EXISTS data ( | |
| time INTEGER PRIMARY KEY, | |
| gas_ohms REAL, | |
| humidity_pctRH REAL, | |
| temperature_degC REAL, | |
| pressure_hPa REAL, | |
| heat_stable INT)''') | |
| conn.commit() | |
| return conn | |
| last_uploaded_ts = -1 | |
| def insert_data(db, data, blob_service_client): | |
| global last_uploaded_ts | |
| ts = int(time()) | |
| db.execute("INSERT INTO data VALUES (?, ?, ?, ?, ?, ?)", ( | |
| ts, | |
| data.gas_resistance, | |
| data.humidity, | |
| data.temperature, | |
| data.pressure, | |
| data.heat_stable | |
| )) | |
| # This is called every 45 sec | |
| # (10% chance of commit) * 5 == 50% chance | |
| # 45 sec * 5 = a commit every 3.75 min | |
| if randint(0, 9) == 3: | |
| db.commit() | |
| # This is called every 3.75 min | |
| # 225 sec * 5 = a commit every 18 min | |
| if randint(0, 9) == 3: | |
| try: | |
| blob_name = datetime.utcfromtimestamp(ts).strftime("%Y/%m") + '/' + str(ts) | |
| blob_client = blob_service_client.get_blob_client(container="data", blob=blob_name) | |
| blob = json.dumps(db.execute("SELECT * FROM data WHERE time > ?", (last_uploaded_ts,)).fetchall()) | |
| blob_client.upload_blob(blob.encode()) | |
| last_uploaded_ts = ts | |
| except Exception as ex: | |
| print(f"[ERR] while updating: {ex}") | |
| def plot(): | |
| import plotly.express as px # python3 -m pip install dash | |
| import pandas as pd # python3 -m pip install pandas | |
| import dash | |
| from dash import dcc | |
| from dash import html | |
| df = pd.read_sql_query("SELECT * FROM data", get_db()) | |
| # 'time'-col from ints to 'real datetimes' | |
| df['time'] = list(map(datetime.fromtimestamp, df['time'])) | |
| cols = ['gas_ohms', 'humidity_pctRH', 'temperature_degC', 'pressure_hPa'] | |
| app = dash.Dash() | |
| app.layout = html.Div([ | |
| dcc.Graph(figure=px.line(df, x='time', y=col)) for col in cols | |
| ]) | |
| #t0 = min(df['time']) | |
| #df['days'] = [(t-t0).days for t in df['time']] | |
| #fig = px.line(df, | |
| # x='temperature_degC', range_x=[min(df['temperature_degC']), max(df['temperature_degC'])], | |
| # y='humidity_pctRH', range_y=[min(df['humidity_pctRH']), max(df['humidity_pctRH'])], | |
| # animation_frame='days') | |
| #fig.show() | |
| # | |
| #fig = px.scatter(df, x="gdpPercap", y="lifeExp", animation_frame="year", animation_group="country", | |
| # size="pop", color="continent", hover_name="country", facet_col="continent", | |
| # log_x=True, size_max=45, range_x=[100,100000], range_y=[25,90]) | |
| #fig.write_html("/tmp/file.html") | |
| def collect_data(): | |
| import bme680 # python3 -m pip install bme680 | |
| connect_str = os.getenv('AZURE_STORAGE_CONNECTION_STRING') | |
| blob_service_client = BlobServiceClient.from_connection_string(connect_str) | |
| try: | |
| sensor = bme680.BME680(bme680.I2C_ADDR_PRIMARY) | |
| except IOError: | |
| sensor = bme680.BME680(bme680.I2C_ADDR_SECONDARY) | |
| db = get_db() | |
| sensor.set_gas_heater_temperature(320) # "Target temperature in degrees celsius, between 200 and 400" | |
| sensor.set_gas_heater_duration(150) # "Heating durations between 1 ms and 4032 ms" | |
| # sensor.select_gas_heater_profile(0) | |
| while True: | |
| sleep(45) | |
| if sensor.get_sensor_data(): | |
| insert_data(db, sensor.data, blob_service_client) | |
| else: | |
| print(f"[{int(time())}] get_sensor_data() => False") | |
| if __name__ == "__main__": | |
| from sys import argv | |
| if len(argv) > 1: | |
| assert argv[1] == '--plot' | |
| plot() | |
| else: | |
| collect_data() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment