202 lines
6.2 KiB
Python
202 lines
6.2 KiB
Python
"""Support for monitoring Repetier Server Sensors."""
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
import time
|
|
|
|
from homeassistant.components.sensor import SensorDeviceClass, SensorEntity
|
|
from homeassistant.core import HomeAssistant, callback
|
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
from homeassistant.helpers.typing import UNDEFINED, ConfigType, DiscoveryInfoType
|
|
from homeassistant.util import dt as dt_util
|
|
|
|
from . import REPETIER_API, SENSOR_TYPES, UPDATE_SIGNAL, RepetierSensorEntityDescription
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
def setup_platform(
|
|
hass: HomeAssistant,
|
|
config: ConfigType,
|
|
add_entities: AddEntitiesCallback,
|
|
discovery_info: DiscoveryInfoType | None = None,
|
|
) -> None:
|
|
"""Set up the available Repetier Server sensors."""
|
|
if discovery_info is None:
|
|
return
|
|
|
|
sensor_map = {
|
|
"bed_temperature": RepetierTempSensor,
|
|
"extruder_temperature": RepetierTempSensor,
|
|
"chamber_temperature": RepetierTempSensor,
|
|
"current_state": RepetierSensor,
|
|
"current_job": RepetierJobSensor,
|
|
"job_end": RepetierJobEndSensor,
|
|
"job_start": RepetierJobStartSensor,
|
|
}
|
|
|
|
sensors_info: list[dict] = discovery_info["sensors"]
|
|
entities = []
|
|
for info in sensors_info:
|
|
printer_name = info["printer_name"]
|
|
api = hass.data[REPETIER_API][printer_name]
|
|
printer_id = info["printer_id"]
|
|
sensor_type = info["sensor_type"]
|
|
temp_id = info["temp_id"]
|
|
description = SENSOR_TYPES[sensor_type]
|
|
name_suffix = "" if description.name is UNDEFINED else description.name
|
|
name = f"{info['name']}{name_suffix}"
|
|
if temp_id is not None:
|
|
_LOGGER.debug("%s Temp_id: %s", sensor_type, temp_id)
|
|
name = f"{name}{temp_id}"
|
|
sensor_class = sensor_map[sensor_type]
|
|
entity = sensor_class(api, temp_id, name, printer_id, description)
|
|
entities.append(entity)
|
|
|
|
add_entities(entities, True)
|
|
|
|
|
|
class RepetierSensor(SensorEntity):
|
|
"""Class to create and populate a Repetier Sensor."""
|
|
|
|
entity_description: RepetierSensorEntityDescription
|
|
_attr_should_poll = False
|
|
|
|
def __init__(
|
|
self,
|
|
api,
|
|
temp_id,
|
|
name,
|
|
printer_id,
|
|
description: RepetierSensorEntityDescription,
|
|
) -> None:
|
|
"""Init new sensor."""
|
|
self.entity_description = description
|
|
self._api = api
|
|
self._attributes: dict = {}
|
|
self._temp_id = temp_id
|
|
self._printer_id = printer_id
|
|
self._state = None
|
|
|
|
self._attr_name = name
|
|
self._attr_available = False
|
|
|
|
@property
|
|
def extra_state_attributes(self):
|
|
"""Return sensor attributes."""
|
|
return self._attributes
|
|
|
|
@property
|
|
def native_value(self):
|
|
"""Return sensor state."""
|
|
return self._state
|
|
|
|
@callback
|
|
def update_callback(self):
|
|
"""Get new data and update state."""
|
|
self.async_schedule_update_ha_state(True)
|
|
|
|
async def async_added_to_hass(self):
|
|
"""Connect update callbacks."""
|
|
self.async_on_remove(
|
|
async_dispatcher_connect(self.hass, UPDATE_SIGNAL, self.update_callback)
|
|
)
|
|
|
|
def _get_data(self):
|
|
"""Return new data from the api cache."""
|
|
sensor_type = self.entity_description.key
|
|
data = self._api.get_data(self._printer_id, sensor_type, self._temp_id)
|
|
if data is None:
|
|
_LOGGER.debug("Data not found for %s and %s", sensor_type, self._temp_id)
|
|
self._attr_available = False
|
|
return None
|
|
self._attr_available = True
|
|
return data
|
|
|
|
def update(self):
|
|
"""Update the sensor."""
|
|
if (data := self._get_data()) is None:
|
|
return
|
|
state = data.pop("state")
|
|
_LOGGER.debug("Printer %s State %s", self.name, state)
|
|
self._attributes.update(data)
|
|
self._state = state
|
|
|
|
|
|
class RepetierTempSensor(RepetierSensor):
|
|
"""Represent a Repetier temp sensor."""
|
|
|
|
@property
|
|
def native_value(self):
|
|
"""Return sensor state."""
|
|
if self._state is None:
|
|
return None
|
|
return round(self._state, 2)
|
|
|
|
def update(self):
|
|
"""Update the sensor."""
|
|
if (data := self._get_data()) is None:
|
|
return
|
|
state = data.pop("state")
|
|
temp_set = data["temp_set"]
|
|
_LOGGER.debug("Printer %s Setpoint: %s, Temp: %s", self.name, temp_set, state)
|
|
self._attributes.update(data)
|
|
self._state = state
|
|
|
|
|
|
class RepetierJobSensor(RepetierSensor):
|
|
"""Represent a Repetier job sensor."""
|
|
|
|
@property
|
|
def native_value(self):
|
|
"""Return sensor state."""
|
|
if self._state is None:
|
|
return None
|
|
return round(self._state, 2)
|
|
|
|
|
|
class RepetierJobEndSensor(RepetierSensor):
|
|
"""Class to create and populate a Repetier Job End timestamp Sensor."""
|
|
|
|
_attr_device_class = SensorDeviceClass.TIMESTAMP
|
|
|
|
def update(self):
|
|
"""Update the sensor."""
|
|
if (data := self._get_data()) is None:
|
|
return
|
|
job_name = data["job_name"]
|
|
start = data["start"]
|
|
print_time = data["print_time"]
|
|
from_start = data["from_start"]
|
|
time_end = start + round(print_time, 0)
|
|
self._state = dt_util.utc_from_timestamp(time_end)
|
|
remaining = print_time - from_start
|
|
remaining_secs = int(round(remaining, 0))
|
|
_LOGGER.debug(
|
|
"Job %s remaining %s",
|
|
job_name,
|
|
time.strftime("%H:%M:%S", time.gmtime(remaining_secs)),
|
|
)
|
|
|
|
|
|
class RepetierJobStartSensor(RepetierSensor):
|
|
"""Class to create and populate a Repetier Job Start timestamp Sensor."""
|
|
|
|
_attr_device_class = SensorDeviceClass.TIMESTAMP
|
|
|
|
def update(self):
|
|
"""Update the sensor."""
|
|
if (data := self._get_data()) is None:
|
|
return
|
|
job_name = data["job_name"]
|
|
start = data["start"]
|
|
from_start = data["from_start"]
|
|
self._state = dt_util.utc_from_timestamp(start)
|
|
elapsed_secs = int(round(from_start, 0))
|
|
_LOGGER.debug(
|
|
"Job %s elapsed %s",
|
|
job_name,
|
|
time.strftime("%H:%M:%S", time.gmtime(elapsed_secs)),
|
|
)
|