From b4027baf6837b9cc720f17a37baf41b46697a6b5 Mon Sep 17 00:00:00 2001 From: Eli Ribble Date: Fri, 26 May 2023 09:44:17 -0700 Subject: [PATCH] Don't require a full pin scan for the root page. The full pin scan is slow, and it's slowing me down. Instead, just load what we know we need for the configured relays unless we are adding a new relay. --- pnpdevice/relays.py | 109 ++++++++++++++++++++++++-------------------- pnpdevice/server.py | 1 + 2 files changed, 61 insertions(+), 49 deletions(-) diff --git a/pnpdevice/relays.py b/pnpdevice/relays.py index 83fb4d8..7aee8a5 100644 --- a/pnpdevice/relays.py +++ b/pnpdevice/relays.py @@ -87,10 +87,10 @@ class Manager: self.configpath = configpath self.has_fakes = has_fakes - # Handles to various chips - self._chips = [] - # Info on various pins - self._pins = [] + # Handles to various chips, mapped by chip number + self._chips = {} + # Info on various pins, mapped by (chip number, line_number) + self._pins = {} # Cached info on the relays self._relays = [] # Connection to single-board computer GPIO @@ -104,7 +104,7 @@ class Manager: def chips(self) -> List[Chip]: if not self._chips: self._load_chips() - return self._chips + return self._chips.values() def connect(self) -> None: self.sbc = rgpio.sbc( @@ -116,16 +116,18 @@ class Manager: self.sbc = None def get_chip_by_number(self, number: int) -> Chip: - for chip in self.chips: - if chip.number == number: - return chip - raise Exception(f"Can't find chip {number}") + try: + return self._chips[number] + except KeyError: + self._load_chip(number) + return self._chips[number] def get_pin_by_number(self, chip: Chip, line_number: int) -> Pin: - for pin in self.pins: - if pin.chip == chip and pin.line_number == line_number: - return pin - raise Exception(f"Can't find pin {chip.name}-{line_number}") + try: + return self._pins[(chip.number, line_number)] + except KeyError: + self._load_pin(chip, line_number) + return self._pins[(chip.number, line_number)] def get_relay_by_pin_id(self, pin_id: str) -> Relay: for relay in self.relays: @@ -133,11 +135,15 @@ class Manager: return relay return None + def load_all_pins(self) -> None: + self._load_chips() + self._load_pins() + @property def pins(self) -> List[Pin]: if not self._pins: self._load_pins() - return self._pins + return self._pins.values() @property def relays(self) -> Iterable[Relay]: @@ -177,50 +183,55 @@ class Manager: def shutdown(self) -> None: _write_config(self.configpath, self.config) + def _load_chip(self, number: int) -> None: + try: + handle = self.sbc.gpiochip_open(number) + except rgpio.error: + return + if handle < 0: + return + okay, number_of_lines, name, label = self.sbc.gpio_get_chip_info(handle) + LOGGER.info("Chip info: %s %s %s %s", okay, number_of_lines, name, label) + if okay != 0: + LOGGER.warn("Chip %s not okay.", name) + return + self._chips[number] = Chip( + handle=handle, + label=label, + name=name, + number=number, + number_of_lines=number_of_lines, + ) + # Talk to the remote pins daemon and get information about the chips def _load_chips(self) -> None: for i in range(MAX_CHIPS): - try: - handle = self.sbc.gpiochip_open(i) - except rgpio.error: - continue - if handle < 0: - continue - okay, number_of_lines, name, label = self.sbc.gpio_get_chip_info(handle) - LOGGER.info("Chip info: %s %s %s %s", okay, number_of_lines, name, label) - if okay != 0: - LOGGER.warn("Chip %s not okay.", name) - continue - self._chips.append(Chip( - handle=handle, - label=label, - name=name, - number=i, - number_of_lines=number_of_lines, - )) + self._load_chip(i) + + def _load_pin(self, chip: Chip, line_number: int) -> None: + okay, offset, flags, name, user = self.sbc.gpio_get_line_info(chip.handle, line_number) + LOGGER.info("Got line info: %s %s %s %s %s", okay, offset, flags, name, user) + assert offset == line_number + if okay != 0: + LOGGER.warn("Line %s is not okay", name) + return + if not name: + LOGGER.warn("Ignoring line %d because it has no name.", line_number) + return + self._pins[(chip.number, line_number)] = Pin( + chip=chip, + flags=flags, + line_number=line_number, + name=name, + user=user, + ) # Talk to the remote pins daemon and get information about the pins def _load_pins(self) -> None: LOGGER.info("Loading pins") for chip in self.chips: for line in range(chip.number_of_lines): - okay, offset, flags, name, user = self.sbc.gpio_get_line_info(chip.handle, line) - LOGGER.info("Got line info: %s %s %s %s %s", okay, offset, flags, name, user) - assert offset == line - if okay != 0: - LOGGER.warn("Line %s is not okay", name) - continue - if not name: - LOGGER.warn("Ignoring line %d because it has no name.", line) - continue - self._pins.append(Pin( - chip=chip, - flags=flags, - line_number=line, - name=name, - user=user, - )) - + self._load_pin(chip, line) def _read_config(configpath: pathlib.Path) -> None: with open(configpath, "rb") as f: diff --git a/pnpdevice/server.py b/pnpdevice/server.py index 22303e6..24b48d6 100644 --- a/pnpdevice/server.py +++ b/pnpdevice/server.py @@ -36,6 +36,7 @@ def index(request: Request): @app.get("/relay/create") def relay_create_get(request: Request): "Get the form to create a new relay." + relays.load_all_pins() pins = relays.pins return templates.TemplateResponse("relay-create.template.html", { "request": request,