1 """Support for Repetier-Server sensors."""
3 from __future__
import annotations
5 from dataclasses
import dataclass
6 from datetime
import timedelta
9 import pyrepetierng
as pyrepetier
10 import voluptuous
as vol
16 CONF_MONITORED_CONDITIONS,
31 _LOGGER = logging.getLogger(__name__)
33 DEFAULT_NAME =
"RepetierServer"
35 REPETIER_API =
"repetier_api"
37 UPDATE_SIGNAL =
"repetier_update_signal"
39 TEMP_DATA = {
"tempset":
"temp_set",
"tempread":
"state",
"output":
"output"}
44 """API methods for properties."""
46 offline: dict[str, str |
None]
48 temp_data: dict[str, str] |
None =
None
49 attribute: str |
None =
None
52 API_PRINTER_METHODS: dict[str, APIMethods] = {
54 offline={
"heatedbeds":
None,
"state":
"off"},
55 state={
"heatedbeds":
"temp_data"},
57 attribute=
"heatedbeds",
60 offline={
"extruder":
None,
"state":
"off"},
61 state={
"extruder":
"temp_data"},
66 offline={
"heatedchambers":
None,
"state":
"off"},
67 state={
"heatedchambers":
"temp_data"},
69 attribute=
"heatedchambers",
72 offline={
"state":
None},
75 "activeextruder":
"active_extruder",
76 "hasxhome":
"x_homed",
77 "hasyhome":
"y_homed",
78 "haszhome":
"z_homed",
79 "firmware":
"firmware",
80 "firmwareurl":
"firmware_url",
84 offline={
"job":
None,
"state":
"off"},
89 "totallines":
"total_lines",
90 "linessent":
"lines_sent",
91 "oflayer":
"total_layers",
92 "layer":
"current_layer",
93 "speedmultiply":
"feed_rate",
94 "flowmultiply":
"flow",
101 offline={
"job":
None,
"state":
"off",
"start":
None,
"printtime":
None},
105 "printtime":
"print_time",
106 "printedtimecomp":
"from_start",
114 "printedtimecomp":
None,
116 state={
"job":
"job_name",
"start":
"start",
"printedtimecomp":
"from_start"},
122 """Validate that printers have an unique name."""
123 names = [util_slugify(printer[CONF_NAME])
for printer
in value]
124 vol.Schema(vol.Unique())(names)
128 @dataclass(frozen=True)
130 """Mixin for required keys."""
135 @dataclass(frozen=True)
138 SensorEntityDescription, RepetierRequiredKeysMixin
140 """Describes Repetier sensor entity."""
143 SENSOR_TYPES: dict[str, RepetierSensorEntityDescription] = {
145 key=
"bed_temperature",
147 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
149 device_class=SensorDeviceClass.TEMPERATURE,
152 key=
"extruder_temperature",
154 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
156 device_class=SensorDeviceClass.TEMPERATURE,
159 key=
"chamber_temperature",
161 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
163 device_class=SensorDeviceClass.TEMPERATURE,
168 icon=
"mdi:printer-3d",
173 native_unit_of_measurement=PERCENTAGE,
174 icon=
"mdi:file-percent",
180 icon=
"mdi:clock-end",
186 icon=
"mdi:clock-start",
191 SENSOR_SCHEMA = vol.Schema(
193 vol.Optional(CONF_MONITORED_CONDITIONS, default=
list(SENSOR_TYPES)): vol.All(
194 cv.ensure_list, [vol.In(SENSOR_TYPES)]
196 vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
200 CONFIG_SCHEMA = vol.Schema(
207 vol.Required(CONF_API_KEY): cv.string,
208 vol.Required(CONF_HOST): cv.string,
209 vol.Optional(CONF_PORT, default=3344): cv.port,
210 vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
211 vol.Optional(CONF_SENSORS, default={}): SENSOR_SCHEMA,
215 has_all_unique_names,
218 extra=vol.ALLOW_EXTRA,
222 def setup(hass: HomeAssistant, config: ConfigType) -> bool:
223 """Set up the Repetier Server component."""
224 hass.data[REPETIER_API] = {}
226 for repetier
in config[DOMAIN]:
227 _LOGGER.debug(
"Repetier server config %s", repetier[CONF_HOST])
229 url = f
"http://{repetier[CONF_HOST]}"
230 port = repetier[CONF_PORT]
231 api_key = repetier[CONF_API_KEY]
233 client = pyrepetier.Repetier(url=url, port=port, apikey=api_key)
235 printers = client.getprinters()
240 sensors = repetier[CONF_SENSORS][CONF_MONITORED_CONDITIONS]
241 api =
PrinterAPI(hass, client, printers, sensors, repetier[CONF_NAME], config)
245 hass.data[REPETIER_API][repetier[CONF_NAME]] = api
251 """Handle the printer API."""
253 def __init__(self, hass, client, printers, sensors, conf_name, config):
254 """Set up instance."""
263 def get_data(self, printer_id, sensor_type, temp_id):
264 """Get data from the state cache."""
265 printer = self.
printersprinters[printer_id]
266 methods = API_PRINTER_METHODS[sensor_type]
267 for prop, offline
in methods.offline.items():
268 if getattr(printer, prop) == offline:
273 for prop, attr
in methods.state.items():
274 prop_data = getattr(printer, prop)
275 if attr ==
"temp_data":
276 temp_methods = methods.temp_data
or {}
277 for temp_prop, temp_attr
in temp_methods.items():
278 data[temp_attr] = getattr(prop_data[temp_id], temp_prop)
280 data[attr] = prop_data
284 """Update the state cache from the printer API."""
285 for printer
in self.
printersprinters:
292 for pidx, printer
in enumerate(self.
printersprinters):
293 for sensor_type
in self.
sensorssensors:
295 info[
"sensor_type"] = sensor_type
296 info[
"printer_id"] = pidx
297 info[
"name"] = printer.slug
298 info[
"printer_name"] = self.
conf_nameconf_name
300 known = f
"{printer.slug}-{sensor_type}"
304 methods = API_PRINTER_METHODS[sensor_type]
305 if "temp_data" in methods.state.values():
306 prop_data = getattr(printer, methods.attribute
or "")
307 if prop_data
is None:
309 for idx, _
in enumerate(prop_data):
310 prop_info = info.copy()
311 prop_info[
"temp_id"] = idx
312 sensor_info.append(prop_info)
314 info[
"temp_id"] =
None
315 sensor_info.append(info)
321 self.
_hass_hass,
"sensor", DOMAIN, {
"sensors": sensor_info}, self.
configconfig
def get_data(self, printer_id, sensor_type, temp_id)
def update(self, now=None)
def __init__(self, hass, client, printers, sensors, conf_name, config)
bool add(self, _T matcher)
def has_all_unique_names(value)
bool setup(HomeAssistant hass, ConfigType config)
None load_platform(core.HomeAssistant hass, Platform|str component, str platform, DiscoveryInfoType|None discovered, ConfigType hass_config)
None dispatcher_send(HomeAssistant hass, str signal, *Any args)