Feature/influx check #3

Merged
kkallas merged 3 commits from feature/influx-check into main 2026-10-02 11:39:48 +02:00
2 changed files with 52 additions and 3 deletions
Showing only changes of commit 2b6d43eb45 - Show all commits

No files matched your search

+12 -3
View File
@@ -10,6 +10,7 @@ from __future__ import annotations
import enum import enum
import queue import queue
import sys
import threading import threading
import time import time
from collections.abc import Callable from collections.abc import Callable
@@ -92,13 +93,21 @@ class SerialManager:
ser = serial.serial_for_url( ser = serial.serial_for_url(
info.device, baudrate=self._baud, timeout=READ_TIMEOUT_S, do_not_open=True info.device, baudrate=self._baud, timeout=READ_TIMEOUT_S, do_not_open=True
) )
# Deassert both lines before open. On USB-Serial-JTAG, RTS=1/DTR=0 # On USB-Serial-JTAG, RTS=1/DTR=0 holds the chip in reset and DTR=1
# holds the chip in reset and DTR=1 during reset selects download # during reset selects download mode.
# mode; pyserial would otherwise assert both on open (Windows). # Windows: pyserial applies both lines atomically at open, so
# deassert both beforehand (it would otherwise assert both).
# macOS/Linux: the OS asserts both lines on open and pyserial then
# writes DTR before RTS, passing through RTS=1/DTR=0 and resetting
# the box on every connect. Drop RTS first, then DTR.
posix = sys.platform != "win32"
if not posix:
ser.dtr = False ser.dtr = False
ser.rts = False ser.rts = False
try: try:
ser.open() ser.open()
if posix:
ser.dtr = False
except (serial.SerialException, OSError): except (serial.SerialException, OSError):
return None return None
self._target.device = info.device # COM number / node may change self._target.device = info.device # COM number / node may change
+40
View File
@@ -86,6 +86,46 @@ def test_hard_reset_pushes_rts_via_dtr_write(monkeypatch):
assert all(c[1] is False for c in ser.calls if c[0] == "dtr") assert all(c[1] is False for c in ser.calls if c[0] == "dtr")
class _PosixOpenSerial:
"""pyserial on macOS/Linux: the OS asserts both lines on open, then
pyserial writes the requested DTR, then RTS. Records every line state."""
def __init__(self, *args, **kwargs):
self.port = args[0] if args else "fake"
self.dtr = self.rts = True # pyserial defaults
self.states = []
def __setattr__(self, name, value):
object.__setattr__(self, name, value)
if name in ("dtr", "rts") and getattr(self, "is_open", False):
self.states.append((self.dtr, self.rts))
def open(self):
want_dtr, want_rts = self.dtr, self.rts
object.__setattr__(self, "dtr", True)
object.__setattr__(self, "rts", True)
self.is_open = True
self.states.append((True, True))
self.dtr = want_dtr
self.rts = want_rts
def test_open_on_posix_never_passes_through_reset(monkeypatch):
monkeypatch.setattr(mgr_mod.sys, "platform", "darwin")
monkeypatch.setattr(mgr_mod, "find_port", lambda sn, dev: LOOP)
opened = []
monkeypatch.setattr(
mgr_mod.serial, "serial_for_url",
lambda *a, **k: opened.append(_PosixOpenSerial(*a, **k)) or opened[-1],
)
m = SerialManager(lambda ln: None, lambda s, d: None)
m._target = mgr_mod._Target(LOOP.device, None)
ser = m._open()
# (DTR, RTS) = (False, True) resets the chip on connect.
assert (False, True) not in ser.states
assert ser.states[-1] == (False, False)
def test_waits_when_port_missing(monkeypatch): def test_waits_when_port_missing(monkeypatch):
monkeypatch.setattr(mgr_mod, "find_port", lambda sn, dev: None) monkeypatch.setattr(mgr_mod, "find_port", lambda sn, dev: None)
states, lines = [], [] states, lines = [], []