Skip to content

Commit 32c4c93

Browse files
committed
Be more specific on the sensors added to the websocket, also add a new way to tell the connector that a new list of temperatures names is available
1 parent 101b40a commit 32c4c93

File tree

2 files changed

+134
-42
lines changed

2 files changed

+134
-42
lines changed

octoprint_moonraker_connector/client.py

Lines changed: 109 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -138,18 +138,27 @@ class Configfile(BaseModel):
138138

139139

140140
class TemperatureDataPoint:
141+
type: str = "temperature_sensor"
142+
id: str = ""
143+
hadTarget: bool = True
141144
actual: float = 0.0
142145
target: float = 0.0
143146

144-
def __init__(self, actual: float = 0.0, target: float = 0.0):
147+
def __init__(self, type: str = "temperature_sensor", id: str = "", hasTarget: bool = True, actual: float = 0.0, target: float = 0.0):
148+
self.type = type
149+
self.id = id
150+
self.hasTarget = hasTarget
145151
self.actual = actual
146152
self.target = target
147153

148154
def __str__(self):
149-
return f"{self.actual} / {self.target}"
155+
if self.hasTarget:
156+
return f"{self.actual} / {self.target}"
157+
else:
158+
return f"{self.actual}"
150159

151160
def __repr__(self):
152-
return f"TemperatureDataPoint({self.actual}, {self.target})"
161+
return f"TemperatureDataPoint({self.type}, {self.id}, {self.hasTarget}, {self.actual}, {self.target})"
153162

154163

155164
class KlipperState(enum.Enum):
@@ -245,6 +254,11 @@ def on_moonraker_print_detected(
245254
def on_moonraker_server_info(self, server_info: dict[str, Any]) -> None:
246255
pass
247256

257+
def on_moonraker_temperature_store_update(
258+
self, data: dict[str, TemperatureDataPoint]
259+
) -> None:
260+
pass
261+
248262
def on_moonraker_file_tree_updated(
249263
self, root: str, path: str, tree: dict[str, dict[str, InternalFile]]
250264
) -> None:
@@ -300,15 +314,12 @@ class MoonrakerClient(JsonRpcClient):
300314
WEBSOCKET_URL = "ws://{host}:{port}/websocket"
301315
HTTP_URL = "http://{host}:{port}"
302316

303-
GENERIC_HEATER_PREFIX = "heater_generic "
304317
GENERIC_EXTRUDER_PREFIX = "extruder"
305-
GENERIC_TEMPERATURE_FAN_PREFIX = "temperature_fan "
306-
GENERIC_TEMPERATURE_PROBE_PREFIX = "temperature_probe "
307-
GENERIC_TEMPERATURE_SENSOR_PREFIX = "temperature_sensor "
308318
GENERIC_TMC_PREFIX = "tmc"
309319
TMC_HAVE_TEMPERATURE = [
310320
"tmc2240",
311321
]
322+
HEATERS = ();
312323
MACRO_PREFIX = "gcode_macro "
313324

314325
RELEVANT_PRINTER_OBJECTS = (
@@ -323,10 +334,6 @@ class MoonrakerClient(JsonRpcClient):
323334
x
324335
for x in obj_list
325336
if x.startswith(MoonrakerClient.GENERIC_EXTRUDER_PREFIX)
326-
or x.startswith(MoonrakerClient.GENERIC_HEATER_PREFIX)
327-
or x.startswith(MoonrakerClient.GENERIC_TEMPERATURE_FAN_PREFIX)
328-
or x.startswith(MoonrakerClient.GENERIC_TEMPERATURE_PROBE_PREFIX)
329-
or x.startswith(MoonrakerClient.GENERIC_TEMPERATURE_SENSOR_PREFIX)
330337
or x.startswith(MoonrakerClient.GENERIC_TMC_PREFIX)
331338
or x.startswith(MoonrakerClient.MACRO_PREFIX)
332339
],
@@ -355,6 +362,7 @@ def __init__(
355362
self._klipper_state_subscription = False
356363
self._subbed_objs: list[str] = []
357364

365+
self._temperature_store_received = False
358366
self._log_history_received = False
359367

360368
self._heaters: list[str] = []
@@ -527,9 +535,10 @@ def on_server_info(future: Future) -> None:
527535
f"Connected to Moonraker {moonraker_version}, API version {api_version}",
528536
)
529537

538+
self.get_printer_config()
530539
self.fetch_console_history()
531540
self.fetch_job_history()
532-
self.subscribe_to_updates()
541+
#self.subscribe_to_updates()
533542

534543
else:
535544
# log error
@@ -538,7 +547,7 @@ def on_server_info(future: Future) -> None:
538547
self._dual_log(logging.ERROR, error)
539548

540549
except Exception as exc:
541-
self._logger.exception("Error while retrieving server info")
550+
self._logger.exception(f"Error while retrieving server info: {exc}")
542551
error_str = f"Error while retrieving server info: {str(exc)}. Please check moonraker.log for details."
543552
self._listener.on_moonraker_disconnected(error=error_str)
544553

@@ -560,7 +569,7 @@ def on_printer_objects(future: Future) -> None:
560569
obj_list = printer_objects.get("objects", [])
561570

562571
matched_objs = []
563-
for obj in self.RELEVANT_PRINTER_OBJECTS:
572+
for obj in self.RELEVANT_PRINTER_OBJECTS + self.HEATERS:
564573
if isinstance(obj, str) and obj in obj_list:
565574
matched_objs.append(obj)
566575

@@ -581,11 +590,8 @@ def on_printer_objects(future: Future) -> None:
581590
for obj in matched_objs
582591
if obj in ("heater_bed")
583592
or obj.startswith(self.GENERIC_EXTRUDER_PREFIX)
584-
or obj.startswith(self.GENERIC_HEATER_PREFIX)
585-
or obj.startswith(self.GENERIC_TEMPERATURE_FAN_PREFIX)
586-
or obj.startswith(self.GENERIC_TEMPERATURE_PROBE_PREFIX)
587-
or obj.startswith(self.GENERIC_TEMPERATURE_SENSOR_PREFIX)
588593
or obj.startswith(self.GENERIC_TMC_PREFIX)
594+
or obj in self.HEATERS
589595
]
590596

591597
self.query_printer_objects(matched_objs)
@@ -640,6 +646,21 @@ def on_result(future: Future) -> None:
640646
future.add_done_callback(on_result)
641647
return future
642648

649+
def get_printer_config(self) -> Future:
650+
def on_result(future: Future) -> None:
651+
try:
652+
results = future.result()
653+
654+
config = results["status"]["configfile"]["config"]
655+
self.fetch_temperature_store(config=config)
656+
except Exception as e:
657+
self._logger.exception(f"Error while fetching klipper config: {e}")
658+
659+
params = {"objects": {"configfile": None}}
660+
self.call_method("printer.objects.query", params=params).add_done_callback(
661+
on_result
662+
)
663+
643664
def subscribe_printer_objects(self, objs: list[str] = None) -> Future:
644665
if objs is None:
645666
objs = self._subbed_objs
@@ -674,6 +695,53 @@ def on_status(future: Future) -> None:
674695
)
675696
return result_future
676697

698+
def fetch_temperature_store(self, config: dict) -> Future:
699+
def on_result(future: Future) -> None:
700+
try:
701+
results = future.result()
702+
for section in results:
703+
if section.startswith(self.GENERIC_EXTRUDER_PREFIX):
704+
continue;
705+
706+
if section not in config:
707+
self._logger.warning(f"{section} not found in config")
708+
continue
709+
710+
sectionconfig = config[section]
711+
if "gcode_id" not in sectionconfig:
712+
self._logger.warning(f"skipping {section}, no gcode_id")
713+
continue
714+
715+
if " " in section:
716+
type, name = section.split(maxsplit=1)
717+
else:
718+
type = ""
719+
name = section
720+
721+
if name not in self._current_temperatures:
722+
self._current_temperatures[name] = TemperatureDataPoint(
723+
type=type,
724+
id=sectionconfig["gcode_id"],
725+
hasTarget=True if "target" in sectionconfig else False
726+
)
727+
728+
if section not in self.HEATERS:
729+
self.HEATERS += (section,)
730+
731+
if section not in self._heaters:
732+
self._heaters.append(section)
733+
734+
self._temperature_store_received = True
735+
self._listener.on_moonraker_temperature_store_update(self._current_temperatures)
736+
self.subscribe_to_updates()
737+
738+
except Exception as e:
739+
self._logger.exception(f"Error while fetching temperature store: {e}")
740+
741+
self.call_method("server.temperature_store").add_done_callback(
742+
on_result
743+
)
744+
677745
def fetch_console_history(self, count: int = 100, force: bool = False) -> Future:
678746
if self._log_history_received and not force:
679747
return
@@ -1084,41 +1152,49 @@ def _process_update(self, payload: dict[str, Any]) -> None:
10841152
self._update_gcode_move(payload)
10851153
self._update_idle_timeout(payload)
10861154
self._update_print_stats(payload)
1087-
self._update_temperatures(payload)
1155+
if self._temperature_store_received:
1156+
self._update_temperatures(payload)
10881157
self._update_virtual_sdcard(payload)
10891158

10901159
def _update_temperatures(self, payload: dict[str, Any]) -> None:
10911160
dirty_actual = False
10921161
dirty_target = False
1162+
dirty_sensorslist = False
10931163

10941164
for heater in self._heaters:
10951165
if heater not in payload:
10961166
continue
10971167

1098-
if heater.startswith(self.GENERIC_HEATER_PREFIX):
1099-
name = heater[len(self.GENERIC_HEATER_PREFIX) :]
1100-
elif heater.startswith(self.GENERIC_TEMPERATURE_FAN_PREFIX):
1101-
name = heater[len(self.GENERIC_TEMPERATURE_FAN_PREFIX) :]
1102-
elif heater.startswith(self.GENERIC_TEMPERATURE_PROBE_PREFIX):
1103-
name = heater[len(self.GENERIC_TEMPERATURE_PROBE_PREFIX) :]
1104-
elif heater.startswith(self.GENERIC_TEMPERATURE_SENSOR_PREFIX):
1105-
name = heater[len(self.GENERIC_TEMPERATURE_SENSOR_PREFIX) :]
1106-
elif heater.startswith(self.GENERIC_TMC_PREFIX):
1107-
name = heater[8:]
1108-
driver = heater[:7]
1109-
if driver not in self.TMC_HAVE_TEMPERATURE:
1110-
continue
1168+
if " " in heater:
1169+
type, name = heater.split(maxsplit=1)
11111170
else:
1171+
type = ""
11121172
name = heater
11131173

1114-
data = self._current_temperatures.get(name, TemperatureDataPoint())
1174+
if heater.startswith(self.GENERIC_TMC_PREFIX) and type not in self.TMC_HAVE_TEMPERATURE:
1175+
continue
1176+
1177+
if name not in self._current_temperatures:
1178+
dirty_sensorslist = True
1179+
self._logger.warning(f"Adding {heater} to temperatures list")
1180+
1181+
data = self._current_temperatures.get(name, TemperatureDataPoint(type=type))
1182+
1183+
if heater.startswith(self.GENERIC_TMC_PREFIX) and data.hasTarget:
1184+
data.hasTarget = False
1185+
11151186
if "temperature" in payload[heater]:
11161187
data.actual = payload[heater]["temperature"] or 0
11171188
dirty_actual = True
11181189
if "target" in payload[heater]:
11191190
data.target = payload[heater]["target"]
11201191
dirty_target = True
11211192
self._current_temperatures[name] = data
1193+
if data.id == "C" and name != "chamber":
1194+
self._current_temperatures["chamber"] = data
1195+
1196+
if dirty_sensorslist:
1197+
self._listener.on_moonraker_temperature_store_update(self._current_temperatures)
11221198

11231199
if dirty_actual or dirty_target:
11241200
now = time.monotonic()

octoprint_moonraker_connector/connector.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ def connection_preconditions_met(cls, params):
105105
host = params.get("host")
106106
return host and resolve_host(host)
107107

108-
TEMPERATURE_LOOKUP = {"extruder": "tool0", "heater_bed": "bed", "chamber": "chamber", "Chamber": "chamber", "cavity": "chamber"}
108+
TEMPERATURE_LOOKUP = {}
109109

110110
def __init__(self, *args, **kwargs):
111111
super().__init__(*args, **kwargs)
@@ -573,14 +573,6 @@ def on_moonraker_connected(self):
573573
"apikey": self._apikey is not None,
574574
},
575575
)
576-
extruder_count = self._profile["extruder"]["count"]
577-
if extruder_count > 1:
578-
for i in range(1, extruder_count):
579-
if f"extruder{i}" not in self.TEMPERATURE_LOOKUP:
580-
self.TEMPERATURE_LOOKUP[f"extruder{i}"] = f"tool{i}"
581-
for heater, data in self._client.current_temperatures.items():
582-
if heater not in self.TEMPERATURE_LOOKUP:
583-
self.TEMPERATURE_LOOKUP[heater] = heater
584576
self._listener.on_printer_files_available(True)
585577
self.refresh_printer_files(recursive=True)
586578

@@ -603,6 +595,30 @@ def on_moonraker_server_info(self, server_info):
603595
)
604596
self._listener.on_printer_firmware_info(firmware_info)
605597

598+
def on_moonraker_temperature_store_update(
599+
self, data: dict[str, TemperatureDataPoint]
600+
) -> None:
601+
# rebuild the list, if we are here we reloaded and something
602+
# could have changed
603+
self.TEMPERATURE_LOOKUP = {"extruder": "tool0", "heater_bed": "bed"}
604+
extruder_count = self._profile["extruder"]["count"]
605+
if extruder_count > 1:
606+
for i in range(1, extruder_count):
607+
if f"extruder{i}" not in self.TEMPERATURE_LOOKUP:
608+
self.TEMPERATURE_LOOKUP[f"extruder{i}"] = f"tool{i}"
609+
610+
mapped_data = {}
611+
for key, value in data.items():
612+
if key not in self.TEMPERATURE_LOOKUP:
613+
if "id" in key and key[id].upper() == "C":
614+
self.TEMPERATURE_LOOKUP[key] = "chamber"
615+
else:
616+
self.TEMPERATURE_LOOKUP[key] = key
617+
new_key = self.TEMPERATURE_LOOKUP.get(key)
618+
if new_key is not None:
619+
mapped_data[new_key] = (value.actual, value.target)
620+
self._listener.on_printer_temperature_update(mapped_data)
621+
606622
def on_moonraker_temperature_update(
607623
self, data: dict[str, TemperatureDataPoint]
608624
) -> None:

0 commit comments

Comments
 (0)