Skip to content

Commit

Permalink
offload the finish measurement and get sample in a separate thread
Browse files Browse the repository at this point in the history
  • Loading branch information
Frix-x committed Sep 15, 2024
1 parent fe78456 commit 1791e3f
Showing 1 changed file with 40 additions and 7 deletions.
47 changes: 40 additions & 7 deletions shaketune/helpers/accelerometer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import time
from multiprocessing import Process
from pathlib import Path
from threading import Thread
from typing import List, Tuple, TypedDict

import numpy as np
Expand Down Expand Up @@ -140,7 +141,7 @@ def wait_for_file_writes(self, k_reactor, timeout: int = 20):

if not complete:
raise TimeoutError(
'Shake&Tune was unable to write the accelerometer data into the archive file. '
'Shake&Tune was unable to write the accelerometer data into the .STDATA file. '
'This might be due to a slow SD card or a busy or full filesystem.'
)

Expand All @@ -152,6 +153,7 @@ def __init__(self, klipper_accelerometer):
self._k_accelerometer = klipper_accelerometer
self._bg_client = None
self._measurements_manager: MeasurementsManager = None
self._get_samples_thread = None

@staticmethod
def find_axis_accelerometer(printer, axis: str = 'xy'):
Expand Down Expand Up @@ -188,11 +190,42 @@ def stop_recording(self) -> MeasurementsManager:

bg_client = self._bg_client
self._bg_client = None
bg_client.finish_measurements()

samples = bg_client.samples or bg_client.get_samples()
self._measurements_manager.append_samples_to_last_measurement(samples)
m_manager = self._measurements_manager
self._measurements_manager = None
# Start a thread to finish the measurements and get the samples without blocking the main
# Klipper code. Since these operations are I/O-bound, the GIL should not cause significant
# issues and a thread is even recommended over a Process since bg_client may not be pickleable.
self._get_samples_thread = Thread(target=self._finish_and_get_samples, args=(bg_client,))
self._get_samples_thread.daemon = True
self._get_samples_thread.start()

return m_manager
return self._measurements_manager

def _finish_and_get_samples(self, bg_client):
try:
bg_client.finish_measurements()
samples = bg_client.samples or bg_client.get_samples()
self._measurements_manager.append_samples_to_last_measurement(samples)
except Exception as e:
ConsoleOutput.print(f'Error during accelerometer data retrieval: {e}')

def wait_for_samples(self, k_reactor, timeout: int = 20):
if self._get_samples_thread is None:
return # No samples are being retrieved

eventtime = k_reactor.monotonic()
endtime = eventtime + timeout
complete = False

while eventtime < endtime:
eventtime = k_reactor.pause(eventtime + 0.05)
if not self._get_samples_thread.is_alive():
complete = True
break

if not complete:
raise TimeoutError(
'Shake&Tune was unable to retrieve accelerometer data in time. '
'This might be due to slow hardware or a busy system.'
)

self._get_samples_thread = None

0 comments on commit 1791e3f

Please sign in to comment.