From 2a6be5d50a719eaa8f66142cea85b9b0b2bd2c09 Mon Sep 17 00:00:00 2001 From: Hector van der Aa Date: Wed, 29 Jul 2026 17:43:57 +0100 Subject: [PATCH] Initial disk pairing impl --- main.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/main.py b/main.py index 2c9705a..5ca126f 100644 --- a/main.py +++ b/main.py @@ -1,11 +1,13 @@ from functools import partial +import json +from pathlib import Path from queue import Empty, Queue from time import sleep from typing import Literal import pyudev from gpiozero import LED, Button from threading import Thread, Event -from dataclasses import dataclass +from dataclasses import asdict, dataclass red = LED(17) yellow = LED(27) @@ -23,11 +25,36 @@ class DiskEvent: DiskState = Literal["disconnected", "pairing", "connecting", "connected"] +@dataclass +class Config: + diskSerial: str = "" + + @dataclass class AppState: stopEvent = Event() diskEventQueue: Queue[DiskEvent] = Queue() diskState: DiskState = "disconnected" + config = Config() + + +def saveConfig(config: Config, path: Path) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + + with path.open("w", encoding="utf-8") as file: + json.dump(asdict(config), file, indent=4) + + +def loadOrCreateConfig(path: Path) -> Config: + if not path.exists(): + config = Config() + saveConfig(config, path) + return config + + with path.open("r", encoding="utf-8") as file: + rawConfig = json.load(file) + + return Config(**rawConfig) def onButtonPressed(state: AppState) -> None: @@ -98,9 +125,25 @@ def ledWorker(state: AppState) -> None: state.stopEvent.wait(0.25) +def findDiskNode(serial: str) -> str | None: + context = pyudev.Context() + + for device in context.list_devices( + subsystem="block", + DEVTYPE="disk", + ): + deviceSerial = device.get("ID_SERIAL_SHORT") or device.get("ID_SERIAL") + + if deviceSerial == serial: + return device.device_node + + return None + + def main() -> None: try: state = AppState() + state.config = loadOrCreateConfig("config.json") button.when_activated = partial(onButtonPressed, state) diskPollThread = Thread( @@ -124,7 +167,16 @@ def main() -> None: while True: try: event = state.diskEventQueue.get_nowait() - print(event) + if ( + state.diskState == "pairing" + and event.event == "connected" + and event.serial != "Unknown" + ): + state.config.diskSerial = event.serial + saveConfig(state.config, "config.json") + print(findDiskNode(state.config.diskSerial)) + state.diskState = "connected" + except Empty: sleep(1)