Compare commits

..

103 Commits

Author SHA1 Message Date
3f32c9a4a2 aioclient: More accurate DFU docstring 2024-08-29 13:23:50 +08:00
89986fd810 No need for async as well 2024-08-29 12:51:18 +08:00
f8900d295d Order 2024-08-29 12:12:05 +08:00
f0772a8072 No need for async 2024-08-29 12:11:49 +08:00
b9ba1e2d9f Remove extra imports 2024-08-29 12:02:56 +08:00
4997db0b4c blank line 2024-08-29 11:48:39 +08:00
65e3f6395b report group 2024-08-29 11:47:39 +08:00
daa3192d41 end_session in thermostat itself afterall 2024-08-29 11:40:57 +08:00
a6be838445 Reorder MainWindow 2024-08-29 11:26:11 +08:00
89076b2d13 Actually pid_auto_tune_request belongs to ctrl_panel 2024-08-29 11:09:33 +08:00
78b3f8e419 fixup! fixup! Rearrange MainWindow.__init__ 2024-08-29 10:57:45 +08:00
3925551071 Move command line host:port setting handling
To main
2024-08-29 10:36:18 +08:00
2fd852e171 finish IP -> HOST 2024-08-29 10:35:41 +08:00
425dee173b No need for explicitly resetting Autotune elements 2024-08-28 17:49:19 +08:00
9531e7063a fixup! Rearrange MainWindow.__init__ 2024-08-28 17:26:43 +08:00
e3ea0f970e Use new style super() 2024-08-28 17:22:59 +08:00
9b9b4baf98 Rearrange MainWindow.__init__ 2024-08-28 17:20:14 +08:00
60295d2baa Thermostat: Add disconnect callback
For communicating with the autotuner before the client fully
disconnects
2024-08-28 17:06:17 +08:00
c761f9fe94 Fix hwrev getting 2024-08-28 16:32:55 +08:00
585c35b4c9 fixup forgetting to await 2024-08-28 16:09:30 +08:00
f9f8f6f2b6 Remove info_box_trigger 2024-08-28 13:45:57 +08:00
2a12d02bc8 Remove connection errored 2024-08-28 13:38:09 +08:00
96b0ddc26c Simply test for connectivity for turning PID off 2024-08-28 13:37:49 +08:00
e30d07d707 Fix pressing enter not working in conn menu 2024-08-28 11:38:51 +08:00
326c22d6b2 Assign connection_errored as well 2024-08-28 11:07:34 +08:00
b3f629fb4a Back out 2024-08-28 11:06:26 +08:00
c2dccb80f8 Put UI changes into conn_menu 2024-08-28 11:03:26 +08:00
db127f788b fixup! Refactor repeated stuff 2024-08-28 10:55:58 +08:00
863106d835 fixup! Concentrate ThermostatCtrlMenu UI changes 2024-08-28 10:54:58 +08:00
ff4aa61b1e fixup! Clear Graph UI changes 2024-08-28 10:52:12 +08:00
209ea365c2 ConnectionBtn + StatusLbl 2024-08-28 10:50:48 +08:00
35a179f7fa Clear Graph UI changes 2024-08-28 10:50:38 +08:00
94eb6b09fd Concentrate ThermostatCtrlMenu UI changes 2024-08-28 10:33:59 +08:00
2ec059d402 Descriptive name 2024-08-28 10:24:37 +08:00
ac9ddc92a6 Refactor repeated stuff 2024-08-28 10:24:25 +08:00
94eb331c96 Actually move it into autotuners 2024-08-27 18:29:13 +08:00
40abceb688 Split PID handler UI up 2024-08-27 18:24:56 +08:00
7b662374bc hwrev updates 2024-08-27 18:13:05 +08:00
dc5460f591 aioclient: Add missing readline for saving
Saving all channels returns multiple JSON objects, read the extra {}.
2024-08-27 17:08:38 +08:00
df79d4d977 Fix not actually awaiting for load/save 2024-08-27 17:07:45 +08:00
9910f935a9 Add back the info_box 2024-08-27 17:07:12 +08:00
e3ac7debc4 Fix info boxes for load/saving from flash 2024-08-27 17:00:16 +08:00
a8d7986c82 Move reset request to thermostat control menu
We don't get auto reconnect anymore
2024-08-27 16:51:01 +08:00
5a09c026fa Move pid autotuning request to CtrlPanel
And update autotune UI only on state change instead of every single
report update
2024-08-27 16:46:48 +08:00
8ab04ac3cd autotuner*s* 2024-08-27 16:04:07 +08:00
5ecbb262be Move channelGraph stuff inside LiveDataPlotter 2024-08-27 16:01:07 +08:00
f141705b0e Move plot_options_menu stuff into menu 2024-08-27 16:01:03 +08:00
19470b3d02 Move autotune ticking connect 2024-08-27 15:20:50 +08:00
5862a2f7d5 Moove functools up 2024-08-27 14:56:17 +08:00
ac34472d31 Get thermostat_ctrl_menu to subscribe to hwrev updates 2024-08-27 13:31:23 +08:00
f45061a652 Save/load info box content 2024-08-27 13:21:41 +08:00
d9a3fcdc4b Remove unused load/save request & signal 2024-08-27 13:19:06 +08:00
22fc7cbf22 Fix loading all channel settings would bring up 2 info boxes 2024-08-27 13:17:25 +08:00
0133d2e41b ok which commit to fixup huh 2024-08-27 12:06:57 +08:00
43758e12a3 hw_rev 2024-08-27 11:27:31 +08:00
5dcf9e8f31 fan_update: tec_qt to thermostat_ctrl_menu 2024-08-27 10:45:19 +08:00
40c0519237 Fix updating status label for hwrev = None 2024-08-27 10:40:06 +08:00
260a466078 Put some menu requests in menu itself 2024-08-26 18:01:01 +08:00
8a13ce2b47 Tie Thermostat ConnectionState to Qt signal for now
Change this to callback-based later for decoupling from Qt
2024-08-26 17:09:29 +08:00
ba369c880e Move sigActivatedHandle to CtrlPanel 2024-08-26 15:23:55 +08:00
375e159c39 Get rid of timeout on readline 2024-08-26 15:21:26 +08:00
4240312bf4 Put send_command in CtrlPanel 2024-08-26 13:49:56 +08:00
20f168e04c flake update 2024-08-26 13:11:26 +08:00
efe0c086d8 Extra bail removed 2024-08-26 12:21:57 +08:00
9f3591770a return hwrev when start_session 2024-08-26 12:21:57 +08:00
17157fd890 state str 2024-08-26 12:21:57 +08:00
42268e2186 params update concurrently 2024-08-26 12:21:57 +08:00
db15c0052e Compact 2024-08-26 12:21:57 +08:00
bfddfd8e20 Stuff non-UI changes in Thermostat model 2024-08-26 12:21:57 +08:00
77b66e15cc State dependend UI 2024-08-26 12:21:57 +08:00
ae51fc739e State 2024-08-26 12:21:57 +08:00
7279c4d64a Actually its OSError 2024-08-26 12:21:57 +08:00
71f40027f5 conneting 2024-08-26 12:21:57 +08:00
388c914c18 Remove wait_for
OSError raised anyways
2024-08-26 12:21:57 +08:00
659ed384ae {start,end}_session -> [dis]connect 2024-08-26 12:21:57 +08:00
b252dc6a44 Simplify on_connect_btn_clicked
Raise if OSError
2024-08-26 12:21:57 +08:00
0dbed18ba1 Connecting task moved? 2024-08-26 12:21:57 +08:00
2b9a4c168e AsyncIO version Client -> AsyncioClient 2024-08-26 12:21:57 +08:00
83405103f2 Exclusively use the Thermostat object as a medium
All calls to the Thermostat should be forwarded by the medium.
2024-08-26 12:21:57 +08:00
71f4ad6e34 Integrate WrappedClient into Thermostat model 2024-08-26 12:21:57 +08:00
4d21770542 Should not stop cancelling read if timeout'd 2024-08-26 12:21:57 +08:00
52ee422a70 Fix Autotuner state for forceful disconnect 2024-08-26 12:21:57 +08:00
5475bf7951 _ 2024-08-26 12:21:57 +08:00
da70430c35 Make connection loss handling more elegant
Show an info box on connection lost informing the user that the
Thermostat was forcefully disconnected.
2024-08-26 12:21:57 +08:00
5e8f61be9e ================gui_dev-fix_asyncio=============== 2024-08-26 12:21:57 +08:00
b6f936a65f This is bail 2024-08-26 12:21:57 +08:00
79cc11dd14 thermostat: Properly register task
Also Thermostat.task -> Thermostat._update_params_task
2024-08-26 12:21:57 +08:00
7a5bb8d308 ip -> host 2024-08-26 12:21:57 +08:00
7245e514e8 Lazy evaluating for debug string command 2024-08-26 12:21:57 +08:00
fbaeb870c6 Add pytec runnables 2024-08-26 12:21:52 +08:00
f922ea906f PYTHON shell 2024-08-26 12:18:22 +08:00
aef3a9870b Exactlier wording 2024-08-26 12:18:22 +08:00
752d6f8eab unused 2024-08-26 12:18:22 +08:00
7a5ec14b95 encoding 2024-08-26 12:18:22 +08:00
b2f188b556 Just catch asyncio.TimeoutError
Will just change to TimeoutError once we switch to Python 3.11 in the
flake.
2024-08-26 12:18:22 +08:00
a2afd81dcd Remove exception too general 2024-08-26 12:18:22 +08:00
89319c0cd9 Use asserts to check for connectivity 2024-08-26 12:18:22 +08:00
f75de51447 Add back the parent 2024-08-26 12:18:22 +08:00
6f0956b35c Fix method call 2024-08-26 12:18:22 +08:00
6067c41ca4 README: Proofread 2024-08-26 12:18:22 +08:00
8a01249d60 Swap order arounda bit more 2024-08-26 12:18:22 +08:00
0ec18dfbff Formatting 2024-08-26 12:18:22 +08:00
6f7b46bc2f Use qtextras 2024-08-26 12:18:19 +08:00
5 changed files with 45 additions and 65 deletions

View File

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

View File

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

View File

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

View File

@ -285,6 +285,19 @@ class CtrlPanel(QObject):
f"Channel {ch} PID Autotune has failed.", 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) @asyncSlot(int)
async def load_settings(self, ch): async def load_settings(self, ch):
await self.thermostat.load_cfg(ch) await self.thermostat.load_cfg(ch)
@ -303,17 +316,3 @@ class CtrlPanel(QObject):
f"Channel {ch} settings has been saved to flash.\n" f"Channel {ch} settings has been saved to flash.\n"
"It will be loaded on Thermostat reset, or when settings are explicitly loaded.", "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,7 +59,9 @@ class MainWindow(QtWidgets.QMainWindow):
self.info_box = InfoBox() self.info_box = InfoBox()
# Models # Models
self.thermostat = Thermostat(self, self.report_refresh_spin.value()) self.thermostat = Thermostat(
self, self.report_refresh_spin.value()
)
self._connecting_task = None self._connecting_task = None
self.thermostat.connection_state_changed.connect(self._on_connection_changed) self.thermostat.connection_state_changed.connect(self._on_connection_changed)