sensor: add history field options
Signed-off-by: Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
parent
b60e6dc311
commit
81899e04fd
@ -11,7 +11,7 @@ from __future__ import annotations
|
|||||||
import logging
|
import logging
|
||||||
from collections import defaultdict, deque
|
from collections import defaultdict, deque
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from ..common import RequestType
|
from ..common import RequestType, HistoryFieldData
|
||||||
|
|
||||||
# Annotation imports
|
# Annotation imports
|
||||||
from typing import (
|
from typing import (
|
||||||
@ -24,12 +24,14 @@ from typing import (
|
|||||||
Type,
|
Type,
|
||||||
TYPE_CHECKING,
|
TYPE_CHECKING,
|
||||||
Union,
|
Union,
|
||||||
|
Callable
|
||||||
)
|
)
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ..confighelper import ConfigHelper
|
from ..confighelper import ConfigHelper
|
||||||
from ..common import WebRequest
|
from ..common import WebRequest
|
||||||
from .mqtt import MQTTClient
|
from .mqtt import MQTTClient
|
||||||
|
from .history import History
|
||||||
|
|
||||||
SENSOR_UPDATE_TIME = 1.0
|
SENSOR_UPDATE_TIME = 1.0
|
||||||
SENSOR_EVENT_NAME = "sensors:sensor_update"
|
SENSOR_EVENT_NAME = "sensors:sensor_update"
|
||||||
@ -56,6 +58,57 @@ class BaseSensor:
|
|||||||
self.values: DefaultDict[str, Deque[Union[int, float]]] = defaultdict(
|
self.values: DefaultDict[str, Deque[Union[int, float]]] = defaultdict(
|
||||||
lambda: deque(maxlen=store_size)
|
lambda: deque(maxlen=store_size)
|
||||||
)
|
)
|
||||||
|
history: History = self.server.lookup_component("history")
|
||||||
|
self.field_info: Dict[str, List[HistoryFieldData]] = {}
|
||||||
|
all_opts = list(config.get_options().keys())
|
||||||
|
cfg_name = config.get_name()
|
||||||
|
hist_field_prefix = "history_field_"
|
||||||
|
for opt in all_opts:
|
||||||
|
if not opt.startswith(hist_field_prefix):
|
||||||
|
continue
|
||||||
|
name = opt[len(hist_field_prefix):]
|
||||||
|
field_cfg: Dict[str, str] = config.getdict(opt)
|
||||||
|
ident: Optional[str] = field_cfg.pop("parameter", None)
|
||||||
|
if ident is None:
|
||||||
|
raise config.error(
|
||||||
|
f"[{cfg_name}]: option '{opt}', key 'parameter' must be"
|
||||||
|
f"specified"
|
||||||
|
)
|
||||||
|
do_init: str = field_cfg.pop("init_tracker", "false").lower()
|
||||||
|
reset_cb = self._gen_reset_callback(ident) if do_init == "true" else None
|
||||||
|
excl_paused: str = field_cfg.pop("exclude_paused", "false").lower()
|
||||||
|
report_total: str = field_cfg.pop("report_total", "false").lower()
|
||||||
|
report_max: str = field_cfg.pop("report_maximum", "false").lower()
|
||||||
|
precision: Optional[str] = field_cfg.pop("precision", None)
|
||||||
|
try:
|
||||||
|
fdata = HistoryFieldData(
|
||||||
|
name,
|
||||||
|
cfg_name,
|
||||||
|
field_cfg.pop("desc", f"{ident} tracker"),
|
||||||
|
field_cfg.pop("strategy", "basic"),
|
||||||
|
units=field_cfg.pop("units", None),
|
||||||
|
reset_callback=reset_cb,
|
||||||
|
exclude_paused=excl_paused == "true",
|
||||||
|
report_total=report_total == "true",
|
||||||
|
report_maximum=report_max == "true",
|
||||||
|
precision=int(precision) if precision is not None else None,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
raise config.error(
|
||||||
|
f"[{cfg_name}]: option '{opt}', error encountered during "
|
||||||
|
f"sensor field configuration: {e}"
|
||||||
|
) from e
|
||||||
|
for key in field_cfg.keys():
|
||||||
|
self.server.add_warning(
|
||||||
|
f"[{cfg_name}]: Option '{opt}' contains invalid key '{key}'"
|
||||||
|
)
|
||||||
|
self.field_info.setdefault(ident, []).append(fdata)
|
||||||
|
history.register_auxiliary_field(fdata)
|
||||||
|
|
||||||
|
def _gen_reset_callback(self, param_name: str) -> Callable[[], float]:
|
||||||
|
def on_reset() -> float:
|
||||||
|
return self.last_measurements.get(param_name, 0)
|
||||||
|
return on_reset
|
||||||
|
|
||||||
def _update_sensor_value(self, eventtime: float) -> None:
|
def _update_sensor_value(self, eventtime: float) -> None:
|
||||||
"""
|
"""
|
||||||
@ -108,6 +161,7 @@ class MQTTSensor(BaseSensor):
|
|||||||
context = {
|
context = {
|
||||||
"payload": payload.decode(),
|
"payload": payload.decode(),
|
||||||
"set_result": partial(_set_result, store=measurements),
|
"set_result": partial(_set_result, store=measurements),
|
||||||
|
"log_debug": logging.debug
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -118,11 +172,12 @@ class MQTTSensor(BaseSensor):
|
|||||||
else:
|
else:
|
||||||
self.error_state = None
|
self.error_state = None
|
||||||
self.last_measurements = measurements
|
self.last_measurements = measurements
|
||||||
logging.debug(
|
for name, value in measurements.items():
|
||||||
"Received updated sensor value for %s: %s",
|
fdata_list = self.field_info.get(name)
|
||||||
self.name,
|
if fdata_list is None:
|
||||||
self.last_measurements,
|
continue
|
||||||
)
|
for fdata in fdata_list:
|
||||||
|
fdata.tracker.update(value)
|
||||||
|
|
||||||
async def _on_mqtt_disconnected(self):
|
async def _on_mqtt_disconnected(self):
|
||||||
self.error_state = "MQTT Disconnected"
|
self.error_state = "MQTT Disconnected"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user