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,192 @@
|
|
|
1
|
+
"""
|
|
2
|
+
MAVLink auto-detection.
|
|
3
|
+
|
|
4
|
+
Scans for MAVLink-capable connections: UDP ports, serial flight controllers,
|
|
5
|
+
and TCP endpoints.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
from plexus.adapters.mavlink_detect import scan_mavlink
|
|
9
|
+
|
|
10
|
+
connections = scan_mavlink()
|
|
11
|
+
for conn in connections:
|
|
12
|
+
print(f"{conn.connection_string} ({conn.transport})")
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import glob
|
|
16
|
+
import logging
|
|
17
|
+
import os
|
|
18
|
+
import socket
|
|
19
|
+
from dataclasses import dataclass
|
|
20
|
+
from typing import List
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
# Common MAVLink UDP ports
|
|
25
|
+
MAVLINK_UDP_PORTS = [14550, 14551]
|
|
26
|
+
|
|
27
|
+
# Common MAVLink TCP ports (SITL, companion computers)
|
|
28
|
+
MAVLINK_TCP_PORTS = [5760, 5762]
|
|
29
|
+
|
|
30
|
+
# Known flight controller USB vendor IDs
|
|
31
|
+
FC_USB_VIDS = {
|
|
32
|
+
"2dae": "Holybro (Pixhawk)",
|
|
33
|
+
"1209": "ArduPilot / Generic FC",
|
|
34
|
+
"26ac": "3DR (Pixhawk 1)",
|
|
35
|
+
"0483": "STMicro (many FCs)",
|
|
36
|
+
"1fc9": "NXP (FMUK66)",
|
|
37
|
+
"3162": "CubePilot",
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass
|
|
42
|
+
class DetectedMAVLink:
|
|
43
|
+
"""Information about a detected MAVLink connection."""
|
|
44
|
+
connection_string: str
|
|
45
|
+
transport: str # "udp", "tcp", "serial"
|
|
46
|
+
description: str
|
|
47
|
+
is_available: bool # True if the connection was verified
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _scan_udp() -> List[DetectedMAVLink]:
|
|
51
|
+
"""Scan for MAVLink UDP listeners on standard ports."""
|
|
52
|
+
detected = []
|
|
53
|
+
|
|
54
|
+
for port in MAVLINK_UDP_PORTS:
|
|
55
|
+
sock = None
|
|
56
|
+
try:
|
|
57
|
+
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
58
|
+
sock.settimeout(0.1)
|
|
59
|
+
sock.bind(("0.0.0.0", port))
|
|
60
|
+
# Port is free — no one is sending here yet, but it's available
|
|
61
|
+
detected.append(DetectedMAVLink(
|
|
62
|
+
connection_string=f"udpin:0.0.0.0:{port}",
|
|
63
|
+
transport="udp",
|
|
64
|
+
description=f"UDP port {port} (available to listen)",
|
|
65
|
+
is_available=True,
|
|
66
|
+
))
|
|
67
|
+
except OSError:
|
|
68
|
+
# Port in use — something may already be sending MAVLink here
|
|
69
|
+
detected.append(DetectedMAVLink(
|
|
70
|
+
connection_string=f"udpin:0.0.0.0:{port}",
|
|
71
|
+
transport="udp",
|
|
72
|
+
description=f"UDP port {port} (in use — possible MAVLink source)",
|
|
73
|
+
is_available=True,
|
|
74
|
+
))
|
|
75
|
+
finally:
|
|
76
|
+
if sock:
|
|
77
|
+
sock.close()
|
|
78
|
+
|
|
79
|
+
return detected
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _scan_tcp() -> List[DetectedMAVLink]:
|
|
83
|
+
"""Scan for MAVLink TCP endpoints on localhost."""
|
|
84
|
+
detected = []
|
|
85
|
+
|
|
86
|
+
for port in MAVLINK_TCP_PORTS:
|
|
87
|
+
sock = None
|
|
88
|
+
try:
|
|
89
|
+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
90
|
+
sock.settimeout(0.5)
|
|
91
|
+
result = sock.connect_ex(("127.0.0.1", port))
|
|
92
|
+
if result == 0:
|
|
93
|
+
detected.append(DetectedMAVLink(
|
|
94
|
+
connection_string=f"tcp:127.0.0.1:{port}",
|
|
95
|
+
transport="tcp",
|
|
96
|
+
description=f"TCP port {port} (SITL or companion)",
|
|
97
|
+
is_available=True,
|
|
98
|
+
))
|
|
99
|
+
except (OSError, socket.error):
|
|
100
|
+
pass
|
|
101
|
+
finally:
|
|
102
|
+
if sock:
|
|
103
|
+
sock.close()
|
|
104
|
+
|
|
105
|
+
return detected
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _scan_serial() -> List[DetectedMAVLink]:
|
|
109
|
+
"""Scan serial ports for known flight controller USB VIDs."""
|
|
110
|
+
detected = []
|
|
111
|
+
|
|
112
|
+
# Check /sys/bus/usb for known FC vendor IDs (Linux)
|
|
113
|
+
usb_path = "/sys/bus/usb/devices"
|
|
114
|
+
fc_serial_paths = set()
|
|
115
|
+
|
|
116
|
+
if os.path.isdir(usb_path):
|
|
117
|
+
try:
|
|
118
|
+
for entry in os.listdir(usb_path):
|
|
119
|
+
vid_path = os.path.join(usb_path, entry, "idVendor")
|
|
120
|
+
try:
|
|
121
|
+
with open(vid_path, "r") as f:
|
|
122
|
+
vid = f.read().strip().lower()
|
|
123
|
+
except (OSError, IOError):
|
|
124
|
+
continue
|
|
125
|
+
|
|
126
|
+
if vid in FC_USB_VIDS:
|
|
127
|
+
# Look for tty sub-device
|
|
128
|
+
dev_dir = os.path.join(usb_path, entry)
|
|
129
|
+
for tty in glob.glob(os.path.join(dev_dir, "**", "tty", "tty*"), recursive=True):
|
|
130
|
+
tty_name = os.path.basename(tty)
|
|
131
|
+
dev_path = f"/dev/{tty_name}"
|
|
132
|
+
if os.path.exists(dev_path):
|
|
133
|
+
fc_serial_paths.add((dev_path, FC_USB_VIDS[vid]))
|
|
134
|
+
except OSError:
|
|
135
|
+
pass
|
|
136
|
+
|
|
137
|
+
for dev_path, fc_name in sorted(fc_serial_paths):
|
|
138
|
+
detected.append(DetectedMAVLink(
|
|
139
|
+
connection_string=dev_path,
|
|
140
|
+
transport="serial",
|
|
141
|
+
description=f"Flight controller: {fc_name}",
|
|
142
|
+
is_available=True,
|
|
143
|
+
))
|
|
144
|
+
|
|
145
|
+
# Fallback: check common serial paths for FC-like devices
|
|
146
|
+
if not detected:
|
|
147
|
+
fc_patterns = ["/dev/ttyACM*", "/dev/ttyUSB*"]
|
|
148
|
+
for pattern in fc_patterns:
|
|
149
|
+
for device_path in sorted(glob.glob(pattern)):
|
|
150
|
+
detected.append(DetectedMAVLink(
|
|
151
|
+
connection_string=device_path,
|
|
152
|
+
transport="serial",
|
|
153
|
+
description="Serial port (possible flight controller)",
|
|
154
|
+
is_available=False, # Not verified
|
|
155
|
+
))
|
|
156
|
+
|
|
157
|
+
return detected
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def scan_mavlink() -> List[DetectedMAVLink]:
|
|
161
|
+
"""
|
|
162
|
+
Scan for MAVLink connections on the system.
|
|
163
|
+
|
|
164
|
+
Checks:
|
|
165
|
+
1. UDP ports 14550, 14551
|
|
166
|
+
2. TCP ports 5760, 5762 on localhost
|
|
167
|
+
3. Serial ports with known flight controller USB VIDs
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
List of detected MAVLink connections
|
|
171
|
+
"""
|
|
172
|
+
detected = []
|
|
173
|
+
|
|
174
|
+
# UDP ports
|
|
175
|
+
try:
|
|
176
|
+
detected.extend(_scan_udp())
|
|
177
|
+
except Exception as e:
|
|
178
|
+
logger.debug(f"Error scanning MAVLink UDP ports: {e}")
|
|
179
|
+
|
|
180
|
+
# TCP ports
|
|
181
|
+
try:
|
|
182
|
+
detected.extend(_scan_tcp())
|
|
183
|
+
except Exception as e:
|
|
184
|
+
logger.debug(f"Error scanning MAVLink TCP ports: {e}")
|
|
185
|
+
|
|
186
|
+
# Serial ports
|
|
187
|
+
try:
|
|
188
|
+
detected.extend(_scan_serial())
|
|
189
|
+
except Exception as e:
|
|
190
|
+
logger.debug(f"Error scanning MAVLink serial ports: {e}")
|
|
191
|
+
|
|
192
|
+
return detected
|