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 {
pname = "thermostat_gui";
version = "0.0.0";
@ -163,6 +177,7 @@
rust
openocd
dfu-util
pytec-dev-wrappers
]
++ (with python3Packages; [
numpy
@ -174,6 +189,9 @@
pglive
qtextras
]);
shellHook = ''
export PYTHONPATH=`pwd`/pytec:$PYTHONPATH
'';
};
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():
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)
print(await tec.get_pwm())
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.timeout = None
async def start_session(self, host="192.168.1.26", port=23):
"""Start session to Thermostat at specified host and port.
async def connect(self, host="192.168.1.26", port=23):
"""Connect to Thermostat at specified host and port.
Example::
client = AsyncioClient()
await client.start_session()
await client.connect()
"""
self._reader, self._writer = await asyncio.open_connection(host, port)
await self._check_zero_limits()
@ -29,8 +29,8 @@ class AsyncioClient:
"""Returns True if client is connected"""
return self._writer is not None
async def end_session(self):
"""End session to Thermostat"""
async def disconnect(self):
"""Disconnect from the Thermostat"""
if self._writer is None:
return
@ -70,7 +70,7 @@ class AsyncioClient:
line = await self._read_write(command)
response = json.loads(line)
logging.debug(f"{command}: {response}")
logging.debug("%s: %s", command, response)
if "error" in response:
raise CommandError(response["error"])
return response
@ -241,7 +241,7 @@ class AsyncioClient:
self._writer.write("reset\n".encode("utf-8"))
await self._writer.drain()
await self.end_session()
await self.disconnect()
async def dfu(self):
"""Put the Thermostat in DFU update mode
@ -254,7 +254,7 @@ class AsyncioClient:
self._writer.write("dfu\n".encode("utf-8"))
await self._writer.drain()
await self.end_session()
await self.disconnect()
async def ipv4(self):
"""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
import asyncio
import logging
from enum import Enum
from pytec.aioclient import AsyncioClient
class ThermostatConnectionState(Enum):
STATE_DISCONNECTED = "disconnected"
STATE_CONNECTING = "connecting"
STATE_CONNECTED = "connected"
class Thermostat(QObject, metaclass=PropertyMeta):
hw_rev = Property(dict)
fan = Property(dict)
@ -25,20 +32,21 @@ class Thermostat(QObject, metaclass=PropertyMeta):
self._report_mode_task = None
self._poll_for_report = True
self.connection_errored = False
self.task = None
super().__init__(parent)
async def start_session(self, host, port):
await self._client.start_session(host, port)
await self._client.connect(host, port)
async def run(self):
self.task = asyncio.create_task(self.update_params())
while True:
if self.task.done():
try:
_ = self.task.result()
except asyncio.TimeoutError:
self.task.result()
except OSError:
logging.error(
"Encountered an error while updating parameter tree.",
"Encountered an error while polling for information from Thermostat.",
exc_info=True,
)
self.connection_error.emit()
@ -96,7 +104,7 @@ class Thermostat(QObject, metaclass=PropertyMeta):
]
async def end_session(self):
await self._client.end_session()
await self._client.disconnect()
self.connection_errored = False
async def set_ipv4(self, ipv4):

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

@ -65,6 +65,7 @@ class MainWindow(QtWidgets.QMainWindow):
self.thermostat = Thermostat(
self, self.report_refresh_spin.value()
)
self._connecting_task = None
def handle_connection_error():
self.info_box.display_info_box(
@ -238,40 +239,38 @@ class MainWindow(QtWidgets.QMainWindow):
except:
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()
async def on_connect_btn_clicked(self):
host, port = (
self.conn_menu.host_set_line.text(),
self.conn_menu.port_set_spin.value(),
)
if (self._connecting_task is None) and (not self.thermostat.connected()):
host = self.conn_menu.host_set_line.text()
port = 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.connect_btn.setText("Stop")
self.conn_menu.host_set_line.setEnabled(False)
self.conn_menu.port_set_spin.setEnabled(False)
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
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
except (OSError, asyncio.TimeoutError):
self._connecting()
self._connecting_task = asyncio.create_task(
self.thermostat.start_session(host=host, port=port)
)
try:
await self._connecting_task
except (OSError, asyncio.CancelledError) as exc:
await self.bail()
except ConnectionResetError:
pass
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()
@asyncSlot()
async def bail(self):