Auto-detect relay port via ID probe in relay script
This commit is contained in:
parent
828261ac0f
commit
3ec47427cf
3 changed files with 59 additions and 7 deletions
|
|
@ -67,11 +67,18 @@ reboot** — nooit hardcoden. Detectie:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /Users/eddy/src/usbtoggle
|
cd /Users/eddy/src/usbtoggle
|
||||||
./relay 1 [poort] # relais aan → USB afgekoppeld (module uit)
|
./relay 1 # relais aan → USB afgekoppeld (module uit)
|
||||||
./relay 0 [poort] # relais uit → USB aangekoppeld (module aan)
|
./relay 0 # relais uit → USB aangekoppeld (module aan)
|
||||||
./relay id [poort] # identificatie (chip-ID)
|
./relay id # identificatie (chip-ID)
|
||||||
|
./relay 1 /dev/cu.usbserial-XXXX # poort expliciet opgeven (alleen als auto-detect faalt)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- Zonder poortargument zoekt het script de module **automatisch**: het
|
||||||
|
probeert alle CH340-poorten (`VID:PID=1A86:7523`) met het `id`-commando
|
||||||
|
en gebruikt de eerste die `ID usbtoggle-relay` antwoordt. De module
|
||||||
|
wordt dus gevonden waar die ook is aangesloten; de poortnaam hoeft
|
||||||
|
nooit hardcoded te worden.
|
||||||
|
|
||||||
- Replies: `ON` / `OFF` / `ID ...`; exit 0 = gelukt, exit 1 = fout (usage,
|
- Replies: `ON` / `OFF` / `ID ...`; exit 0 = gelukt, exit 1 = fout (usage,
|
||||||
poort niet te openen, geen geldige reply).
|
poort niet te openen, geen geldige reply).
|
||||||
- Het script opent de poort met DTR/RTS gedeasserted (geen CH340 auto-reset);
|
- Het script opent de poort met DTR/RTS gedeasserted (geen CH340 auto-reset);
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,14 @@ Sluit aan via USB en stuur commando's:
|
||||||
```bash
|
```bash
|
||||||
./relay 1 # relais aan
|
./relay 1 # relais aan
|
||||||
./relay 0 # relais uit
|
./relay 0 # relais uit
|
||||||
./relay 1 /dev/cu.usbserial-XXXX # poort opgeven als default afwijkt
|
|
||||||
./relay id # toont module-ID (chip-ID, uniek per chip, onafhankelijk van USB-poort)
|
./relay id # toont module-ID (chip-ID, uniek per chip, onafhankelijk van USB-poort)
|
||||||
|
./relay 1 /dev/cu.usbserial-XXXX # poort expliciet opgeven (alleen als auto-detect faalt)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Zonder poortargument zoekt het script de module zelf: het probeert alle
|
||||||
|
CH340-poorten met het `id`-commando en gebruikt de eerste die `ID
|
||||||
|
usbtoggle-relay` antwoordt — waar de module ook is aangesloten.
|
||||||
|
|
||||||
## Pinnen
|
## Pinnen
|
||||||
|
|
||||||
| Component | GPIO |
|
| Component | GPIO |
|
||||||
|
|
|
||||||
47
relay
47
relay
|
|
@ -1,9 +1,42 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Toggle the USB relay via serial: ./relay 1|0|id [serial_port]."""
|
"""Toggle the USB relay via serial: ./relay 1|0|id [serial_port].
|
||||||
|
|
||||||
|
Without an explicit port the relay board is found automatically: every
|
||||||
|
USB serial port is probed with the ID command until one answers.
|
||||||
|
"""
|
||||||
import sys
|
import sys
|
||||||
import serial
|
import serial
|
||||||
|
import serial.tools.list_ports
|
||||||
|
|
||||||
DEFAULT_PORT = "/dev/cu.usbserial-2110"
|
|
||||||
|
def find_relay_port() -> str | None:
|
||||||
|
"""Find the relay board by probing CH340 ports with the ID command."""
|
||||||
|
candidates = [
|
||||||
|
p.device
|
||||||
|
for p in serial.tools.list_ports.comports()
|
||||||
|
if "1A86:7523" in (p.hwid or "")
|
||||||
|
]
|
||||||
|
for dev in candidates:
|
||||||
|
try:
|
||||||
|
s = serial.Serial()
|
||||||
|
s.port = dev
|
||||||
|
s.baudrate = 115200
|
||||||
|
s.timeout = 1
|
||||||
|
s.dtr = False
|
||||||
|
s.rts = False
|
||||||
|
s.open()
|
||||||
|
try:
|
||||||
|
s.readline() # gooi boot-banner weg
|
||||||
|
s.reset_input_buffer()
|
||||||
|
s.write(b"?")
|
||||||
|
s.flush()
|
||||||
|
if s.readline().decode(errors="replace").startswith("ID "):
|
||||||
|
return dev
|
||||||
|
finally:
|
||||||
|
s.close()
|
||||||
|
except serial.SerialException:
|
||||||
|
continue
|
||||||
|
return None
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
if len(sys.argv) not in (2, 3) or sys.argv[1] not in ("0", "1", "id"):
|
if len(sys.argv) not in (2, 3) or sys.argv[1] not in ("0", "1", "id"):
|
||||||
|
|
@ -11,7 +44,15 @@ def main() -> int:
|
||||||
return 1
|
return 1
|
||||||
command = sys.argv[1]
|
command = sys.argv[1]
|
||||||
serial_cmd = "?" if command == "id" else command
|
serial_cmd = "?" if command == "id" else command
|
||||||
port = sys.argv[2] if len(sys.argv) == 3 else DEFAULT_PORT
|
if len(sys.argv) == 3:
|
||||||
|
port = sys.argv[2]
|
||||||
|
else:
|
||||||
|
port = find_relay_port()
|
||||||
|
if port is None:
|
||||||
|
print("ERROR: no relay module found on any USB serial port",
|
||||||
|
file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
print(f"Using {port}", file=sys.stderr)
|
||||||
try:
|
try:
|
||||||
# dtr/rts expliciet uit vóór open: voorkomt (of beperkt) de CH340
|
# dtr/rts expliciet uit vóór open: voorkomt (of beperkt) de CH340
|
||||||
# auto-reset (DTR->RST) bij het openen van de poort. pyserial 3.5
|
# auto-reset (DTR->RST) bij het openen van de poort. pyserial 3.5
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue