""" Fiber + radio port: central domain object for a row in fiber_map.json. Power (Acroname hub downstream), SSH routing, PCIe / wlan / USB metadata all hang off this aggregate. ``FiWiHarness`` supplies BrainStem power; not the conceptual center. """ from __future__ import annotations from dataclasses import dataclass from typing import Any, Dict, Iterator, List, Optional, Tuple from fiwi import fiber_map_io as fm from fiwi.ssh_node import SshNode @dataclass class FiberRadioPort: """ One logical fiber/radio attachment: ``fiber_ports[]`` in the map document. ``entry`` is the live dict from the document (mutations persist when the doc is saved). """ map_key: str entry: Optional[Dict[str, Any]] @property def port_id(self) -> Optional[int]: """Integer fiber id when ``map_key`` is decimal; else None.""" if self.map_key.isdigit(): return int(self.map_key) return None def hub_port(self) -> Optional[Tuple[int, int]]: """(hub_1based, port_0based) or None if unmapped / invalid.""" return fm.fiber_entry_hub_port(self.entry) def ssh_target(self) -> Optional[str]: """user@host when this port’s hubs are reached via SSH; else None.""" return fm.fiber_ssh_target(self.entry) if isinstance(self.entry, dict) else None def ssh_node(self) -> Optional[SshNode]: """Remote Fi-Wi host (``SshNode``) for this port, or None when mapped locally.""" t = self.ssh_target() if not t: return None try: return SshNode.parse(t) except ValueError: return None def is_mapped(self) -> bool: """True when hub.port is valid in the entry.""" return self.hub_port() is not None def chip_preview(self, width: int = 26) -> str: return fm.stored_chip_preview(self.entry) if isinstance(self.entry, dict) else "" def pcie_preview(self, width: int = 22) -> str: return fm.stored_pcie_preview(self.entry) if isinstance(self.entry, dict) else "" @classmethod def from_map_key(cls, doc: Dict[str, Any], map_key: str) -> FiberRadioPort: ports = doc.get("fiber_ports") if isinstance(doc, dict) else None if not isinstance(ports, dict): return cls(str(map_key), None) ent = ports.get(str(map_key)) return cls( str(map_key), ent if isinstance(ent, dict) else None, ) @classmethod def from_port_id(cls, doc: Dict[str, Any], port_id: int) -> FiberRadioPort: return cls.from_map_key(doc, str(int(port_id))) @staticmethod def each_from_document(doc: Dict[str, Any]) -> Iterator[FiberRadioPort]: """All ``fiber_ports`` rows (sorted), including unmapped / empty values.""" ports = doc.get("fiber_ports") if isinstance(doc, dict) else None if not isinstance(ports, dict): return for key in sorted(ports.keys(), key=fm.fiber_sort_key): ent = ports[key] yield FiberRadioPort( str(key), ent if isinstance(ent, dict) else None, ) def load_fiber_radio_ports(doc: Dict[str, Any]) -> List[FiberRadioPort]: """Registry of all fiber map rows (sorted keys).""" return list(FiberRadioPort.each_from_document(doc))