226 lines
8.2 KiB
Python
Executable File
226 lines
8.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import datetime
|
|
from os import environ as env
|
|
from time import sleep
|
|
import json
|
|
|
|
import click
|
|
import configparser
|
|
from airthings import fetch_measurements, discover_devices
|
|
from influxdb import InfluxDBClient
|
|
from influxdb.exceptions import InfluxDBServerError
|
|
|
|
|
|
def read_config(file):
|
|
config = configparser.ConfigParser()
|
|
config.read(file)
|
|
return config
|
|
|
|
|
|
@click.group()
|
|
@click.option('--debug/--no-debug')
|
|
@click.option('-c', '--config', default="config.ini", help='give config file')
|
|
@click.pass_context
|
|
def cli(ctx, debug, config):
|
|
ctx.ensure_object(dict)
|
|
ctx.obj['DEBUG'] = debug
|
|
ctx.obj['CONFIG'] = config
|
|
if debug:
|
|
click.echo("Debug is enabled")
|
|
|
|
@cli.command()
|
|
@click.pass_context
|
|
def verify(ctx):
|
|
"""Verify your Influxdb configuration"""
|
|
config = read_config(ctx.obj['CONFIG'])
|
|
|
|
influx_host = env.get("InfluxdbHost", config['DEFAULT']['InfluxdbHost'])
|
|
influx_port = env.get("InfluxdbPort", config['DEFAULT']['InfluxdbPort'])
|
|
influx_user = env.get("InfluxdbUser", config['DEFAULT']['InfluxdbUser'])
|
|
influx_pass = env.get("InfluxdbPassword", config['DEFAULT']['InfluxdbPassword'])
|
|
influx_db = env.get("InfluxdbDatabase", config['DEFAULT']['InfluxdbDatabase'])
|
|
|
|
client = InfluxDBClient(influx_host, influx_port, influx_user, influx_pass, influx_db)
|
|
click.echo("Trying to connect to influxdb...")
|
|
try:
|
|
ping = client.ping()
|
|
click.echo("Success! Version: %s"% ping)
|
|
except InfluxDBClientError as e:
|
|
click.echo("An error occured: %s" % e)
|
|
|
|
@cli.command()
|
|
def identify():
|
|
"""Lists available sensors nearby"""
|
|
|
|
airthings_devices = fetch_measurements()
|
|
click.echo("Found %s Airthings device(s):" % len(airthings_devices))
|
|
for device in airthings_devices:
|
|
click.echo("=" * 36)
|
|
click.echo("\tMAC address: %s" % device.mac_address)
|
|
click.echo("\tIdentifier: %s" % device.identifier)
|
|
click.echo("\tModel: %s" % device.label)
|
|
click.echo("\tModel number: %s" % device.model_number)
|
|
click.echo("\tHas measurements:" + str(device.has_measurements))
|
|
click.echo("\tSensor capabilities:")
|
|
for sensor, supported in device.sensor_capabilities.items():
|
|
click.echo("\t" + sensor + "=" + "YES" if supported else "\t" + "NO")
|
|
click.echo("+" * 11 + "Measurements" + "+" * 11)
|
|
click.echo("\t %s" % device.humidity)
|
|
click.echo("\t %s" % device.radon_short_term_avg)
|
|
click.echo("\t %s" % device.radon_long_term_avg)
|
|
click.echo("\t %s" % device.temperature)
|
|
click.echo("\t %s" % device.atmospheric_pressure)
|
|
click.echo("\t %s" % device.co2)
|
|
click.echo("\t %s" % device.voc)
|
|
|
|
|
|
|
|
|
|
@cli.command()
|
|
@click.pass_context
|
|
def start(ctx):
|
|
"""
|
|
Start collecting data from your airthings sensors
|
|
"""
|
|
click.echo("Starting the Airthings to Influxdb Bridge")
|
|
click.echo("Reading the config...")
|
|
config = read_config(ctx.obj['CONFIG'])
|
|
|
|
influx_host = env.get("InfluxdbHost", config['DEFAULT']['InfluxdbHost'])
|
|
influx_port = env.get("InfluxdbPort", config['DEFAULT']['InfluxdbPort'])
|
|
influx_user = env.get("InfluxdbUser", config['DEFAULT']['InfluxdbUser'])
|
|
influx_pass = env.get("InfluxdbPassword", config['DEFAULT']['InfluxdbPassword'])
|
|
influx_db = env.get("InfluxdbDatabase", config['DEFAULT']['InfluxdbDatabase'])
|
|
interval = env.get("Interval", config['DEFAULT']['Interval'])
|
|
|
|
click.echo("Starting the Influxdb Client...")
|
|
|
|
client = InfluxDBClient(influx_host, influx_port, influx_user, influx_pass, influx_db)
|
|
|
|
data = []
|
|
|
|
click.echo("Starting sensor probing")
|
|
while True:
|
|
click.echo("Searching devices...")
|
|
airthings_devices = fetch_measurements()
|
|
click.echo("Found %s Airthings devices:" % len(airthings_devices))
|
|
for device in airthings_devices:
|
|
click.echo("=" * 36)
|
|
click.echo("\tMAC address: %s" % device.mac_address)
|
|
click.echo("\tIdentifier: %s" % device.identifier)
|
|
click.echo("\tModel: %s" % device.label)
|
|
click.echo("\tModel number: %s" % device.model_number)
|
|
click.echo("\tHas measurements: %s" % device.has_measurements)
|
|
|
|
click.echo("Collecting sensor data...")
|
|
now = datetime.datetime.now()
|
|
|
|
if device.humidity:
|
|
json_body = {
|
|
"measurement": "humidity",
|
|
"tags": {
|
|
"mac address": device.mac_address,
|
|
"identifier": device.identifier,
|
|
"model": device.label,
|
|
"model number": device.model_number
|
|
},
|
|
"time": now,
|
|
"fields": {
|
|
"value": device.humidity.value
|
|
}
|
|
}
|
|
data.append(json_body)
|
|
if device.radon_short_term_avg:
|
|
json_body = {
|
|
"measurement": "radon_short_term_avg",
|
|
"tags": {
|
|
"mac address": device.mac_address,
|
|
"identifier": device.identifier,
|
|
"model": device.label,
|
|
"model number": device.model_number
|
|
},
|
|
"time": now,
|
|
"fields": {
|
|
"value": device.radon_short_term_avg.value
|
|
}
|
|
}
|
|
data.append(json_body)
|
|
if device.radon_long_term_avg:
|
|
json_body = {
|
|
"measurement": "radon_long_term_avg",
|
|
"tags": {
|
|
"mac address": device.mac_address,
|
|
"identifier": device.identifier,
|
|
"model": device.label,
|
|
"model number": device.model_number
|
|
},
|
|
"time": now,
|
|
"fields": {
|
|
"value": device.radon_long_term_avg.value
|
|
}
|
|
}
|
|
data.append(json_body)
|
|
if device.temperature:
|
|
json_body = {
|
|
"measurement": "temperature",
|
|
"tags": {
|
|
"mac address": device.mac_address,
|
|
"identifier": device.identifier,
|
|
"model": device.label,
|
|
"model number": device.model_number
|
|
},
|
|
"time": now,
|
|
"fields": {
|
|
"value": device.temperature.value
|
|
}
|
|
}
|
|
data.append(json_body)
|
|
if device.co2:
|
|
json_body = {
|
|
"measurement": "co2",
|
|
"tags": {
|
|
"mac address": device.mac_address,
|
|
"identifier": device.identifier,
|
|
"model": device.label,
|
|
"model number": device.model_number
|
|
},
|
|
"time": now,
|
|
"fields": {
|
|
"value": device.co2.value
|
|
}
|
|
}
|
|
data.append(json_body)
|
|
if device.voc:
|
|
json_body = {
|
|
"measurement": "voc",
|
|
"tags": {
|
|
"mac address": device.mac_address,
|
|
"identifier": device.identifier,
|
|
"model": device.label,
|
|
"model number": device.model_number
|
|
},
|
|
"time": now,
|
|
"fields": {
|
|
"value": device.voc.value
|
|
}
|
|
}
|
|
data.append(json_body)
|
|
|
|
#write data
|
|
click.echo("Trying to send datapoints...")
|
|
|
|
try:
|
|
client.write_points(data)
|
|
click.echo("Sent!")
|
|
except InfluxDBServerError as e:
|
|
click.echo("An error occured: %s" % e)
|
|
click.echo("Storing data for now, waiting for the next interval.")
|
|
click.echo("Sleeping for %s seconds" % interval)
|
|
sleep(int(interval))
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
cli()
|