Compare commits

..

88 Commits

Author SHA1 Message Date
70627342f3 Real concurrently 2024-08-30 17:37:53 +08:00
ffa0783cff Don't create report task if not polling for it 2024-08-30 16:55:15 +08:00
ba6b24fe95 PIDAutotuner: Don't use separate sig for interval 2024-08-30 16:55:15 +08:00
2e0ecd9758 aioexample: Show polling while report mode on
WIP: handle KeyboardInterrupt
2024-08-30 16:55:15 +08:00
199aeb3609 aioclient: More accurate DFU docstring 2024-08-30 16:55:15 +08:00
1e81641169 No need for async as well 2024-08-30 16:55:15 +08:00
2c95bd9d09 No need for async 2024-08-30 16:55:15 +08:00
d83c4ed4f6 Remove extra imports 2024-08-30 16:55:15 +08:00
637d8d029a report group 2024-08-30 16:55:15 +08:00
671004703b end_session in thermostat itself afterall 2024-08-30 16:55:15 +08:00
10873933f4 Reorder MainWindow 2024-08-30 16:55:15 +08:00
ec1fffecd1 Rearrange MainWindow.__init__ 2024-08-30 16:55:15 +08:00
36c063d917 Thermostat: Add disconnect callback
For communicating with the autotuner before the client fully
disconnects

Also then there's no need for explicitly resetting autotune elements
2024-08-30 16:55:15 +08:00
65b9202cea Remove info_box_trigger 2024-08-30 16:55:15 +08:00
a72a0606f1 Remove connection errored 2024-08-30 16:55:15 +08:00
81f09a9f0f Simply test for connectivity for turning PID off 2024-08-30 16:55:15 +08:00
f768ea5d4f Fix pressing enter not working in conn menu 2024-08-30 16:55:15 +08:00
e849610658 Assign connection_errored as well 2024-08-30 16:55:15 +08:00
bbe9a60824 Back out 2024-08-30 16:55:15 +08:00
cd07cdeddd Put UI changes into conn_menu 2024-08-30 16:55:15 +08:00
fe3a22a599 ConnectionBtn + StatusLbl 2024-08-30 16:55:15 +08:00
2b35bf57f9 Clear Graph UI changes 2024-08-30 16:55:15 +08:00
8a83bbc1d1 Concentrate ThermostatCtrlMenu UI changes 2024-08-30 16:55:15 +08:00
82315d65b2 Descriptive name 2024-08-30 16:55:15 +08:00
dfe08546fe Refactor repeated stuff 2024-08-30 16:55:15 +08:00
c4309c5ba0 Split PID handler UI up 2024-08-30 16:55:15 +08:00
3387ad67f7 Fix hwrev getting 2024-08-30 16:55:15 +08:00
903f9f8767 hwrev updates 2024-08-30 15:53:05 +08:00
aadf8a2595 Fix info boxes for load/saving from flash 2024-08-30 15:53:05 +08:00
49561a2f5a Move reset request to thermostat control menu
We don't get auto reconnect anymore
2024-08-30 15:53:05 +08:00
b32b38d830 Move pid autotuning request to CtrlPanel
And update autotune UI only on state change instead of every single
report update
2024-08-30 15:53:05 +08:00
fcda46d1f3 Move channelGraph stuff inside LiveDataPlotter 2024-08-30 15:53:05 +08:00
89e9da4499 Move plot_options_menu stuff into menu 2024-08-30 15:53:05 +08:00
87ca0694cd Move autotune ticking connect 2024-08-30 15:53:05 +08:00
03233386d0 Get thermostat_ctrl_menu to subscribe to hwrev updates 2024-08-30 15:53:05 +08:00
242a2b2e69 Save/load info box content 2024-08-30 15:53:05 +08:00
b84af82722 Fix loading all channel settings would bring up 2 info boxes 2024-08-30 15:53:05 +08:00
7997ef2472 Add back asyncSlot to save_cfg_request 2024-08-30 15:53:05 +08:00
911b4c680f hw_rev 2024-08-30 15:53:05 +08:00
19677c2251 fan_update: tec_qt to thermostat_ctrl_menu 2024-08-30 15:53:05 +08:00
5f30f12875 Fix updating status label for hwrev = None 2024-08-30 15:53:05 +08:00
3283b126b8 Put some menu requests in menu itself 2024-08-30 15:53:05 +08:00
59ba8c692d Broadcast ConnectionState changes from Thermostat 2024-08-30 15:53:05 +08:00
e3ef9115a5 Move sigActivatedHandle to CtrlPanel 2024-08-30 15:53:05 +08:00
c5c311ae14 Get rid of timeout on readline 2024-08-30 15:53:05 +08:00
6699458939 Put send_command in CtrlPanel 2024-08-30 15:53:05 +08:00
8a4a963f9b Extra bail removed 2024-08-30 15:53:05 +08:00
2f10ad8056 return hwrev when start_session 2024-08-30 15:53:05 +08:00
3731282146 state str 2024-08-30 15:53:05 +08:00
50ac1c2078 params update concurrently 2024-08-30 15:53:05 +08:00
0eebc0a6df Stuff non-UI changes in Thermostat model 2024-08-30 15:53:05 +08:00
78ba799d56 Base Thermostat connectivity UI changes to state 2024-08-30 15:53:05 +08:00
f9c0f140fa Remove wait_for
OSError raised anyways
2024-08-30 15:53:05 +08:00
93d96401b9 Actually its OSError 2024-08-30 15:53:05 +08:00
881bf6ff6c {start,end}_session -> [dis]connect 2024-08-30 15:53:05 +08:00
7e0dd61f79 Simplify on_connect_btn_clicked
Raise if OSError
2024-08-30 15:53:05 +08:00
ed34eb9e03 Connecting task moved? 2024-08-30 15:53:05 +08:00
387d1226c5 AsyncIO version Client -> AsyncioClient 2024-08-30 15:53:05 +08:00
058e597ef0 Exclusively use the Thermostat object as a medium
All calls to the Thermostat should be forwarded by the medium.
2024-08-30 15:53:05 +08:00
80975f50b1 Integrate WrappedClient into Thermostat model 2024-08-30 15:53:05 +08:00
86afa19085 Should not stop cancelling read if timeout'd 2024-08-30 15:53:05 +08:00
4b6dfdf478 Fix Autotuner state for forceful disconnect 2024-08-30 15:53:05 +08:00
85cb2027a8 _ 2024-08-30 15:53:05 +08:00
4fedb14727 Make connection loss handling more elegant
Show an info box on connection lost informing the user that the
Thermostat was forcefully disconnected.
2024-08-30 15:53:05 +08:00
863920f922 ================gui_dev-fix_asyncio=============== 2024-08-30 15:53:05 +08:00
96b57f199d Use new style super() 2024-08-30 15:53:05 +08:00
f2da457860 Move command line host:port setting handling
To main
2024-08-30 15:40:31 +08:00
066c75fc21 aioclient: Add missing readline for saving
Saving all channels returns multiple JSON objects, read the extra {}.
2024-08-30 15:38:59 +08:00
60b05ddfeb import order rearrange 2024-08-30 15:38:59 +08:00
6a78a2069d This is bail 2024-08-30 15:38:59 +08:00
6eb5b7298e thermostat: Properly register task
Also Thermostat.task -> Thermostat._update_params_task
2024-08-30 15:38:58 +08:00
4a292c19db ip -> host 2024-08-30 15:38:58 +08:00
0b115b3394 Lazy evaluating for debug string command 2024-08-30 15:38:58 +08:00
2e904cb498 Add pytec runnables 2024-08-30 15:38:58 +08:00
d3f378f058 PYTHON shell 2024-08-30 15:38:58 +08:00
d0273cd41b Exactlier wording 2024-08-30 15:38:58 +08:00
0988ed24d6 unused 2024-08-30 15:38:58 +08:00
ab3b26a2a4 encoding 2024-08-30 15:38:58 +08:00
000b97398b Just catch asyncio.TimeoutError
Will just change to TimeoutError once we switch to Python 3.11 in the
flake.
2024-08-30 15:38:58 +08:00
e162bcf210 Remove exception too general 2024-08-30 15:38:58 +08:00
c3d7804898 Use asserts to check for connectivity 2024-08-30 15:38:58 +08:00
9c0977262c Add back the parent 2024-08-30 15:38:58 +08:00
017206bd34 Fix method call 2024-08-30 15:38:58 +08:00
f46bd2b50e README: Proofread 2024-08-30 15:38:58 +08:00
5b48fb2793 Swap order arounda bit more 2024-08-30 15:38:58 +08:00
358403e651 Formatting 2024-08-30 15:38:58 +08:00
4a48379923 Use qtextras 2024-08-30 15:38:58 +08:00
b766e949e8 flake update 2024-08-30 15:38:58 +08:00
5 changed files with 65 additions and 45 deletions

View File

@ -1,7 +1,19 @@
import asyncio
from contextlib import suppress
from pytec.aioclient import AsyncioClient
async def poll_for_info(tec):
while True:
print(tec.get_pwm())
print(tec.get_steinhart_hart())
print(tec.get_pid())
print(tec.get_postfilter())
print(tec.get_fan())
await asyncio.sleep(1)
async def main():
tec = AsyncioClient()
await tec.connect() # (host="192.168.1.26", port=23)
@ -11,8 +23,14 @@ async def main():
print(await tec.get_pwm())
print(await tec.get_postfilter())
print(await tec.get_steinhart_hart())
polling_task = asyncio.create_task(poll_for_info(tec))
async for data in tec.report_mode():
print(data)
polling_task.cancel()
with suppress(asyncio.CancelledError):
await polling_task
asyncio.run(main())

View File

@ -11,7 +11,6 @@ class PIDAutoTuner(QObject):
self._thermostat = thermostat
self._thermostat.report_update.connect(self.tick)
self._thermostat.interval_update.connect(self.update_sampling_interval)
self.autotuners = [PIDAutotune(25) for _ in range(num_of_channel)]
self.target_temp = [20.0 for _ in range(num_of_channel)]
@ -20,10 +19,6 @@ class PIDAutoTuner(QObject):
self.lookback = [3.0 for _ in range(num_of_channel)]
self.sampling_interval = [1 / 16.67 for _ in range(num_of_channel)]
@pyqtSlot(list)
def update_sampling_interval(self, interval):
self.sampling_interval = interval
def set_params(self, params_name, ch, val):
getattr(self, params_name)[ch] = val
@ -50,11 +45,14 @@ class PIDAutoTuner(QObject):
@asyncSlot(list)
async def tick(self, report):
for channel_report in report:
ch = channel_report["channel"]
self.sampling_interval[ch] = channel_report["interval"]
# TODO: Skip when PID Autotune or emit error message if NTC is not connected
if channel_report["temperature"] is None:
continue
ch = channel_report["channel"]
match self.autotuners[ch].state():
case (
PIDAutotuneState.STATE_READY

View File

@ -20,7 +20,6 @@ class Thermostat(QObject, metaclass=PropertyMeta):
pid = Property(list)
pwm = Property(list)
postfilter = Property(list)
interval = Property(list)
report = Property(list)
connection_error = pyqtSignal()
@ -54,36 +53,45 @@ class Thermostat(QObject, metaclass=PropertyMeta):
"Encountered an error while polling for information from Thermostat.",
exc_info=True,
)
self.handle_connection_error()
await self.handle_connection_error()
return
self._update_params_task = asyncio.create_task(self.update_params())
await asyncio.sleep(self._update_s)
def handle_connection_error(self):
self.end_session()
async def handle_connection_error(self):
await self.end_session()
self.connection_error.emit()
async def get_hw_rev(self):
return await self._client.hw_rev()
async def update_params(self):
fan_task = asyncio.create_task(self._client.get_fan())
pwm_task = asyncio.create_task(self._client.get_pwm())
pid_task = asyncio.create_task(self._client.get_pid())
report_task = asyncio.create_task(self._client.report())
thermistor_task = asyncio.create_task(self._client.get_steinhart_hart())
postfilter_task = asyncio.create_task(self._client.get_postfilter())
self.fan = await fan_task
self.pwm = await pwm_task
if self._poll_for_report:
self.report = await report_task
self.interval = [
self.report[i]["interval"] for i in range(len(self.report))
]
self.pid = await pid_task
self.thermistor = await thermistor_task
self.postfilter = await postfilter_task
(
self.fan,
self.pwm,
self.report,
self.pid,
self.thermistor,
self.postfilter,
) = await asyncio.gather(
self._client.get_fan(),
self._client.get_pwm(),
self._client.report(),
self._client.get_pid(),
self._client.get_steinhart_hart(),
self._client.get_postfilter(),
)
else:
self.fan, self.pwm, self.pid, self.thermistor, self.postfilter = (
await asyncio.gather(
self._client.get_fan(),
self._client.get_pwm(),
self._client.get_pid(),
self._client.get_steinhart_hart(),
self._client.get_postfilter(),
)
)
def connected(self):
return self._client.connected()
@ -110,9 +118,6 @@ class Thermostat(QObject, metaclass=PropertyMeta):
async def report_mode(self):
async for report in self._client.report_mode():
self.report_update.emit(report)
self.interval = [
self.report[i]["interval"] for i in range(len(self.report))
]
@asyncSlot()
async def end_session(self):

View File

@ -285,19 +285,6 @@ class CtrlPanel(QObject):
f"Channel {ch} PID Autotune has failed.",
)
@asyncSlot()
async def pid_auto_tune_request(self, ch):
match self.autotuners.get_state(ch):
case PIDAutotuneState.STATE_OFF | PIDAutotuneState.STATE_FAILED:
self.autotuners.load_params_and_set_ready(ch)
case (
PIDAutotuneState.STATE_READY
| PIDAutotuneState.STATE_RELAY_STEP_UP
| PIDAutotuneState.STATE_RELAY_STEP_DOWN
):
await self.autotuners.stop_pid_from_running(ch)
@asyncSlot(int)
async def load_settings(self, ch):
await self.thermostat.load_cfg(ch)
@ -316,3 +303,17 @@ class CtrlPanel(QObject):
f"Channel {ch} settings has been saved to flash.\n"
"It will be loaded on Thermostat reset, or when settings are explicitly loaded.",
)
@asyncSlot()
async def pid_auto_tune_request(self, ch=0):
match self.autotuners.get_state(ch):
case PIDAutotuneState.STATE_OFF | PIDAutotuneState.STATE_FAILED:
self.autotuners.load_params_and_set_ready(ch)
case (
PIDAutotuneState.STATE_READY
| PIDAutotuneState.STATE_RELAY_STEP_UP
| PIDAutotuneState.STATE_RELAY_STEP_DOWN
):
await self.autotuners.stop_pid_from_running(ch)

View File

@ -59,9 +59,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.info_box = InfoBox()
# Models
self.thermostat = Thermostat(
self, self.report_refresh_spin.value()
)
self.thermostat = Thermostat(self, self.report_refresh_spin.value())
self._connecting_task = None
self.thermostat.connection_state_changed.connect(self._on_connection_changed)