2023-04-25 18:31:17 +00:00
|
|
|
import logging
|
2022-06-13 10:59:18 +00:00
|
|
|
import os
|
2023-04-25 18:31:17 +00:00
|
|
|
import sys
|
|
|
|
|
2024-02-06 21:22:47 +00:00
|
|
|
from prometheus_client import Gauge
|
|
|
|
from pyhap.accessory import Accessory
|
2022-02-21 20:24:05 +00:00
|
|
|
from pyhap.const import CATEGORY_SENSOR
|
2024-02-07 19:11:25 +00:00
|
|
|
import bme680
|
2023-04-25 18:31:17 +00:00
|
|
|
|
2024-02-06 21:22:47 +00:00
|
|
|
from app.config import Settings
|
2022-02-21 20:24:05 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Bme680Sensor(Accessory):
|
|
|
|
"""Implementation of a mock temperature sensor accessory."""
|
|
|
|
|
|
|
|
category = CATEGORY_SENSOR # This is for the icon in the iOS Home app.
|
|
|
|
|
2024-02-08 20:49:34 +00:00
|
|
|
def __init__(self, driver, *, aid=None, settings: Settings):
|
2022-02-21 20:24:05 +00:00
|
|
|
"""Here, we just store a reference to the current temperature characteristic and
|
|
|
|
add a method that will be executed every time its value changes.
|
|
|
|
"""
|
|
|
|
# If overriding this method, be sure to call the super's implementation first.
|
2024-02-08 20:49:34 +00:00
|
|
|
super().__init__(driver, settings.hap.bridge.bme680.name, aid=aid)
|
2022-02-21 20:24:05 +00:00
|
|
|
|
2024-02-06 21:22:47 +00:00
|
|
|
self.settings = settings
|
|
|
|
self.sensor = bme680.BME680(
|
|
|
|
settings.hap.bridge.bme680.address or bme680.I2C_ADDR_PRIMARY
|
|
|
|
)
|
2022-02-21 20:24:05 +00:00
|
|
|
|
|
|
|
self.sensor.set_humidity_oversample(bme680.OS_2X)
|
|
|
|
self.sensor.set_pressure_oversample(bme680.OS_4X)
|
|
|
|
self.sensor.set_temperature_oversample(bme680.OS_8X)
|
|
|
|
self.sensor.set_filter(bme680.FILTER_SIZE_3)
|
|
|
|
|
2022-06-13 10:59:18 +00:00
|
|
|
if os.getenv("ENABLE_GAS_MEASUREMENT", "false") == "true":
|
|
|
|
self.sensor.set_gas_status(bme680.ENABLE_GAS_MEAS)
|
|
|
|
self.sensor.set_gas_heater_temperature(320)
|
|
|
|
self.sensor.set_gas_heater_duration(150)
|
|
|
|
self.sensor.select_gas_heater_profile(0)
|
|
|
|
|
2022-06-13 10:37:49 +00:00
|
|
|
self._temperature_metric = Gauge(
|
2022-06-13 11:04:10 +00:00
|
|
|
"bme680_temperature_celsius", "The temperature measurement in celsius."
|
2022-06-13 10:37:49 +00:00
|
|
|
)
|
|
|
|
self._humidity_metric = Gauge(
|
|
|
|
"bme680_humidity_rh", "The humidity measurement in relative humidity."
|
|
|
|
)
|
|
|
|
self._pressure_metric = Gauge(
|
|
|
|
"bme680_pressure_hpa", "The pressure measurement in hectopascals."
|
|
|
|
)
|
|
|
|
self._gas_resistance_metric = Gauge(
|
|
|
|
"bme860_gas_resistance_ohm", "The gas resistance measurement in ohms."
|
|
|
|
)
|
|
|
|
|
2022-02-21 20:24:05 +00:00
|
|
|
# Add the services that this Accessory will support with add_preload_service here
|
2022-06-13 10:37:49 +00:00
|
|
|
temp_service = self.add_preload_service("TemperatureSensor")
|
|
|
|
humidity_service = self.add_preload_service("HumiditySensor")
|
2022-02-21 20:24:05 +00:00
|
|
|
|
2022-06-13 10:37:49 +00:00
|
|
|
self.temp_value = temp_service.get_characteristic("CurrentTemperature")
|
|
|
|
self.humidity_value = humidity_service.get_characteristic(
|
|
|
|
"CurrentRelativeHumidity"
|
|
|
|
)
|
2022-02-21 20:24:05 +00:00
|
|
|
|
2023-04-25 18:31:17 +00:00
|
|
|
def _run(self):
|
2022-02-21 20:24:05 +00:00
|
|
|
if self.sensor.get_sensor_data():
|
|
|
|
self.temp_value.set_value(self.sensor.data.temperature)
|
|
|
|
self.humidity_value.set_value(self.sensor.data.humidity)
|
|
|
|
|
2022-06-13 10:37:49 +00:00
|
|
|
# Update prometheus metrics.
|
|
|
|
self._temperature_metric.set(self.sensor.data.temperature)
|
|
|
|
self._humidity_metric.set(self.sensor.data.humidity)
|
|
|
|
self._pressure_metric.set(self.sensor.data.pressure)
|
|
|
|
|
|
|
|
if self.sensor.data.heat_stable:
|
|
|
|
self._gas_resistance_metric.set(self.sensor.data.gas_resistance)
|
|
|
|
|
2023-04-25 18:32:02 +00:00
|
|
|
@Accessory.run_at_interval(120)
|
2023-04-25 18:31:17 +00:00
|
|
|
def run(self):
|
2023-06-06 20:33:44 +00:00
|
|
|
"""
|
2024-02-06 21:22:47 +00:00
|
|
|
This function runs the accessory. It polls for data and publishes it at the given interval.
|
2023-04-25 18:31:17 +00:00
|
|
|
"""
|
|
|
|
try:
|
2024-02-08 21:06:36 +00:00
|
|
|
logging.info("Reading data from BME680 sensor.")
|
2023-04-25 18:31:17 +00:00
|
|
|
self._run()
|
|
|
|
except IOError as e:
|
|
|
|
# This happens from time to time, best we stop and let systemd restart us.
|
2024-02-06 21:22:47 +00:00
|
|
|
logging.critical("Failed to run BME680.")
|
|
|
|
sys.exit(1)
|
2023-04-25 18:31:17 +00:00
|
|
|
|
2022-02-21 20:24:05 +00:00
|
|
|
def stop(self):
|
|
|
|
"""We override this method to clean up any resources or perform final actions, as
|
|
|
|
this is called by the AccessoryDriver when the Accessory is being stopped.
|
|
|
|
"""
|
2022-06-13 10:37:49 +00:00
|
|
|
print("Stopping accessory.")
|