The State & Topology Plane (Fleet Orchestration)
The State & Topology Plane acts as the stateful, topology-aware "Fleet Engine" of the xovis-sdk. It abstracts physical sensors, lens topologies, and virtual multisensor clusters into highly organized, accessible structures.
Interaction: Topology, Cache, and StateBucket
To build robust, offline-first fleet management, the SDK separates structural relationships from the configurations themselves. This is achieved through the coordinated interplay of Topology, Cache, Buckets, and Managers.
Demystifying the Terms
To navigate the State & Topology Plane with confidence, it helps to understand these four core concepts:
- Topology (The Floorplan / Blueprint): This is the logical and physical map of your network and hardware. It defines which physical sensors (
singlesensor) and virtual stitched environments (multisensors) actually exist. It does not contain configuration data; it only defines the structure of what can be configured (like physical rack layouts and loading zones). - Bucket (The Shipping Pallets / Crates): A StateBucket (e.g.,
HostStateBucketorContextStateBucket) is a raw, behaviorless data container. It holds JSON-serialized lists of resources (zones, lines, agents, connections) belonging to a specific context. It is the structured "cargo" or contents stored in a specific compartment. - Cache (The Warehouse): This is the localized storage repository (the in-memory state mapping and the persisted
device_state.jsonfile) where all state buckets are stored. It acts as the offline-first single source of truth for the SDK, indexing and holding all assets. - Manager (The Warehouse Operator): The active orchestrator (specifically
ConfigCacheManagerorHubCacheManager) that manages the lifecycle of the cache. It executes the synchronization loops (sync), schedules background updates, handles disk serialization via non-blocking threads, and exposes intuitive dot-notationREPLAccessorlayers.
The Core Workflow
- Topology Discovery: The
client.topologymanager identifies which contexts exist. It discovers if the sensor is a standalone device (singlesensor) or part of a stitchedmultisensorcluster. - Cache Synchronization: When you call
await client.cache.sync(), the SDK queries the topology map to find all active physical and virtual context endpoints, fetches their configurations, and populates the localized Cache. - StateBucket Storage: For every context identified in the topology, the SDK isolates and populates a localized
StateBucketwithin the Cache containing the specific zones, lines, and agents belonging to that context.
The Map"]:::client C["Config Cache Manager
The Orchestrator"]:::client end subgraph Network [LAN & Remote Network] L["Physical Lens"]:::network MS["Multisensor Cluster"]:::network end T -- "Scans & Discovers" --> Network C <-- "Uses Map from" --> T subgraph Buckets [State Buckets / Contexts] SB1["Bucket: singlesensor
Zones, Lines, Agents"]:::buckets SB2["Bucket: multisensor_1
Multisensor Zones, Logics"]:::buckets end C -- "Populates & Manages" --> Buckets SB1 -- "Represents Data for" --> L SB2 -- "Represents Data for" --> MS %% 3-Tier Cache System (Disk/System/Memory) subgraph DiskStorage ["3-Tier Caching System"] Tier1["Tier 1: Local Workspace
_local_resources/states/"]:::cache Tier2["Tier 2: System Cache
~/.cache/xovis/"]:::cache Tier3["Tier 3: Memory Fallback
RAM Only"]:::cache end C -- "Persists to" --> DiskStorage %% Styling Overrides style DeviceClient fill:#0f172a,stroke:#2dd4bf,stroke-dasharray: 5 5 style Network fill:#0f172a,stroke:#38bdf8,stroke-dasharray: 5 5 style Buckets fill:#111827,stroke:#818cf8,stroke-dasharray: 5 5 style DiskStorage fill:#111827,stroke:#eab308,stroke-dasharray: 5 5
When you execute client.cache.export_to_file("device_state.json"), the SDK aggregates all localized StateBuckets structured by the TopologyManager and dumps them into a single, cohesive offline state JSON file.
Component Responsibilities
| Component | Responsibility | Technical Definition | Analogy |
|---|---|---|---|
| Topology | Structural Logic: Discovers active network hosts, lens clusters, and synthesizes multisensor graphs. | TopologyManager |
The Floorplan / Aisles Layout of the warehouse. |
| Managers | Life-cycle Management: Active executor running sync loops, background watchers, and disk serialization. | ConfigCacheManager / HubCacheManager |
The Warehouse Operator / Dispatcher managing inventory flow. |
| Cache | State Repository: The in-memory collection and serialized files representing the offline-first state of the fleet. | Local state cache dictionary / device_state.json |
The Warehouse itself where all assets are stored and indexed. |
| Buckets | Data Container: Isolated Pydantic models containing serialized zones, lines, and agents for a context. | HostStateBucket / ContextStateBucket |
The Shipping Pallets / Crates holding specific grouped cargo. |
Multisensor Topology & Caching Lifecycle
The xovis-sdk features specialized, high-performance lifecycle handlers for multisensor network clusters and topology configurations:
- Auto-Discovery via Synchronization: Upon calling
await client.cache.sync()or invokingHardwareSyncer.warmup(), theConfigCacheManagerqueries/api/v5/multisensors/status. This endpoint identifies whether the connected device is a master or a member of a virtual multisensor context. - Concurrent Config Ingestion: If a multisensor topology is discovered, the manager concurrently retrieves and builds the structured model representing parent/child zones, lines, analytics states, and scene definitions in a single non-blocking pass.
- Dynamic Child-Client Spawning: Developers can invoke
await context.get_child_clients()on aMultisensorContext. This queries/api/v5/multisensors/{id}/sensorsand dynamically spawns authenticated, matchingDeviceClientinstances for all physical child sensors, inheriting authentication credentials, SSL certificates, and proxy tunnel settings. - Autonomous Watcher Synchronization: Under the
BACKGROUND_WATCHERcaching strategy, the SDK continuously monitors the device checksum endpoints. When configuration or topology changes are detected on the physical sensor, a background synchronization loop triggers automatically to keep the cache updated on disk. - Optional Recursive Child Caching: By default, child-device caching is deactivated to prevent unexpected network overhead. Developers can opt-in to recursively synchronize all physical child sensor configurations concurrently using the
cache_child_devices=Trueflag:client = DeviceClient("192.168.1.50", cache_child_devices=True) await client.cache.sync() # Recursively synchronizes child configurations - Dynamic Child Client Access (
child_devices): Access physical child devices directly through the parent context. Individual child clients are dynamically registered, enabling dot-notation or dictionary-like lookup under.child_devices.by_name:child_client = client.cache.multisensors.by_name.Stitched_Context.child_devices.by_name.Camera_Left - Merged Child Configurations: Merged properties (
connections,zones,lines,agents,logics,modifiers,counters,masks,layers) automatically aggregate and flatten the configurations from all child caches into a single autocomplete-safeCacheCollection:# Access a connection belonging to any child device conn = client.cache.multisensors.by_name.Stitched_Context.child_devices.connections.by_name.my_child_connection - Concurrent Group Broadcasting: Intercept and broadcast standard live operations (e.g.,
.images,.system,.analytics) concurrently to all child sensors in a single call with isolated error handling inBulkResult:# Captures live diagnostic frames across all child cameras concurrently bulk_results = await client.cache.multisensors.by_name.Stitched_Context.child_devices.images.get_live() - Offline-First Child Cache State Access (
child_caches): Inspect child caches without network requests:# Reads offline zone configuration from a physical child sensor child_zone = client.cache.multisensors.by_name.Stitched_Context.child_caches.Camera_Left.zones.by_name.Raw_Zone_1 - Dynamic Space Sanitization: Xovis names often include spaces (e.g.,
"Main Entrance"). The SDK automatically sanitizes these into valid Python identifiers (Main_Entrance) for perfect IDE auto-suggestions, while retaining original names for bracket-style lookups (["Main Entrance"]).
Core Philosophy
A standard sensor is more than just a single IP address—it represents an entire network topology of physical sensors, stitched virtual environments, and configuration buckets. This plane manages these relationships seamlessly.
- Rule - Logical Fleet Buckets vs. Physical Topology: The SDK differentiates between physical topology (managed by
HostStateBucketandChildDevicesAccessorfor stitched multisensors) and logical fleet grouping (managed byDeviceGroupandHubFleetDirectory). Physical topology represents actual hardware connections, whereasDeviceGroupacts as an orchestration construct for bulk command execution across arbitrary independent nodes. - Rule - Context Isolation: A device IP is a "Host". A host runs isolated "Contexts". The
singlesensorcontext applies strictly to physical lenses (and MUST gracefully raiseHardwareNotSupportedErrorif the host is a lensless Spider NUC). Themultisensorscontext applies to 0..N virtual stitched environments. Geometries and DataPushes are strictly partitioned by context. - Rule - Multisensor Cache Rooting: Virtual contexts discovered via
multisensors.sync()MUST be rooted into the persistentHostStateBucketvia the@multisensors.setter. This ensures that DataPush agents and connections persist across CRUD operations and are visible to theREPLAccessor. - Rule - String-Normalized Resolution: All resource managers MUST normalize context and resource IDs to strings when interacting with the stateful cache. Integer keys are strictly forbidden in the
multisensorsmapping to prevent resolution failures. - Rule - Proactive Context Discovery: Resource managers SHOULD trigger a proactive
multisensors.sync()if a targeted virtual context is missing from the local cache, enabling on-the-fly recovery of hardware state. - Rule - Hardware-Aware Context Routing: Agents MUST call
get_system_infoas a mandatory prerequisite to identify the hardware type (Spider vs. PC/PF series). Spider NUCs lack a physical lens and will rejectsinglesensorrequests.SinglesensorContext.datapushmust raiseHardwareNotSupportedErroron lensless hardware. - Rule - Smart Caching & GC Trap: The SDK uses a
ConfigCacheManager(Device) andHubCacheManager(Hub, with client-sidefleet_filtermapping). CRITICAL: IfBACKGROUND_WATCHERis active, theasyncio.create_taskloop MUST be stored in a hard-referencedSet(to prevent Python 3.11+ GC mid-execution) and cleanly cancelled in__aexit__. - Rule - Offline-First Persistence: The
ConfigCacheManagersupports auto-persistence viaauto_persist_path. Disk serialization/deserialization MUST be offloaded usingasyncio.to_threadto ensure zero blocking of the async event loop. - Rule - Edge Topology Synthesis: The
TopologyManagersynthesizes directed graphs (MSGraph) by concurrently cross-referencing multisensor child clusters with physical local network nodes. - Rule - Network Probing (Hybrid First-Responder): Active L3 subnet scanning MUST utilize the pure-Python Hybrid First-Responder Strategy. The SDK aggressively sweeps the IP range concurrently but instantly aborts and hands off discovery to the very first responsive sensor found, using its
/discover/localnetworkendpoint to extract the full L2 payload (MACs, Names, Groups) in one efficient request. - Rule - Multisensor Discovery Synthesis (Top-Down Only): Discovery MUST be synthesized Top-Down. Children are "ignorant" and return fake standalone status. You MUST utilize the 3-Tier Discovery Fallback Strategy (1. Passive OS ARP Cache, 2. Active L2 Proxy Sensor Scan via
/discover/localnetwork, 3. Active L3 Subnet Scan with Hybrid First-Responder) to discover nodes, query their/multisensors/status, and correlatesensors[].mac_addresslists from Master nodes (whereenabled: true) to build the hierarchy. - Rule - Robust Multisensor JSON Parsing: The
/api/v5/multisensors/statusendpoint inconsistently returns either a rawlistor adict(e.g.,{"multisensors_status": [...]}or{"multisensors": [...]}). The SDK MUST use robust dictionary fallback parsing and avoid strictisinstance(data, list)checks to prevent silent cache initialization failures.