Compare commits

...

17 Commits

Author SHA1 Message Date
2b6b7f4db0 State 2024-08-23 11:37:03 +08:00
9ad20dcf4d Actually its OSError 2024-08-23 11:37:03 +08:00
ccec874756 _ 2024-08-23 11:37:03 +08:00
54472c0eee Resgister task 2024-08-23 11:37:03 +08:00
66ca5e9597 conneting 2024-08-23 11:37:03 +08:00
632ee8bfa3 Remove wait_for
OSError raised anyways
2024-08-23 11:37:03 +08:00
506d350d7f Raise if OSError 2024-08-23 11:37:03 +08:00
93e0bd91bf Sep. line 2024-08-23 11:37:03 +08:00
b15490e3b5 {start,end}_session -> [dis]connect 2024-08-23 11:37:03 +08:00
920706fbab Lazy evaluating for debug string command 2024-08-23 11:37:03 +08:00
c0e4d49b7b In 2024-08-23 11:37:03 +08:00
23f484e3d8 Compacting 2024-08-23 11:37:03 +08:00
b0c30d128e try-block 2024-08-23 11:37:03 +08:00
cebac565c4 Fix? 2024-08-23 11:37:03 +08:00
9af7f728e9 Add pytec runnables 2024-08-23 11:37:03 +08:00
bef73df401 PYTHON shell 2024-08-23 11:37:03 +08:00
f1d33f4729 Exactlier wording 2024-08-23 11:37:03 +08:00
7 changed files with 68 additions and 43 deletions

View File

@ -118,6 +118,20 @@
]; ];
}; };
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";
@ -163,6 +177,7 @@
rust rust
openocd openocd
dfu-util dfu-util
pytec-dev-wrappers
] ]
++ (with python3Packages; [ ++ (with python3Packages; [
numpy numpy
@ -174,6 +189,9 @@
pglive pglive
qtextras qtextras
]); ]);
shellHook = ''
export PYTHONPATH=`pwd`/pytec:$PYTHONPATH
'';
}; };
defaultPackage.x86_64-linux = thermostat; defaultPackage.x86_64-linux = thermostat;
}; };

0
pytec/autotune.py Normal file → Executable 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.start_session() # (host="192.168.1.26", port=23) await tec.connect() # (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 Normal file → Executable file
View File

View File

@ -15,12 +15,12 @@ class AsyncioClient:
self._report_mode_on = False self._report_mode_on = False
self.timeout = None self.timeout = None
async def start_session(self, host="192.168.1.26", port=23): async def connect(self, host="192.168.1.26", port=23):
"""Start session to Thermostat at specified host and port. """Connect to Thermostat at specified host and port.
Example:: Example::
client = AsyncioClient() client = AsyncioClient()
await client.start_session() await client.connect()
""" """
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 +29,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 end_session(self): async def disconnect(self):
"""End session to Thermostat""" """Disconnect from the Thermostat"""
if self._writer is None: if self._writer is None:
return return
@ -70,7 +70,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(f"{command}: {response}") logging.debug("%s: %s", command, response)
if "error" in response: if "error" in response:
raise CommandError(response["error"]) raise CommandError(response["error"])
return response return response
@ -241,7 +241,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.end_session() await self.disconnect()
async def dfu(self): async def dfu(self):
"""Put the Thermostat in DFU update mode """Put the Thermostat in DFU update mode
@ -254,7 +254,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.end_session() await self.disconnect()
async def ipv4(self): async def ipv4(self):
"""Get the IPv4 settings of the Thermostat""" """Get the IPv4 settings of the Thermostat"""

View File

@ -3,9 +3,16 @@ 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 enum import Enum
from pytec.aioclient import AsyncioClient from pytec.aioclient import AsyncioClient
class ThermostatConnectionState(Enum):
STATE_DISCONNECTED = "disconnected"
STATE_CONNECTING = "connecting"
STATE_CONNECTED = "connected"
class Thermostat(QObject, metaclass=PropertyMeta): class Thermostat(QObject, metaclass=PropertyMeta):
hw_rev = Property(dict) hw_rev = Property(dict)
fan = Property(dict) fan = Property(dict)
@ -25,20 +32,21 @@ 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.start_session(host, port) await self._client.connect(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 asyncio.TimeoutError: except OSError:
logging.error( logging.error(
"Encountered an error while updating parameter tree.", "Encountered an error while polling for information from Thermostat.",
exc_info=True, exc_info=True,
) )
self.connection_error.emit() self.connection_error.emit()
@ -96,7 +104,7 @@ class Thermostat(QObject, metaclass=PropertyMeta):
] ]
async def end_session(self): async def end_session(self):
await self._client.end_session() await self._client.disconnect()
self.connection_errored = False self.connection_errored = False
async def set_ipv4(self, ipv4): async def set_ipv4(self, ipv4):

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

@ -65,6 +65,7 @@ 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(
@ -238,40 +239,38 @@ class MainWindow(QtWidgets.QMainWindow):
except: except:
pass pass
@asyncSlot() def _connecting(self):
async def on_connect_btn_clicked(self):
host, port = (
self.conn_menu.host_set_line.text(),
self.conn_menu.port_set_spin.value(),
)
self._connecting_task = None
try:
if (self._connecting_task is None) or (not 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: @asyncSlot()
self._connecting_task = asyncio.wait_for( async def on_connect_btn_clicked(self):
self.thermostat.start_session(host=host, port=port), timeout=5 if (self._connecting_task is None) and (not self.thermostat.connected()):
) host = self.conn_menu.host_set_line.text()
await self._connecting_task port = self.conn_menu.port_set_spin.value()
except asyncio.TimeoutError:
return
await self._on_connection_changed(True)
else:
if self._connecting_task is not None:
self._connecting_task.cancel()
await self.bail()
# TODO: Remove asyncio.TimeoutError in Python 3.11 self._connecting()
except (OSError, asyncio.TimeoutError): self._connecting_task = asyncio.create_task(
self.thermostat.start_session(host=host, port=port)
)
try: try:
await self._connecting_task
except (OSError, asyncio.CancelledError) as exc:
await self.bail()
if isinstance(exc, asyncio.CancelledError):
return
raise
else:
await self._on_connection_changed(True)
finally:
self._connecting_task = None
elif self._connecting_task is not None:
self._connecting_task.cancel()
else:
await self.bail() await self.bail()
except ConnectionResetError:
pass
@asyncSlot() @asyncSlot()
async def bail(self): async def bail(self):