From fe44e5bbd553c368b892b6885554f35ea7f01592 Mon Sep 17 00:00:00 2001 From: Clayton O'Neill Date: Fri, 7 Aug 2026 13:51:04 -0400 Subject: [PATCH] Extend TempQueue to all physical probes The ADC probe implementations already use TempQueue to provide more stable temperature readings and reject outliers, but other physical probes return their readings without the same handling. This change moves TempQueue handling into the shared probe pipeline and requires each probe implementation to explicitly declare whether it should be used. Directly sampled physical probes enable it, while Bluetooth, virtual, and disabled probes retain their existing behavior. --- probes/ads1015_adafruit.py | 2 +- probes/ads1115.py | 2 +- probes/ads1115_adafruit.py | 2 +- probes/base.py | 52 ++++++++++++++++++++++++++++++------- probes/bt_ibbq.py | 2 +- probes/bt_ibbq_alt.py | 2 +- probes/bt_igrill_alt.py | 2 +- probes/bt_meater.py | 2 +- probes/bt_meater_alt.py | 2 +- probes/bt_meater_exp.py | 2 +- probes/disabled.py | 2 +- probes/ds18b20.py | 4 +-- probes/main.py | 1 + probes/max31865.py | 2 +- probes/max31865_adafruit.py | 2 +- probes/mcp9600_adafruit.py | 2 +- probes/prototype.py | 2 +- probes/virtual_average.py | 2 +- probes/virtual_highest.py | 2 +- probes/virtual_lowest.py | 2 +- probes/virtual_median.py | 2 +- 21 files changed, 63 insertions(+), 30 deletions(-) diff --git a/probes/ads1015_adafruit.py b/probes/ads1015_adafruit.py index 0da4e0959..7cc14063c 100644 --- a/probes/ads1015_adafruit.py +++ b/probes/ads1015_adafruit.py @@ -79,7 +79,7 @@ def read_voltage(self, port): def get_status(self): return self.status -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=True): def __init__(self, probe_info, device_info, units): super().__init__(probe_info, device_info, units) diff --git a/probes/ads1115.py b/probes/ads1115.py index 5ace8f17e..b51b6ae05 100644 --- a/probes/ads1115.py +++ b/probes/ads1115.py @@ -72,7 +72,7 @@ def read_voltage(self, port): def get_status(self): return self.status -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=True): def __init__(self, probe_info, device_info, units): super().__init__(probe_info, device_info, units) diff --git a/probes/ads1115_adafruit.py b/probes/ads1115_adafruit.py index fc520e98c..a6e252f77 100644 --- a/probes/ads1115_adafruit.py +++ b/probes/ads1115_adafruit.py @@ -80,7 +80,7 @@ def read_voltage(self, port): def get_status(self): return self.status -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=True): def __init__(self, probe_info, device_info, units): super().__init__(probe_info, device_info, units) diff --git a/probes/base.py b/probes/base.py index 7b1ab708c..f3bb5b3d8 100644 --- a/probes/base.py +++ b/probes/base.py @@ -28,6 +28,16 @@ ''' class ProbeInterface: + def __init_subclass__(cls, *, uses_temp_queue=None, **kwargs): + super().__init_subclass__(**kwargs) + if uses_temp_queue is None: + raise TypeError( + 'ProbeInterface subclasses must declare ' + 'uses_temp_queue=True or uses_temp_queue=False' + ) + if not isinstance(uses_temp_queue, bool): + raise TypeError('uses_temp_queue must be True or False') + cls.uses_temp_queue = uses_temp_queue def __init__(self, probe_info, device_info, units): self.units = units @@ -93,8 +103,9 @@ def _build_output_data(self, probe_info): def _build_ports(self): ''' Build ports objects. ''' self.port_queues = {} - for port in self.port_map: - self.port_queues[port] = TempQueue(qlength=10, units=self.units) + if self.uses_temp_queue: + for port in self.port_map: + self.port_queues[port] = TempQueue(qlength=10, units=self.units) def _temp_to_resistance(self, temp, probe_profile): ''' @@ -204,15 +215,9 @@ def read_all_ports(self, output_data): ''' Convert Voltage to Temperature and Tr ''' port_values[port], self.output_data['tr'][self.port_map[port]] = self._voltage_to_temp(port_values[port], self.probe_profiles[port], port=port) - ''' Enqueue the Temperature Readings to Port Queues ''' - if port_values[port] == None: - ''' If the read value is None, pass that to the output instead of adding to the queue ''' - output_value = None - else: - self.port_queues[port].enqueue(port_values[port]) - output_value = self.port_queues[port].average() + output_value = port_values[port] - ''' Get average temperature from the queue and store it in the output data structure''' + ''' Store converted temperature in the output data structure ''' if port == self.primary_port: self.output_data['primary'][self.port_map[port]] = output_value elif port in self.food_ports: @@ -225,8 +230,35 @@ def read_all_ports(self, output_data): return self.output_data + def apply_temp_queue(self, output_data): + '''Apply this device's probe values to its per-port TempQueue.''' + if not self.uses_temp_queue: + return output_data + + for port, label in self.port_map.items(): + if port == self.primary_port: + group = 'primary' + elif port in self.food_ports: + group = 'food' + elif port in self.aux_ports: + group = 'aux' + else: + continue + + if label not in output_data[group]: + continue + + value = output_data[group][label] + if value is None: + continue + + output_data[group][label] = self.port_queues[port].enqueue(value) + + return output_data + def update_units(self, units): self.units = 'C' if units == 'C' else 'F' + self._build_ports() self._init_device() def set_profiles(self, probe_info): diff --git a/probes/bt_ibbq.py b/probes/bt_ibbq.py index f5bb35f3c..f106d81a3 100644 --- a/probes/bt_ibbq.py +++ b/probes/bt_ibbq.py @@ -352,7 +352,7 @@ def get_status(self): self.status['hardware_id'] = self.hardware_id return self.status -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=False): def __init__(self, probe_info, device_info, units): self.hardware_id = device_info['config'].get('hardware_id', None) if self.hardware_id == '': diff --git a/probes/bt_ibbq_alt.py b/probes/bt_ibbq_alt.py index 55fa3252e..fe1e9a294 100644 --- a/probes/bt_ibbq_alt.py +++ b/probes/bt_ibbq_alt.py @@ -247,7 +247,7 @@ def get_status(self): return self.status -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=False): def __init__(self, probe_info, device_info, units): self.hardware_id = device_info['config'].get('hardware_id', None) if self.hardware_id == '': diff --git a/probes/bt_igrill_alt.py b/probes/bt_igrill_alt.py index bf0f8669e..ca4f6d4c0 100644 --- a/probes/bt_igrill_alt.py +++ b/probes/bt_igrill_alt.py @@ -432,7 +432,7 @@ def get_status(self): return self.status -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=False): def __init__(self, probe_info, device_info, units): self.hardware_id = device_info['config'].get('hardware_id', None) self.debug_enabled = _to_bool(device_info['config'].get('debug', IGRILL_DEBUG_DEFAULT), default=IGRILL_DEBUG_DEFAULT) diff --git a/probes/bt_meater.py b/probes/bt_meater.py index d595497de..9cd8a46c3 100644 --- a/probes/bt_meater.py +++ b/probes/bt_meater.py @@ -438,7 +438,7 @@ def get_status(self): self.status['probe_id'] = str(self.probe_id) return self.status -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=False): def __init__(self, probe_info, device_info, units): self.hardware_id = device_info['config'].get('hardware_id', None) if self.hardware_id == '': diff --git a/probes/bt_meater_alt.py b/probes/bt_meater_alt.py index 25f5ffe6c..32d239e8e 100644 --- a/probes/bt_meater_alt.py +++ b/probes/bt_meater_alt.py @@ -558,7 +558,7 @@ def get_status(self): return self.status -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=False): def __init__(self, probe_info, device_info, units): self.hardware_id = device_info['config'].get('hardware_id', None) if self.hardware_id == '': diff --git a/probes/bt_meater_exp.py b/probes/bt_meater_exp.py index 4278d6c67..196fedf97 100644 --- a/probes/bt_meater_exp.py +++ b/probes/bt_meater_exp.py @@ -622,7 +622,7 @@ def get_status(self): self.status['hardware_id'] = self.address return self.status -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=False): def __init__(self, probe_info, device_info, units): self.hardware_id = device_info['config'].get('hardware_id', None) if self.hardware_id == '': diff --git a/probes/disabled.py b/probes/disabled.py index 1270fa4db..4469a45fa 100644 --- a/probes/disabled.py +++ b/probes/disabled.py @@ -32,7 +32,7 @@ ***************************************** ''' -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=False): def __init__(self, probe_info, device_info, units): super().__init__(probe_info, device_info, units) diff --git a/probes/ds18b20.py b/probes/ds18b20.py index 12969d35e..60eb11d4d 100644 --- a/probes/ds18b20.py +++ b/probes/ds18b20.py @@ -121,7 +121,7 @@ def get_status(self): self.status['ready'] = self.initialized return self.status -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=True): def __init__(self, probe_info, device_info, units): super().__init__(probe_info, device_info, units) @@ -154,4 +154,4 @@ def read_all_ports(self, output_data): elif port in self.aux_ports: self.output_data['aux'][self.port_map[port]] = tempF if self.units == 'F' else tempC - return self.output_data \ No newline at end of file + return self.output_data diff --git a/probes/main.py b/probes/main.py index 0485ad3b9..94134ef9c 100644 --- a/probes/main.py +++ b/probes/main.py @@ -74,6 +74,7 @@ def read_probes(self): } for device in self.probe_device_list: device_data = device.read_all_ports(output_data) + device_data = device.apply_temp_queue(device_data) for group in device_data: for probe in device_data[group]: output_data[group][probe] = device_data[group][probe] diff --git a/probes/max31865.py b/probes/max31865.py index d5b07f917..73aa25ab9 100644 --- a/probes/max31865.py +++ b/probes/max31865.py @@ -189,7 +189,7 @@ def close(self): def get_status(self): return self.status -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=True): def __init__(self, probe_info, device_info, units): super().__init__(probe_info, device_info, units) diff --git a/probes/max31865_adafruit.py b/probes/max31865_adafruit.py index 01e326686..bd7ea22e9 100644 --- a/probes/max31865_adafruit.py +++ b/probes/max31865_adafruit.py @@ -93,7 +93,7 @@ def resistance(self): def get_status(self): return self.status -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=True): def __init__(self, probe_info, device_info, units): super().__init__(probe_info, device_info, units) diff --git a/probes/mcp9600_adafruit.py b/probes/mcp9600_adafruit.py index 6863b96e5..7aa7be33e 100644 --- a/probes/mcp9600_adafruit.py +++ b/probes/mcp9600_adafruit.py @@ -73,7 +73,7 @@ def temperature(self): def get_status(self): return self.status -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=True): def __init__(self, probe_info, device_info, units): super().__init__(probe_info, device_info, units) diff --git a/probes/prototype.py b/probes/prototype.py index 47cd1d137..15f2f2804 100644 --- a/probes/prototype.py +++ b/probes/prototype.py @@ -98,7 +98,7 @@ def read_voltage(self, port): def get_status(self): return self.status -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=True): def __init__(self, probe_info, device_info, units): super().__init__(probe_info, device_info, units) diff --git a/probes/virtual_average.py b/probes/virtual_average.py index dede6c8a2..4e0350a9a 100644 --- a/probes/virtual_average.py +++ b/probes/virtual_average.py @@ -35,7 +35,7 @@ ***************************************** ''' -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=False): def __init__(self, probe_info, device_info, units): super().__init__(probe_info, device_info, units) diff --git a/probes/virtual_highest.py b/probes/virtual_highest.py index 07b7dec3b..9ffbd517a 100644 --- a/probes/virtual_highest.py +++ b/probes/virtual_highest.py @@ -34,7 +34,7 @@ ***************************************** ''' -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=False): def __init__(self, probe_info, device_info, units): super().__init__(probe_info, device_info, units) diff --git a/probes/virtual_lowest.py b/probes/virtual_lowest.py index 4a19943f4..2a0074f5f 100644 --- a/probes/virtual_lowest.py +++ b/probes/virtual_lowest.py @@ -34,7 +34,7 @@ ***************************************** ''' -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=False): def __init__(self, probe_info, device_info, units): super().__init__(probe_info, device_info, units) diff --git a/probes/virtual_median.py b/probes/virtual_median.py index d14b4d136..508907980 100644 --- a/probes/virtual_median.py +++ b/probes/virtual_median.py @@ -35,7 +35,7 @@ ***************************************** ''' -class ReadProbes(ProbeInterface): +class ReadProbes(ProbeInterface, uses_temp_queue=False): def __init__(self, probe_info, device_info, units): super().__init__(probe_info, device_info, units)