swarmit 0.4.5__tar.gz → 0.5.0rc1__tar.gz
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.
- {swarmit-0.4.5 → swarmit-0.5.0rc1}/PKG-INFO +7 -7
- {swarmit-0.4.5 → swarmit-0.5.0rc1}/pyproject.toml +6 -6
- swarmit-0.5.0rc1/testbed/swarmit/__init__.py +1 -0
- {swarmit-0.4.5 → swarmit-0.5.0rc1}/testbed/swarmit/controller.py +63 -18
- {swarmit-0.4.5 → swarmit-0.5.0rc1}/testbed/swarmit/protocol.py +21 -0
- swarmit-0.4.5/testbed/swarmit/__init__.py +0 -1
- {swarmit-0.4.5 → swarmit-0.5.0rc1}/.gitignore +0 -0
- {swarmit-0.4.5 → swarmit-0.5.0rc1}/AUTHORS +0 -0
- {swarmit-0.4.5 → swarmit-0.5.0rc1}/LICENSE +0 -0
- {swarmit-0.4.5 → swarmit-0.5.0rc1}/README.md +0 -0
- {swarmit-0.4.5 → swarmit-0.5.0rc1}/dotbot-firmware/doc/sphinx/conf.py +0 -0
- {swarmit-0.4.5 → swarmit-0.5.0rc1}/testbed/cli/main.py +0 -0
- {swarmit-0.4.5 → swarmit-0.5.0rc1}/testbed/swarmit/adapter.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: swarmit
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.5.0rc1
|
4
4
|
Summary: Run Your Own Robot Swarm Testbed.
|
5
5
|
Project-URL: Homepage, https://github.com/DotBots/swarmit
|
6
6
|
Project-URL: Bug Tracker, https://github.com/DotBots/swarmit/issues
|
@@ -14,13 +14,13 @@ Classifier: Operating System :: Microsoft :: Windows
|
|
14
14
|
Classifier: Operating System :: POSIX :: Linux
|
15
15
|
Classifier: Programming Language :: Python :: 3
|
16
16
|
Requires-Python: >=3.7
|
17
|
-
Requires-Dist: click
|
17
|
+
Requires-Dist: click>=8.1.7
|
18
18
|
Requires-Dist: cryptography==43.0.1
|
19
|
-
Requires-Dist: marilib-pkg
|
20
|
-
Requires-Dist: pydotbot>=0.
|
21
|
-
Requires-Dist: rich
|
22
|
-
Requires-Dist: structlog
|
23
|
-
Requires-Dist: tqdm
|
19
|
+
Requires-Dist: marilib-pkg==0.7.0rc1
|
20
|
+
Requires-Dist: pydotbot>=0.25.0
|
21
|
+
Requires-Dist: rich>=14.0.0
|
22
|
+
Requires-Dist: structlog>=24.4.0
|
23
|
+
Requires-Dist: tqdm>=4.66.5
|
24
24
|
Description-Content-Type: text/markdown
|
25
25
|
|
26
26
|
# SwarmIT
|
@@ -26,13 +26,13 @@ authors = [
|
|
26
26
|
{ name="Alexandre Abadie", email="alexandre.abadie@inria.fr" },
|
27
27
|
]
|
28
28
|
dependencies = [
|
29
|
-
"click
|
29
|
+
"click >= 8.1.7",
|
30
30
|
"cryptography == 43.0.1",
|
31
|
-
"pydotbot >= 0.
|
32
|
-
"rich
|
33
|
-
"structlog
|
34
|
-
"tqdm
|
35
|
-
"marilib-pkg
|
31
|
+
"pydotbot >= 0.25.0",
|
32
|
+
"rich >= 14.0.0",
|
33
|
+
"structlog >= 24.4.0",
|
34
|
+
"tqdm >= 4.66.5",
|
35
|
+
"marilib-pkg == 0.7.0rc1",
|
36
36
|
]
|
37
37
|
description = "Run Your Own Robot Swarm Testbed."
|
38
38
|
readme = "README.md"
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "0.5.0rc1"
|
@@ -22,6 +22,7 @@ from testbed.swarmit.adapter import (
|
|
22
22
|
MarilibEdgeAdapter,
|
23
23
|
)
|
24
24
|
from testbed.swarmit.protocol import (
|
25
|
+
DeviceType,
|
25
26
|
PayloadMessage,
|
26
27
|
PayloadOTAChunkRequest,
|
27
28
|
PayloadOTAStartRequest,
|
@@ -39,11 +40,22 @@ COMMAND_MAX_ATTEMPTS = 5
|
|
39
40
|
COMMAND_ATTEMPT_DELAY = 1
|
40
41
|
STATUS_TIMEOUT = 5
|
41
42
|
OTA_MAX_RETRIES_DEFAULT = 10
|
42
|
-
OTA_ACK_TIMEOUT_DEFAULT =
|
43
|
+
OTA_ACK_TIMEOUT_DEFAULT = 2
|
43
44
|
SERIAL_PORT_DEFAULT = get_default_port()
|
44
45
|
BROADCAST_ADDRESS = 0xFFFFFFFFFFFFFFFF
|
45
46
|
|
46
47
|
|
48
|
+
@dataclass
|
49
|
+
class NodeStatus:
|
50
|
+
"""Class that holds node status."""
|
51
|
+
|
52
|
+
device: DeviceType = DeviceType.Unknown
|
53
|
+
status: StatusType = StatusType.Bootloader
|
54
|
+
battery: int = 0
|
55
|
+
pos_x: int = 0
|
56
|
+
pos_y: int = 0
|
57
|
+
|
58
|
+
|
47
59
|
@dataclass
|
48
60
|
class DataChunk:
|
49
61
|
"""Class that holds data chunks."""
|
@@ -101,11 +113,20 @@ def addr_to_hex(addr: int) -> str:
|
|
101
113
|
return hexlify(addr.to_bytes(8, "big")).decode().upper()
|
102
114
|
|
103
115
|
|
116
|
+
def battery_level_color(level: int):
|
117
|
+
if level > 85:
|
118
|
+
return "green"
|
119
|
+
elif level > 65:
|
120
|
+
return "dark_orange"
|
121
|
+
else:
|
122
|
+
return "red"
|
123
|
+
|
124
|
+
|
104
125
|
def generate_status(status_data, devices=[], status_message="found"):
|
105
126
|
data = {
|
106
|
-
|
107
|
-
for
|
108
|
-
if (devices and
|
127
|
+
addr: device_data
|
128
|
+
for addr, device_data in status_data.items()
|
129
|
+
if (devices and addr in devices) or (not devices)
|
109
130
|
}
|
110
131
|
if not data:
|
111
132
|
return Group(Text(f"\nNo device {status_message}\n"))
|
@@ -116,16 +137,35 @@ def generate_status(status_data, devices=[], status_message="found"):
|
|
116
137
|
|
117
138
|
table = Table()
|
118
139
|
table.add_column("Device Addr", style="magenta", no_wrap=True)
|
140
|
+
table.add_column(
|
141
|
+
"Type",
|
142
|
+
style="cyan",
|
143
|
+
justify="center",
|
144
|
+
)
|
145
|
+
table.add_column(
|
146
|
+
"Battery",
|
147
|
+
style="cyan",
|
148
|
+
justify="right",
|
149
|
+
)
|
150
|
+
table.add_column(
|
151
|
+
"Position",
|
152
|
+
style="cyan",
|
153
|
+
justify="right",
|
154
|
+
)
|
119
155
|
table.add_column(
|
120
156
|
"Status",
|
121
157
|
style="green",
|
122
158
|
justify="center",
|
123
159
|
width=max([len(m) for m in StatusType.__members__]),
|
124
160
|
)
|
125
|
-
for device_addr,
|
161
|
+
for device_addr, device_data in sorted(data.items()):
|
162
|
+
|
126
163
|
table.add_row(
|
127
164
|
f"{device_addr}",
|
128
|
-
f"{
|
165
|
+
f"{device_data.device.name}",
|
166
|
+
f"[{battery_level_color(device_data.battery)}]{device_data.battery:>3}%",
|
167
|
+
f"({(device_data.pos_x / 1e6):.2f}, {(device_data.pos_y / 1e6):.2f})",
|
168
|
+
f"{'[bold cyan]' if device_data.status == StatusType.Running else '[bold green]'}{device_data.status.name}",
|
129
169
|
)
|
130
170
|
return Group(header, table)
|
131
171
|
|
@@ -188,7 +228,7 @@ class Controller:
|
|
188
228
|
self.logger = LOGGER.bind(context=__name__)
|
189
229
|
self.settings = settings
|
190
230
|
self._interface: GatewayAdapterBase = None
|
191
|
-
self.status_data: dict[str,
|
231
|
+
self.status_data: dict[str, NodeStatus] = {}
|
192
232
|
self.started_data: list[str] = []
|
193
233
|
self.stopped_data: list[str] = []
|
194
234
|
self.chunks: list[DataChunk] = []
|
@@ -225,11 +265,11 @@ class Controller:
|
|
225
265
|
"""Return the running devices."""
|
226
266
|
return [
|
227
267
|
addr
|
228
|
-
for addr,
|
268
|
+
for addr, node in self.known_devices.items()
|
229
269
|
if (
|
230
270
|
(
|
231
|
-
status == StatusType.Running
|
232
|
-
or status == StatusType.Programming
|
271
|
+
node.status == StatusType.Running
|
272
|
+
or node.status == StatusType.Programming
|
233
273
|
)
|
234
274
|
and (
|
235
275
|
not self.settings.devices or addr in self.settings.devices
|
@@ -242,9 +282,9 @@ class Controller:
|
|
242
282
|
"""Return the resetting devices."""
|
243
283
|
return [
|
244
284
|
device_addr
|
245
|
-
for device_addr,
|
285
|
+
for device_addr, node in self.known_devices.items()
|
246
286
|
if (
|
247
|
-
status == StatusType.Resetting
|
287
|
+
node.status == StatusType.Resetting
|
248
288
|
and (
|
249
289
|
not self.settings.devices
|
250
290
|
or device_addr in self.settings.devices
|
@@ -257,9 +297,9 @@ class Controller:
|
|
257
297
|
"""Return the ready devices."""
|
258
298
|
return [
|
259
299
|
device_addr
|
260
|
-
for device_addr,
|
300
|
+
for device_addr, node in self.known_devices.items()
|
261
301
|
if (
|
262
|
-
status == StatusType.Bootloader
|
302
|
+
node.status == StatusType.Bootloader
|
263
303
|
and (
|
264
304
|
not self.settings.devices
|
265
305
|
or device_addr in self.settings.devices
|
@@ -292,9 +332,14 @@ class Controller:
|
|
292
332
|
packet.payload_type
|
293
333
|
== SwarmitPayloadType.SWARMIT_NOTIFICATION_STATUS
|
294
334
|
):
|
295
|
-
|
296
|
-
|
335
|
+
status = NodeStatus(
|
336
|
+
device=DeviceType(packet.payload.device),
|
337
|
+
status=StatusType(packet.payload.status),
|
338
|
+
battery=packet.payload.battery,
|
339
|
+
pos_x=packet.payload.pos_x,
|
340
|
+
pos_y=packet.payload.pos_y,
|
297
341
|
)
|
342
|
+
self.status_data.update({device_addr: status})
|
298
343
|
elif (
|
299
344
|
packet.payload_type
|
300
345
|
== SwarmitPayloadType.SWARMIT_NOTIFICATION_OTA_START_ACK
|
@@ -384,7 +429,7 @@ class Controller:
|
|
384
429
|
ready_devices = self.ready_devices
|
385
430
|
attempts = 0
|
386
431
|
while attempts < COMMAND_MAX_ATTEMPTS and not all(
|
387
|
-
self.status_data[addr] == StatusType.Running
|
432
|
+
self.status_data[addr].status == StatusType.Running
|
388
433
|
for addr in ready_devices
|
389
434
|
):
|
390
435
|
if not self.settings.devices:
|
@@ -406,7 +451,7 @@ class Controller:
|
|
406
451
|
|
407
452
|
attempts = 0
|
408
453
|
while attempts < COMMAND_MAX_ATTEMPTS and not all(
|
409
|
-
self.status_data[addr]
|
454
|
+
self.status_data[addr].status
|
410
455
|
in [StatusType.Stopping, StatusType.Bootloader]
|
411
456
|
for addr in stoppable_devices
|
412
457
|
):
|
@@ -17,6 +17,15 @@ class StatusType(Enum):
|
|
17
17
|
Programming = 4
|
18
18
|
|
19
19
|
|
20
|
+
class DeviceType(Enum):
|
21
|
+
"""Types of devices."""
|
22
|
+
|
23
|
+
Unknown = 0
|
24
|
+
DotBotV3 = 1
|
25
|
+
DotBotV2 = 2
|
26
|
+
nRF5340DK = 3
|
27
|
+
|
28
|
+
|
20
29
|
class SwarmitPayloadType(IntEnum):
|
21
30
|
"""Types of DotBot payload types."""
|
22
31
|
|
@@ -126,11 +135,23 @@ class PayloadStatusNotification(Payload):
|
|
126
135
|
|
127
136
|
metadata: list[PayloadFieldMetadata] = dataclasses.field(
|
128
137
|
default_factory=lambda: [
|
138
|
+
PayloadFieldMetadata(name="device", disp="dev."),
|
129
139
|
PayloadFieldMetadata(name="status", disp="st."),
|
140
|
+
PayloadFieldMetadata(name="battery", disp="bat."),
|
141
|
+
PayloadFieldMetadata(
|
142
|
+
name="pos_x", disp="pos x", length=4, signed=True
|
143
|
+
),
|
144
|
+
PayloadFieldMetadata(
|
145
|
+
name="pos_y", disp="pos y", length=4, signed=True
|
146
|
+
),
|
130
147
|
]
|
131
148
|
)
|
132
149
|
|
150
|
+
device: DeviceType = DeviceType.Unknown
|
133
151
|
status: StatusType = StatusType.Bootloader
|
152
|
+
battery: int = 0
|
153
|
+
pos_x: int = 0
|
154
|
+
pos_y: int = 0
|
134
155
|
|
135
156
|
|
136
157
|
@dataclass
|
@@ -1 +0,0 @@
|
|
1
|
-
__version__ = "0.4.5"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|