octoprint compat: use subscriptions to update printer data

This tends to be more efficient than polling, particularly on slower machines.

Signed-off-by:  Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
Arksine 2021-04-18 07:12:26 -04:00
parent 9873084667
commit 57836047f6
2 changed files with 50 additions and 40 deletions

View File

@ -28,12 +28,15 @@ class OctoprintCompat:
self.software_version = config['system_args'].get('software_version') self.software_version = config['system_args'].get('software_version')
# Local variables # Local variables
self.klippy_apis = None self.klippy_apis = self.server.lookup_component('klippy_apis')
self.heaters = [] self.heaters = {}
self.last_print_stats = {}
# Register status update event # Register status update event
self.server.register_event_handler( self.server.register_event_handler(
'server:klippy_ready', self._init) 'server:klippy_ready', self._init)
self.server.register_event_handler(
'server:status_update', self._handle_status_update)
# Version & Server information # Version & Server information
self.server.register_endpoint( self.server.register_endpoint(
@ -76,55 +79,59 @@ class OctoprintCompat:
# TODO: shutdown/reboot/restart operations # TODO: shutdown/reboot/restart operations
async def _init(self): async def _init(self):
self.klippy_apis = self.server.lookup_component('klippy_apis') self.heaters = {}
# Fetch heaters # Fetch heaters
try: try:
result = await self.klippy_apis.query_objects({'heaters': None}) result = await self.klippy_apis.query_objects({'heaters': None})
sensors = result.get('heaters', {}).get('available_sensors', [])
except self.server.error as e: except self.server.error as e:
logging.info(f'Error Configuring heaters: {e}') logging.info(f'Error Configuring heaters: {e}')
return sensors = []
self.heaters = result.get('heaters', {}).get('available_sensors', []) # subscribe objects
sub = {s: None for s in sensors}
sub['print_stats'] = None
result = await self.klippy_apis.subscribe_objects(sub)
self.last_print_stats = result.get('print_stats', {})
if sensors:
self.heaters = {name: result.get(name, {}) for name in sensors}
async def printer_state(self): def _handle_status_update(self, status):
if not self.klippy_apis: if 'print_stats' in status:
self.last_print_stats.update(status['print_stats'])
for heater_name, data in self.heaters.items():
if heater_name in status:
data.update(status[heater_name])
def printer_state(self):
klippy_state = self.server.get_klippy_state()
if klippy_state in ["disconnected", "startup"]:
return 'Offline' return 'Offline'
klippy_state = self.server.get_klippy_info().get('state') elif klippy_state != 'ready':
if klippy_state != 'ready':
return 'Error' return 'Error'
result = await self.klippy_apis.query_objects({'print_stats': None})
pstats = result.get('print_stats', {})
return { return {
'standby': 'Operational', 'standby': 'Operational',
'printing': 'Printing', 'printing': 'Printing',
'paused': 'Paused', 'paused': 'Paused',
'complete': 'Operational' 'complete': 'Operational'
}.get(pstats.get('state', 'standby'), 'Error') }.get(self.last_print_stats.get('state', 'standby'), 'Error')
async def printer_temps(self): def printer_temps(self):
temps = {} temps = {}
if not self.klippy_apis: for heater, data in self.heaters.items():
return temps name = 'bed'
if self.heaters: if heater.startswith('extruder'):
result = await self.klippy_apis.query_objects( try:
{heater: None for heater in self.heaters}) tool_no = int(heater[8:])
for heater in self.heaters: except ValueError:
if heater not in result: tool_no = 0
continue name = f'tool{tool_no}'
data = result[heater] elif heater != "heater_bed":
name = 'bed' continue
if heater.startswith('extruder'): temps[name] = {
try: 'actual': round(data.get('temperature', 0.), 2),
tool_no = int(heater[8:]) 'offset': 0,
except ValueError: 'target': data.get('target', 0.),
tool_no = 0 }
name = f'tool{tool_no}'
elif heater != "heater_bed":
continue
temps[name] = {
'actual': round(data.get('temperature', 0.), 2),
'offset': 0,
'target': data.get('target', 0.),
}
return temps return temps
async def _get_version(self, web_request): async def _get_version(self, web_request):
@ -141,7 +148,7 @@ class OctoprintCompat:
""" """
Server status Server status
""" """
klippy_state = self.server.get_klippy_info().get('state') klippy_state = self.server.get_klippy_state()
return { return {
'server': OCTO_VERSION, 'server': OCTO_VERSION,
'safemode': ( 'safemode': (
@ -220,16 +227,16 @@ class OctoprintCompat:
'printTimeLeft': None, 'printTimeLeft': None,
'printTimeOrigin': None, 'printTimeOrigin': None,
}, },
'state': await self.printer_state() 'state': self.printer_state()
} }
async def _get_printer(self, web_request): async def _get_printer(self, web_request):
""" """
Get Printer status Get Printer status
""" """
state = await self.printer_state() state = self.printer_state()
return { return {
'temperature': await self.printer_temps(), 'temperature': self.printer_temps(),
'state': { 'state': {
'text': state, 'text': state,
'flags': { 'flags': {

View File

@ -211,6 +211,9 @@ class Server:
def get_klippy_info(self): def get_klippy_info(self):
return dict(self.klippy_info) return dict(self.klippy_info)
def get_klippy_state(self):
return self.klippy_state
# ***** Klippy Connection ***** # ***** Klippy Connection *****
async def _connect_klippy(self): async def _connect_klippy(self):
if not self.server_running: if not self.server_running: