plexus-python 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plexus/__init__.py +31 -0
- plexus/__main__.py +4 -0
- plexus/adapters/__init__.py +122 -0
- plexus/adapters/base.py +409 -0
- plexus/adapters/ble.py +257 -0
- plexus/adapters/can.py +439 -0
- plexus/adapters/can_detect.py +174 -0
- plexus/adapters/mavlink.py +642 -0
- plexus/adapters/mavlink_detect.py +192 -0
- plexus/adapters/modbus.py +622 -0
- plexus/adapters/mqtt.py +350 -0
- plexus/adapters/opcua.py +607 -0
- plexus/adapters/registry.py +206 -0
- plexus/adapters/serial_adapter.py +547 -0
- plexus/buffer.py +257 -0
- plexus/cameras/__init__.py +57 -0
- plexus/cameras/auto.py +239 -0
- plexus/cameras/base.py +189 -0
- plexus/cameras/picamera.py +171 -0
- plexus/cameras/usb.py +143 -0
- plexus/cli.py +783 -0
- plexus/client.py +465 -0
- plexus/config.py +169 -0
- plexus/connector.py +666 -0
- plexus/deps.py +246 -0
- plexus/detect.py +1238 -0
- plexus/importers/__init__.py +25 -0
- plexus/importers/rosbag.py +778 -0
- plexus/sensors/__init__.py +118 -0
- plexus/sensors/ads1115.py +164 -0
- plexus/sensors/adxl345.py +179 -0
- plexus/sensors/auto.py +290 -0
- plexus/sensors/base.py +412 -0
- plexus/sensors/bh1750.py +102 -0
- plexus/sensors/bme280.py +241 -0
- plexus/sensors/gps.py +317 -0
- plexus/sensors/ina219.py +149 -0
- plexus/sensors/magnetometer.py +239 -0
- plexus/sensors/mpu6050.py +162 -0
- plexus/sensors/sht3x.py +139 -0
- plexus/sensors/spi_scan.py +164 -0
- plexus/sensors/system.py +261 -0
- plexus/sensors/vl53l0x.py +109 -0
- plexus/streaming.py +743 -0
- plexus/tui.py +642 -0
- plexus_python-0.1.0.dist-info/METADATA +470 -0
- plexus_python-0.1.0.dist-info/RECORD +50 -0
- plexus_python-0.1.0.dist-info/WHEEL +4 -0
- plexus_python-0.1.0.dist-info/entry_points.txt +2 -0
- plexus_python-0.1.0.dist-info/licenses/LICENSE +190 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Adapter Registry - Plugin system for protocol adapters
|
|
3
|
+
|
|
4
|
+
The registry allows dynamic registration of protocol adapters,
|
|
5
|
+
enabling community contributions without modifying core code.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
from plexus.adapters import AdapterRegistry, ProtocolAdapter
|
|
9
|
+
|
|
10
|
+
# Register a custom adapter
|
|
11
|
+
AdapterRegistry.register("my-protocol", MyProtocolAdapter)
|
|
12
|
+
|
|
13
|
+
# List available adapters
|
|
14
|
+
print(AdapterRegistry.list())
|
|
15
|
+
|
|
16
|
+
# Create an adapter by name
|
|
17
|
+
adapter = AdapterRegistry.create("mqtt", broker="localhost")
|
|
18
|
+
|
|
19
|
+
# Check if adapter is available
|
|
20
|
+
if AdapterRegistry.has("modbus"):
|
|
21
|
+
adapter = AdapterRegistry.create("modbus", port="/dev/ttyUSB0")
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from typing import Any, Dict, List, Optional, Type
|
|
25
|
+
from plexus.adapters.base import ProtocolAdapter
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class AdapterRegistryMeta(type):
|
|
29
|
+
"""Metaclass for singleton registry"""
|
|
30
|
+
_adapters: Dict[str, Type[ProtocolAdapter]] = {}
|
|
31
|
+
_metadata: Dict[str, Dict[str, Any]] = {}
|
|
32
|
+
|
|
33
|
+
def register(
|
|
34
|
+
cls,
|
|
35
|
+
name: str,
|
|
36
|
+
adapter_class: Type[ProtocolAdapter],
|
|
37
|
+
*,
|
|
38
|
+
description: str = "",
|
|
39
|
+
author: str = "",
|
|
40
|
+
version: str = "1.0.0",
|
|
41
|
+
requires: Optional[List[str]] = None,
|
|
42
|
+
) -> None:
|
|
43
|
+
"""
|
|
44
|
+
Register a protocol adapter.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
name: Unique adapter name (e.g., "mqtt", "modbus", "can")
|
|
48
|
+
adapter_class: The adapter class (must inherit from ProtocolAdapter)
|
|
49
|
+
description: Human-readable description
|
|
50
|
+
author: Author name or organization
|
|
51
|
+
version: Adapter version
|
|
52
|
+
requires: List of required pip packages
|
|
53
|
+
|
|
54
|
+
Example:
|
|
55
|
+
AdapterRegistry.register(
|
|
56
|
+
"modbus",
|
|
57
|
+
ModbusAdapter,
|
|
58
|
+
description="Modbus RTU/TCP adapter",
|
|
59
|
+
requires=["pymodbus"],
|
|
60
|
+
)
|
|
61
|
+
"""
|
|
62
|
+
if not issubclass(adapter_class, ProtocolAdapter):
|
|
63
|
+
raise TypeError(
|
|
64
|
+
f"Adapter class must inherit from ProtocolAdapter, "
|
|
65
|
+
f"got {adapter_class.__name__}"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
cls._adapters[name] = adapter_class
|
|
69
|
+
cls._metadata[name] = {
|
|
70
|
+
"name": name,
|
|
71
|
+
"class": adapter_class.__name__,
|
|
72
|
+
"description": description,
|
|
73
|
+
"author": author,
|
|
74
|
+
"version": version,
|
|
75
|
+
"requires": requires or [],
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
def unregister(cls, name: str) -> bool:
|
|
79
|
+
"""
|
|
80
|
+
Unregister a protocol adapter.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
name: Adapter name to remove
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
True if adapter was removed, False if not found
|
|
87
|
+
"""
|
|
88
|
+
if name in cls._adapters:
|
|
89
|
+
del cls._adapters[name]
|
|
90
|
+
del cls._metadata[name]
|
|
91
|
+
return True
|
|
92
|
+
return False
|
|
93
|
+
|
|
94
|
+
def has(cls, name: str) -> bool:
|
|
95
|
+
"""Check if an adapter is registered."""
|
|
96
|
+
return name in cls._adapters
|
|
97
|
+
|
|
98
|
+
def get(cls, name: str) -> Optional[Type[ProtocolAdapter]]:
|
|
99
|
+
"""Get an adapter class by name."""
|
|
100
|
+
return cls._adapters.get(name)
|
|
101
|
+
|
|
102
|
+
def create(cls, name: str, **kwargs) -> ProtocolAdapter:
|
|
103
|
+
"""
|
|
104
|
+
Create an adapter instance by name.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
name: Adapter name
|
|
108
|
+
**kwargs: Arguments passed to adapter constructor
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
Configured adapter instance
|
|
112
|
+
|
|
113
|
+
Raises:
|
|
114
|
+
KeyError: If adapter not found
|
|
115
|
+
ImportError: If required packages not installed
|
|
116
|
+
|
|
117
|
+
Example:
|
|
118
|
+
adapter = AdapterRegistry.create(
|
|
119
|
+
"mqtt",
|
|
120
|
+
broker="localhost",
|
|
121
|
+
topic="sensors/#"
|
|
122
|
+
)
|
|
123
|
+
"""
|
|
124
|
+
if name not in cls._adapters:
|
|
125
|
+
available = ", ".join(cls._adapters.keys()) or "none"
|
|
126
|
+
raise KeyError(
|
|
127
|
+
f"Unknown adapter: '{name}'. Available: {available}"
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# Check dependencies
|
|
131
|
+
metadata = cls._metadata[name]
|
|
132
|
+
missing = []
|
|
133
|
+
for pkg in metadata.get("requires", []):
|
|
134
|
+
try:
|
|
135
|
+
__import__(pkg.replace("-", "_"))
|
|
136
|
+
except ImportError:
|
|
137
|
+
missing.append(pkg)
|
|
138
|
+
|
|
139
|
+
if missing:
|
|
140
|
+
raise ImportError(
|
|
141
|
+
f"Adapter '{name}' requires: pip install {' '.join(missing)}"
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
adapter_class = cls._adapters[name]
|
|
145
|
+
return adapter_class(**kwargs)
|
|
146
|
+
|
|
147
|
+
def list(cls) -> List[str]:
|
|
148
|
+
"""List all registered adapter names."""
|
|
149
|
+
return list(cls._adapters.keys())
|
|
150
|
+
|
|
151
|
+
def info(cls, name: str) -> Optional[Dict[str, Any]]:
|
|
152
|
+
"""Get metadata for an adapter."""
|
|
153
|
+
return cls._metadata.get(name)
|
|
154
|
+
|
|
155
|
+
def all_info(cls) -> List[Dict[str, Any]]:
|
|
156
|
+
"""Get metadata for all registered adapters."""
|
|
157
|
+
return list(cls._metadata.values())
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class AdapterRegistry(metaclass=AdapterRegistryMeta):
|
|
161
|
+
"""
|
|
162
|
+
Registry for protocol adapters.
|
|
163
|
+
|
|
164
|
+
This is a class-level registry (singleton pattern via metaclass).
|
|
165
|
+
All methods are class methods accessed directly on AdapterRegistry.
|
|
166
|
+
|
|
167
|
+
Example:
|
|
168
|
+
# Register
|
|
169
|
+
AdapterRegistry.register("my-adapter", MyAdapter)
|
|
170
|
+
|
|
171
|
+
# Create
|
|
172
|
+
adapter = AdapterRegistry.create("my-adapter", param=value)
|
|
173
|
+
|
|
174
|
+
# List
|
|
175
|
+
print(AdapterRegistry.list()) # ["mqtt", "my-adapter"]
|
|
176
|
+
"""
|
|
177
|
+
pass
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def register_adapter(
|
|
181
|
+
name: str,
|
|
182
|
+
*,
|
|
183
|
+
description: str = "",
|
|
184
|
+
author: str = "",
|
|
185
|
+
version: str = "1.0.0",
|
|
186
|
+
requires: Optional[List[str]] = None,
|
|
187
|
+
):
|
|
188
|
+
"""
|
|
189
|
+
Decorator to register an adapter class.
|
|
190
|
+
|
|
191
|
+
Usage:
|
|
192
|
+
@register_adapter("my-protocol", description="My custom protocol")
|
|
193
|
+
class MyProtocolAdapter(ProtocolAdapter):
|
|
194
|
+
...
|
|
195
|
+
"""
|
|
196
|
+
def decorator(cls: Type[ProtocolAdapter]) -> Type[ProtocolAdapter]:
|
|
197
|
+
AdapterRegistry.register(
|
|
198
|
+
name,
|
|
199
|
+
cls,
|
|
200
|
+
description=description,
|
|
201
|
+
author=author,
|
|
202
|
+
version=version,
|
|
203
|
+
requires=requires,
|
|
204
|
+
)
|
|
205
|
+
return cls
|
|
206
|
+
return decorator
|