Compare commits

..

2 Commits

Author SHA1 Message Date
9c22950e59 State 2024-08-21 16:18:01 +08:00
cebf995427 Remove all timeouts from aioclient 2024-08-21 16:18:01 +08:00
7 changed files with 43 additions and 64 deletions

View File

@ -118,20 +118,6 @@
]; ];
}; };
pytec-dev-wrappers = pkgs.runCommandNoCC "pytec-dev-wrappers" {}
''
mkdir -p $out/bin
for program in ${self}/pytec/*.py; do
if [ -x $program ]; then
progname=`basename -s .py $program`
outname=$out/bin/$progname
echo "#!${pkgs.bash}/bin/bash" >> $outname
echo "exec python3 -m pytec.$progname \"\$@\"" >> $outname
chmod 755 $outname
fi
done
'';
thermostat_gui = pkgs.python3Packages.buildPythonPackage { thermostat_gui = pkgs.python3Packages.buildPythonPackage {
pname = "thermostat_gui"; pname = "thermostat_gui";
version = "0.0.0"; version = "0.0.0";
@ -177,7 +163,6 @@
rust rust
openocd openocd
dfu-util dfu-util
pytec-dev-wrappers
] ]
++ (with python3Packages; [ ++ (with python3Packages; [
numpy numpy
@ -189,9 +174,6 @@
pglive pglive
qtextras qtextras
]); ]);
shellHook = ''
export PYTHONPATH=`pwd`/pytec:$PYTHONPATH
'';
}; };
defaultPackage.x86_64-linux = thermostat; defaultPackage.x86_64-linux = thermostat;
}; };

0
pytec/autotune.py Executable file → Normal file
View File

View File

@ -4,7 +4,7 @@ from pytec.aioclient import AsyncioClient
async def main(): async def main():
tec = AsyncioClient() tec = AsyncioClient()
await tec.connect() # (host="192.168.1.26", port=23) await tec.start_session() # (host="192.168.1.26", port=23)
await tec.set_param("s-h", 1, "t0", 20) await tec.set_param("s-h", 1, "t0", 20)
print(await tec.get_pwm()) print(await tec.get_pwm())
print(await tec.get_pid()) print(await tec.get_pid())

0
pytec/plot.py Executable file → Normal file
View File

View File

@ -13,14 +13,13 @@ class AsyncioClient:
self._writer = None self._writer = None
self._command_lock = asyncio.Lock() self._command_lock = asyncio.Lock()
self._report_mode_on = False self._report_mode_on = False
self.timeout = None
async def connect(self, host="192.168.1.26", port=23): async def start_session(self, host="192.168.1.26", port=23):
"""Connect to Thermostat at specified host and port. """Start session to Thermostat at specified host and port.
Example:: Example::
client = AsyncioClient() client = AsyncioClient()
await client.connect() await client.start_session()
""" """
self._reader, self._writer = await asyncio.open_connection(host, port) self._reader, self._writer = await asyncio.open_connection(host, port)
await self._check_zero_limits() await self._check_zero_limits()
@ -29,8 +28,8 @@ class AsyncioClient:
"""Returns True if client is connected""" """Returns True if client is connected"""
return self._writer is not None return self._writer is not None
async def disconnect(self): async def end_session(self):
"""Disconnect from the Thermostat""" """End session to Thermostat"""
if self._writer is None: if self._writer is None:
return return
@ -54,9 +53,7 @@ class AsyncioClient:
async def _read_line(self): async def _read_line(self):
# read 1 line # read 1 line
chunk = await asyncio.wait_for( chunk = await self._reader.readline()
self._reader.readline(), self.timeout
) # Only wait for response until timeout
return chunk.decode("utf-8", errors="ignore") return chunk.decode("utf-8", errors="ignore")
async def _read_write(self, command): async def _read_write(self, command):
@ -70,7 +67,7 @@ class AsyncioClient:
line = await self._read_write(command) line = await self._read_write(command)
response = json.loads(line) response = json.loads(line)
logging.debug("%s: %s", command, response) logging.debug(f"{command}: {response}")
if "error" in response: if "error" in response:
raise CommandError(response["error"]) raise CommandError(response["error"])
return response return response
@ -241,7 +238,7 @@ class AsyncioClient:
self._writer.write("reset\n".encode("utf-8")) self._writer.write("reset\n".encode("utf-8"))
await self._writer.drain() await self._writer.drain()
await self.disconnect() await self.end_session()
async def dfu(self): async def dfu(self):
"""Put the Thermostat in DFU update mode """Put the Thermostat in DFU update mode
@ -254,7 +251,7 @@ class AsyncioClient:
self._writer.write("dfu\n".encode("utf-8")) self._writer.write("dfu\n".encode("utf-8"))
await self._writer.drain() await self._writer.drain()
await self.disconnect() await self.end_session()
async def ipv4(self): async def ipv4(self):
"""Get the IPv4 settings of the Thermostat""" """Get the IPv4 settings of the Thermostat"""

View File

@ -32,21 +32,20 @@ class Thermostat(QObject, metaclass=PropertyMeta):
self._report_mode_task = None self._report_mode_task = None
self._poll_for_report = True self._poll_for_report = True
self.connection_errored = False self.connection_errored = False
self.task = None
super().__init__(parent) super().__init__(parent)
async def start_session(self, host, port): async def start_session(self, host, port):
await self._client.connect(host, port) await self._client.start_session(host, port)
async def run(self): async def run(self):
self.task = asyncio.create_task(self.update_params()) self.task = asyncio.create_task(self.update_params())
while True: while True:
if self.task.done(): if self.task.done():
try: try:
self.task.result() _ = self.task.result()
except OSError: except asyncio.TimeoutError:
logging.error( logging.error(
"Encountered an error while polling for information from Thermostat.", "Encountered an error while updating parameter tree.",
exc_info=True, exc_info=True,
) )
self.connection_error.emit() self.connection_error.emit()
@ -104,7 +103,7 @@ class Thermostat(QObject, metaclass=PropertyMeta):
] ]
async def end_session(self): async def end_session(self):
await self._client.disconnect() await self._client.end_session()
self.connection_errored = False self.connection_errored = False
async def set_ipv4(self, ipv4): async def set_ipv4(self, ipv4):

55
pytec/tec_qt.py Executable file → Normal file
View File

@ -65,7 +65,6 @@ class MainWindow(QtWidgets.QMainWindow):
self.thermostat = Thermostat( self.thermostat = Thermostat(
self, self.report_refresh_spin.value() self, self.report_refresh_spin.value()
) )
self._connecting_task = None
def handle_connection_error(): def handle_connection_error():
self.info_box.display_info_box( self.info_box.display_info_box(
@ -239,38 +238,40 @@ class MainWindow(QtWidgets.QMainWindow):
except: except:
pass pass
def _connecting(self):
self.status_lbl.setText("Connecting...")
self.connect_btn.setText("Stop")
self.conn_menu.host_set_line.setEnabled(False)
self.conn_menu.port_set_spin.setEnabled(False)
@asyncSlot() @asyncSlot()
async def on_connect_btn_clicked(self): async def on_connect_btn_clicked(self):
if (self._connecting_task is None) and (not self.thermostat.connected()): host, port = (
host = self.conn_menu.host_set_line.text() self.conn_menu.host_set_line.text(),
port = self.conn_menu.port_set_spin.value() self.conn_menu.port_set_spin.value(),
)
self._connecting() self._connecting_task = None
self._connecting_task = asyncio.create_task( try:
self.thermostat.start_session(host=host, port=port) if (self._connecting_task is None) or (not self.thermostat.connected()):
) self.status_lbl.setText("Connecting...")
try: self.connect_btn.setText("Stop")
await self._connecting_task self.conn_menu.host_set_line.setEnabled(False)
except (OSError, asyncio.CancelledError) as exc: self.conn_menu.port_set_spin.setEnabled(False)
await self.bail()
if isinstance(exc, asyncio.CancelledError): try:
self._connecting_task = asyncio.wait_for(
self.thermostat.start_session(host=host, port=port), timeout=5
)
await self._connecting_task
except asyncio.TimeoutError:
return return
raise
else:
await self._on_connection_changed(True) await self._on_connection_changed(True)
finally: else:
self._connecting_task = None if self._connecting_task is not None:
self._connecting_task.cancel()
await self.bail()
elif self._connecting_task is not None: # TODO: Remove asyncio.TimeoutError in Python 3.11
self._connecting_task.cancel() except (OSError, asyncio.TimeoutError):
else: try:
await self.bail() await self.bail()
except ConnectionResetError:
pass
@asyncSlot() @asyncSlot()
async def bail(self): async def bail(self):