# /// script
# requires-python = ">=3.12"
# dependencies = [
#   "bme680",
#   "paho-mqtt"
# ]
# ///

#!/usr/bin/env python

# read bm3-680 sensor and publish to local MQTT

import bme680
import time
import json
import paho.mqtt.client as paho

mqttbroker="rpi-bram"
mqttport=1883
mqtttopic="bram/arbeit/bme680/"

start_time = time.time()
curr_time = time.time()
burn_in_time = 300

burn_in_data = []

def air_quality(hum_baseline, gas_baseline, hum, gas):

    gas_offset = gas - gas_baseline
    hum_offset = hum - hum_baseline

    # Calculate hum_score as the distance from the hum_baseline.
    if hum_offset > 0:
        hum_score = (100 - hum_baseline - hum_offset)
        hum_score /= (100 - hum_baseline)
        hum_score *= (hum_weighting * 100)

    else:
        hum_score = (hum_baseline + hum_offset)
        hum_score /= hum_baseline
        hum_score *= (hum_weighting * 100)

    # Calculate gas_score as the distance from the gas_baseline.
    if gas_offset > 0:
        gas_score = (gas / gas_baseline)
        gas_score *= (100 - (hum_weighting * 100))

    else:
        gas_score = 100 - (hum_weighting * 100)

    # Calculate air_quality_score.
    air_quality_score = hum_score + gas_score
    #if air_quality_score > 100:
    #    air_quality_score = 100
    return air_quality_score

    print('Gas: {0:.2f} Ohms,humidity: {1:.2f} %RH,air quality: {2:.2f}'.format(
        gas,
        hum,
        air_quality_score))

try:
    sensor = bme680.BME680(bme680.I2C_ADDR_PRIMARY)
except (RuntimeError, IOError):
    sensor = bme680.BME680(bme680.I2C_ADDR_SECONDARY)

# These calibration data can safely be commented
# out, if desired.

print('Calibration data:')
for name in dir(sensor.calibration_data):

    if not name.startswith('_'):
        value = getattr(sensor.calibration_data, name)

        if isinstance(value, int):
            print('{}: {}'.format(name, value))

# These oversampling settings can be tweaked to
# change the balance between accuracy and noise in
# the data.

sensor.set_humidity_oversample(bme680.OS_2X)
sensor.set_pressure_oversample(bme680.OS_4X)
sensor.set_temperature_oversample(bme680.OS_8X)
sensor.set_filter(bme680.FILTER_SIZE_3)
sensor.set_gas_status(bme680.ENABLE_GAS_MEAS)

print('\n\nInitial reading:')
for name in dir(sensor.data):
    value = getattr(sensor.data, name)

    if not name.startswith('_'):
        print('{}: {}'.format(name, value))

sensor.set_gas_heater_temperature(320)
sensor.set_gas_heater_duration(150)
sensor.select_gas_heater_profile(0)

# Up to 10 heater profiles can be configured, each
# with their own temperature and duration.
# sensor.set_gas_heater_profile(200, 150, nb_profile=1)
# sensor.select_gas_heater_profile(1)

############# burn-in for air quality measurment #############
try:
    # Collect gas resistance burn-in values, then use the average
    # of the last 50 values to set the upper limit for calculating
    # gas_baseline.
    print('Collecting gas resistance burn-in data for 5 mins\n')
    while curr_time - start_time < burn_in_time:
        curr_time = time.time()
        if sensor.get_sensor_data() and sensor.data.heat_stable:
            gas = sensor.data.gas_resistance
            burn_in_data.append(gas)
            print('Gas: {0} Ohms'.format(gas))
            time.sleep(1)

    gas_baseline = sum(burn_in_data[-50:]) / 50.0

    # Set the humidity baseline to 40%, an optimal indoor humidity.
    hum_baseline = 40.0

    # This sets the balance between humidity and gas reading in the
    # calculation of air_quality_score (25:75, humidity:gas)
    hum_weighting = 0.25

    print('Gas baseline: {0} Ohms, humidity baseline: {1:.2f} %RH\n'.format(
        gas_baseline,
        hum_baseline))

except KeyboardInterrupt:
    pass

############ read data continuously ##############
try:
    while True:
        if sensor.get_sensor_data():
            if sensor.data.heat_stable:
                gas = sensor.data.gas_resistance
            else:
                gas = 0

            air = air_quality(hum_baseline, gas_baseline, sensor.data.humidity, gas)

            payload = { 'currenttime': time.strftime("%Y-%m-%d %H:%M:%s"),
            'temperature':  sensor.data.temperature,
            'pressure': sensor.data.pressure,
            'humidity': sensor.data.humidity,
            'gas': gas,
            'air_quality': air
            }

            payload_json = json.dumps(payload)

            #print (payload_json)

            mqttcli = paho.Client("cam1")                            #create client object
            mqttcli.connect(mqttbroker,mqttport)                     #establish connection
            ret= mqttcli.publish(mqtttopic,payload_json)             #publish
            mqttcli.disconnect()

        time.sleep(10)

except KeyboardInterrupt:
    pass
