Exclusively use the Thermostat object as a medium

All calls to the Thermostat should be forwarded by the medium.
This commit is contained in:
atse 2024-07-08 11:55:09 +08:00
parent 047bde887e
commit c4d31a78b1
3 changed files with 39 additions and 31 deletions

View File

@ -4,10 +4,10 @@ from autotune import PIDAutotuneState, PIDAutotune
class PIDAutoTuner(QObject): class PIDAutoTuner(QObject):
def __init__(self, parent, client, num_of_channel): def __init__(self, parent, thermostat, num_of_channel):
super().__init__(parent) super().__init__(parent)
self._client = client self._thermostat = thermostat
self.autotuners = [PIDAutotune(25) for _ in range(num_of_channel)] self.autotuners = [PIDAutotune(25) for _ in range(num_of_channel)]
self.target_temp = [20.0 for _ in range(num_of_channel)] self.target_temp = [20.0 for _ in range(num_of_channel)]
self.test_current = [1.0 for _ in range(num_of_channel)] self.test_current = [1.0 for _ in range(num_of_channel)]
@ -37,7 +37,7 @@ class PIDAutoTuner(QObject):
async def stop_pid_from_running(self, ch): async def stop_pid_from_running(self, ch):
self.autotuners[ch].setOff() self.autotuners[ch].setOff()
await self._client.set_param("pwm", ch, "i_set", 0) await self._thermostat.set_param("pwm", ch, "i_set", 0)
@asyncSlot(list) @asyncSlot(list)
async def tick(self, report): async def tick(self, report):
@ -56,21 +56,21 @@ class PIDAutoTuner(QObject):
self.autotuners[ch].run( self.autotuners[ch].run(
channel_report["temperature"], channel_report["time"] channel_report["temperature"], channel_report["time"]
) )
await self._client.set_param( await self._thermostat.set_param(
"pwm", ch, "i_set", self.autotuners[ch].output() "pwm", ch, "i_set", self.autotuners[ch].output()
) )
case PIDAutotuneState.STATE_SUCCEEDED: case PIDAutotuneState.STATE_SUCCEEDED:
kp, ki, kd = self.autotuners[ch].get_tec_pid() kp, ki, kd = self.autotuners[ch].get_tec_pid()
self.autotuners[ch].setOff() self.autotuners[ch].setOff()
await self._client.set_param("pid", ch, "kp", kp) await self._thermostat.set_param("pid", ch, "kp", kp)
await self._client.set_param("pid", ch, "ki", ki) await self._thermostat.set_param("pid", ch, "ki", ki)
await self._client.set_param("pid", ch, "kd", kd) await self._thermostat.set_param("pid", ch, "kd", kd)
await self._client.set_param("pwm", ch, "pid") await self._thermostat.set_param("pwm", ch, "pid")
await self._client.set_param( await self._thermostat.set_param(
"pid", ch, "target", self.target_temp[ch] "pid", ch, "target", self.target_temp[ch]
) )
case PIDAutotuneState.STATE_FAILED: case PIDAutotuneState.STATE_FAILED:
self.autotuners[ch].setOff() self.autotuners[ch].setOff()
await self._client.set_param("pwm", ch, "i_set", 0) await self._thermostat.set_param("pwm", ch, "i_set", 0)

View File

@ -3,6 +3,7 @@ from qasync import asyncSlot
from pytec.gui.model.property import Property, PropertyMeta from pytec.gui.model.property import Property, PropertyMeta
import asyncio import asyncio
import logging import logging
from pytec.aioclient import Client
class Thermostat(QObject, metaclass=PropertyMeta): class Thermostat(QObject, metaclass=PropertyMeta):
@ -17,9 +18,9 @@ class Thermostat(QObject, metaclass=PropertyMeta):
info_box_trigger = pyqtSignal(str, str) info_box_trigger = pyqtSignal(str, str)
connection_error = pyqtSignal() connection_error = pyqtSignal()
def __init__(self, parent, client, update_s): def __init__(self, parent, update_s):
self._update_s = update_s self._update_s = update_s
self._client = client self._client = Client()
self._watch_task = None self._watch_task = None
self._report_mode_task = None self._report_mode_task = None
self._poll_for_report = True self._poll_for_report = True
@ -27,6 +28,9 @@ class Thermostat(QObject, metaclass=PropertyMeta):
self.connection_errored = False self.connection_errored = False
super().__init__(parent) super().__init__(parent)
async def start_session(self, host, port):
await self._client.start_session(host, port, timeout=5)
async def run(self): async def run(self):
self._update_params_task = asyncio.create_task(self.update_params()) self._update_params_task = asyncio.create_task(self.update_params())
while True: while True:
@ -128,3 +132,12 @@ class Thermostat(QObject, metaclass=PropertyMeta):
@pyqtSlot(float) @pyqtSlot(float)
def set_update_s(self, update_s): def set_update_s(self, update_s):
self._update_s = update_s self._update_s = update_s
async def set_fan(self, power="auto"):
await self._client.set_fan(power)
async def get_fan(self):
return await self._client.get_fan()
async def set_param(self, topic, channel, field="", value=""):
await self._client.set_param(topic, channel, field, value)

View File

@ -8,7 +8,6 @@ from pytec.gui.view.ctrl_panel import CtrlPanel
from pytec.gui.view.info_box import InfoBox from pytec.gui.view.info_box import InfoBox
from pytec.gui.model.pid_autotuner import PIDAutoTuner from pytec.gui.model.pid_autotuner import PIDAutoTuner
from pytec.gui.model.thermostat import Thermostat from pytec.gui.model.thermostat import Thermostat
from pytec.aioclient import Client
import json import json
from autotune import PIDAutotuneState from autotune import PIDAutotuneState
from qasync import asyncSlot, asyncClose from qasync import asyncSlot, asyncClose
@ -64,11 +63,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.hw_rev_data = None self.hw_rev_data = None
self.info_box = InfoBox() self.info_box = InfoBox()
self.client = Client() self.thermostat = Thermostat(self, self.report_refresh_spin.value())
self.thermostat = Thermostat(
self, self.client, self.report_refresh_spin.value()
)
def handle_connection_error(): def handle_connection_error():
self.info_box.display_info_box( self.info_box.display_info_box(
@ -79,10 +74,10 @@ class MainWindow(QtWidgets.QMainWindow):
self.thermostat.connection_error.connect(handle_connection_error) self.thermostat.connection_error.connect(handle_connection_error)
self.client.connection_error.connect(self.thermostat.timed_out) self.thermostat.connection_error.connect(self.thermostat.timed_out)
self.client.connection_error.connect(self.bail) self.thermostat.connection_error.connect(self.bail)
self.autotuners = PIDAutoTuner(self, self.client, 2) self.autotuners = PIDAutoTuner(self, self.thermostat, 2)
def get_ctrl_panel_config(args): def get_ctrl_panel_config(args):
with open(args.param_tree, "r", encoding="utf-8") as f: with open(args.param_tree, "r", encoding="utf-8") as f:
@ -242,14 +237,14 @@ class MainWindow(QtWidgets.QMainWindow):
self.conn_menu.port_set_spin.value(), self.conn_menu.port_set_spin.value(),
) )
try: try:
if not (self.client.connecting() or self.client.connected()): if not (self.thermostat.connecting() or self.thermostat.connected()):
self.status_lbl.setText("Connecting...") self.status_lbl.setText("Connecting...")
self.connect_btn.setText("Stop") self.connect_btn.setText("Stop")
self.conn_menu.host_set_line.setEnabled(False) self.conn_menu.host_set_line.setEnabled(False)
self.conn_menu.port_set_spin.setEnabled(False) self.conn_menu.port_set_spin.setEnabled(False)
try: try:
await self.client.start_session(host=host, port=port, timeout=5) await self.thermostat.start_session(host=host, port=port)
except StoppedConnecting: except StoppedConnecting:
return return
await self._on_connection_changed(True) await self._on_connection_changed(True)
@ -266,7 +261,7 @@ class MainWindow(QtWidgets.QMainWindow):
@asyncSlot() @asyncSlot()
async def bail(self): async def bail(self):
await self._on_connection_changed(False) await self._on_connection_changed(False)
await self.client.end_session() await self.thermostat.end_session()
@asyncSlot(object, object) @asyncSlot(object, object)
async def send_command(self, param, changes): async def send_command(self, param, changes):
@ -294,7 +289,7 @@ class MainWindow(QtWidgets.QMainWindow):
new_value = "" new_value = ""
inner_param.setOpts(lock=True) inner_param.setOpts(lock=True)
await self.client.set_param( await self.thermostat.set_param(
channel=ch, value=new_value, **thermostat_param channel=ch, value=new_value, **thermostat_param
) )
inner_param.setOpts(lock=False) inner_param.setOpts(lock=False)
@ -364,24 +359,24 @@ class MainWindow(QtWidgets.QMainWindow):
@asyncSlot(int) @asyncSlot(int)
async def fan_set_request(self, value): async def fan_set_request(self, value):
assert self.client.connected() assert self.thermostat.connected()
if self.thermostat_ctrl_menu.fan_auto_box.isChecked(): if self.thermostat_ctrl_menu.fan_auto_box.isChecked():
with QSignalBlocker(self.thermostat_ctrl_menu.fan_auto_box): with QSignalBlocker(self.thermostat_ctrl_menu.fan_auto_box):
self.thermostat_ctrl_menu.fan_auto_box.setChecked(False) self.thermostat_ctrl_menu.fan_auto_box.setChecked(False)
await self.client.set_fan(value) await self.thermostat.set_fan(value)
if not self.hw_rev_data["settings"]["fan_pwm_recommended"]: if not self.hw_rev_data["settings"]["fan_pwm_recommended"]:
self.thermostat_ctrl_menu.set_fan_pwm_warning() self.thermostat_ctrl_menu.set_fan_pwm_warning()
@asyncSlot(int) @asyncSlot(int)
async def fan_auto_set_request(self, enabled): async def fan_auto_set_request(self, enabled):
assert self.client.connected() assert self.thermostat.connected()
if enabled: if enabled:
await self.client.set_fan("auto") await self.thermostat.set_fan("auto")
self.fan_update(await self.client.get_fan()) self.fan_update(await self.thermostat.get_fan())
else: else:
await self.client.set_fan( await self.thermostat.set_fan(
self.thermostat_ctrl_menu.fan_power_slider.value() self.thermostat_ctrl_menu.fan_power_slider.value()
) )