swarmit 0.3.0__py3-none-any.whl → 0.4.4__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.
- swarmit-0.4.4.dist-info/METADATA +127 -0
- swarmit-0.4.4.dist-info/RECORD +12 -0
- testbed/cli/main.py +140 -170
- testbed/swarmit/__init__.py +1 -1
- testbed/swarmit/adapter.py +112 -64
- testbed/swarmit/controller.py +350 -306
- testbed/swarmit/protocol.py +38 -99
- swarmit-0.3.0.dist-info/METADATA +0 -101
- swarmit-0.3.0.dist-info/RECORD +0 -12
- {swarmit-0.3.0.dist-info → swarmit-0.4.4.dist-info}/WHEEL +0 -0
- {swarmit-0.3.0.dist-info → swarmit-0.4.4.dist-info}/entry_points.txt +0 -0
- {swarmit-0.3.0.dist-info → swarmit-0.4.4.dist-info}/licenses/AUTHORS +0 -0
- {swarmit-0.3.0.dist-info → swarmit-0.4.4.dist-info}/licenses/LICENSE +0 -0
testbed/swarmit/protocol.py
CHANGED
@@ -4,7 +4,7 @@ import dataclasses
|
|
4
4
|
from dataclasses import dataclass
|
5
5
|
from enum import Enum, IntEnum
|
6
6
|
|
7
|
-
from dotbot.protocol import
|
7
|
+
from dotbot.protocol import Payload, PayloadFieldMetadata, register_parser
|
8
8
|
|
9
9
|
|
10
10
|
class StatusType(Enum):
|
@@ -14,6 +14,7 @@ class StatusType(Enum):
|
|
14
14
|
Running = 1
|
15
15
|
Stopping = 2
|
16
16
|
Resetting = 3
|
17
|
+
Programming = 4
|
17
18
|
|
18
19
|
|
19
20
|
class SwarmitPayloadType(IntEnum):
|
@@ -29,8 +30,6 @@ class SwarmitPayloadType(IntEnum):
|
|
29
30
|
|
30
31
|
# Notifications
|
31
32
|
SWARMIT_NOTIFICATION_STATUS = 0x90
|
32
|
-
SWARMIT_NOTIFICATION_STARTED = 0x91
|
33
|
-
SWARMIT_NOTIFICATION_STOPPED = 0x92
|
34
33
|
SWARMIT_NOTIFICATION_OTA_START_ACK = 0x93
|
35
34
|
SWARMIT_NOTIFICATION_OTA_CHUNK_ACK = 0x94
|
36
35
|
SWARMIT_NOTIFICATION_EVENT_GPIO = 0x95
|
@@ -44,17 +43,13 @@ class SwarmitPayloadType(IntEnum):
|
|
44
43
|
|
45
44
|
|
46
45
|
@dataclass
|
47
|
-
class PayloadRequest(
|
46
|
+
class PayloadRequest(Payload):
|
48
47
|
"""Dataclass that holds an application request packet (start/stop/status)."""
|
49
48
|
|
50
|
-
metadata: list[
|
51
|
-
default_factory=lambda: [
|
52
|
-
PacketFieldMetadata(name="device_id", disp="id", length=8),
|
53
|
-
]
|
49
|
+
metadata: list[PayloadFieldMetadata] = dataclasses.field(
|
50
|
+
default_factory=lambda: []
|
54
51
|
)
|
55
52
|
|
56
|
-
device_id: int = 0x0000000000000000
|
57
|
-
|
58
53
|
|
59
54
|
@dataclass
|
60
55
|
class PayloadStatusRequest(PayloadRequest):
|
@@ -72,61 +67,53 @@ class PayloadStopRequest(PayloadRequest):
|
|
72
67
|
|
73
68
|
|
74
69
|
@dataclass
|
75
|
-
class PayloadResetRequest(
|
70
|
+
class PayloadResetRequest(Payload):
|
76
71
|
"""Dataclass that holds an application reset request packet."""
|
77
72
|
|
78
|
-
metadata: list[
|
73
|
+
metadata: list[PayloadFieldMetadata] = dataclasses.field(
|
79
74
|
default_factory=lambda: [
|
80
|
-
|
81
|
-
|
82
|
-
PacketFieldMetadata(name="pos_y", length=4),
|
75
|
+
PayloadFieldMetadata(name="pos_x", length=4),
|
76
|
+
PayloadFieldMetadata(name="pos_y", length=4),
|
83
77
|
]
|
84
78
|
)
|
85
79
|
|
86
|
-
device_id: int = 0
|
87
80
|
pos_x: int = 0
|
88
81
|
pos_y: int = 0
|
89
82
|
|
90
83
|
|
91
84
|
@dataclass
|
92
|
-
class PayloadOTAStartRequest(
|
85
|
+
class PayloadOTAStartRequest(Payload):
|
93
86
|
"""Dataclass that holds an OTA start packet."""
|
94
87
|
|
95
|
-
metadata: list[
|
88
|
+
metadata: list[PayloadFieldMetadata] = dataclasses.field(
|
96
89
|
default_factory=lambda: [
|
97
|
-
|
98
|
-
|
99
|
-
PacketFieldMetadata(
|
90
|
+
PayloadFieldMetadata(name="fw_length", disp="len.", length=4),
|
91
|
+
PayloadFieldMetadata(
|
100
92
|
name="fw_chunk_counts", disp="chunks", length=4
|
101
93
|
),
|
102
|
-
PacketFieldMetadata(
|
103
|
-
name="fw_hash", disp="hash.", type_=bytes, length=32
|
104
|
-
),
|
105
94
|
]
|
106
95
|
)
|
107
96
|
|
108
|
-
device_id: int = 0x0000000000000000
|
109
97
|
fw_length: int = 0
|
110
98
|
fw_chunk_count: int = 0
|
111
|
-
fw_hash: bytes = dataclasses.field(default_factory=lambda: bytearray)
|
112
99
|
|
113
100
|
|
114
101
|
@dataclass
|
115
|
-
class PayloadOTAChunkRequest(
|
102
|
+
class PayloadOTAChunkRequest(Payload):
|
116
103
|
"""Dataclass that holds an OTA chunk packet."""
|
117
104
|
|
118
|
-
metadata: list[
|
105
|
+
metadata: list[PayloadFieldMetadata] = dataclasses.field(
|
119
106
|
default_factory=lambda: [
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
107
|
+
PayloadFieldMetadata(name="index", disp="idx", length=4),
|
108
|
+
PayloadFieldMetadata(name="count", disp="size"),
|
109
|
+
PayloadFieldMetadata(name="sha", type_=bytes, length=8),
|
110
|
+
PayloadFieldMetadata(name="chunk", type_=bytes, length=0),
|
124
111
|
]
|
125
112
|
)
|
126
113
|
|
127
|
-
device_id: int = 0x0000000000000000
|
128
114
|
index: int = 0
|
129
115
|
count: int = 0
|
116
|
+
sha: bytes = dataclasses.field(default_factory=lambda: bytearray)
|
130
117
|
chunk: bytes = dataclasses.field(default_factory=lambda: bytearray)
|
131
118
|
|
132
119
|
|
@@ -134,112 +121,72 @@ class PayloadOTAChunkRequest(Packet):
|
|
134
121
|
|
135
122
|
|
136
123
|
@dataclass
|
137
|
-
class PayloadStatusNotification(
|
124
|
+
class PayloadStatusNotification(Payload):
|
138
125
|
"""Dataclass that holds an application status notification packet."""
|
139
126
|
|
140
|
-
metadata: list[
|
127
|
+
metadata: list[PayloadFieldMetadata] = dataclasses.field(
|
141
128
|
default_factory=lambda: [
|
142
|
-
|
143
|
-
PacketFieldMetadata(name="status", disp="st."),
|
129
|
+
PayloadFieldMetadata(name="status", disp="st."),
|
144
130
|
]
|
145
131
|
)
|
146
132
|
|
147
|
-
device_id: int = 0x0000000000000000
|
148
133
|
status: StatusType = StatusType.Bootloader
|
149
134
|
|
150
135
|
|
151
136
|
@dataclass
|
152
|
-
class
|
153
|
-
"""Dataclass that holds an application started notification packet."""
|
154
|
-
|
155
|
-
metadata: list[PacketFieldMetadata] = dataclasses.field(
|
156
|
-
default_factory=lambda: [
|
157
|
-
PacketFieldMetadata(name="device_id", disp="id", length=8),
|
158
|
-
]
|
159
|
-
)
|
160
|
-
|
161
|
-
device_id: int = 0x0000000000000000
|
162
|
-
|
163
|
-
|
164
|
-
@dataclass
|
165
|
-
class PayloadStoppedNotification(Packet):
|
166
|
-
"""Dataclass that holds an application stopped notification packet."""
|
167
|
-
|
168
|
-
metadata: list[PacketFieldMetadata] = dataclasses.field(
|
169
|
-
default_factory=lambda: [
|
170
|
-
PacketFieldMetadata(name="device_id", disp="id", length=8),
|
171
|
-
]
|
172
|
-
)
|
173
|
-
|
174
|
-
device_id: int = 0x0000000000000000
|
175
|
-
|
176
|
-
|
177
|
-
@dataclass
|
178
|
-
class PayloadOTAStartAckNotification(Packet):
|
137
|
+
class PayloadOTAStartAckNotification(Payload):
|
179
138
|
"""Dataclass that holds an application OTA start ACK notification packet."""
|
180
139
|
|
181
|
-
metadata: list[
|
182
|
-
default_factory=lambda: [
|
183
|
-
PacketFieldMetadata(name="device_id", disp="id", length=8),
|
184
|
-
]
|
140
|
+
metadata: list[PayloadFieldMetadata] = dataclasses.field(
|
141
|
+
default_factory=lambda: []
|
185
142
|
)
|
186
143
|
|
187
|
-
device_id: int = 0x0000000000000000
|
188
|
-
|
189
144
|
|
190
145
|
@dataclass
|
191
|
-
class PayloadOTAChunkAckNotification(
|
146
|
+
class PayloadOTAChunkAckNotification(Payload):
|
192
147
|
"""Dataclass that holds an application OTA chunk ACK notification packet."""
|
193
148
|
|
194
|
-
metadata: list[
|
149
|
+
metadata: list[PayloadFieldMetadata] = dataclasses.field(
|
195
150
|
default_factory=lambda: [
|
196
|
-
|
197
|
-
PacketFieldMetadata(name="index", disp="idx", length=4),
|
198
|
-
PacketFieldMetadata(name="hashes_match", disp="match"),
|
151
|
+
PayloadFieldMetadata(name="index", disp="idx", length=4),
|
199
152
|
]
|
200
153
|
)
|
201
154
|
|
202
|
-
device_id: int = 0x0000000000000000
|
203
155
|
index: int = 0
|
204
|
-
hashes_match: int = 0
|
205
156
|
|
206
157
|
|
207
158
|
@dataclass
|
208
|
-
class PayloadEventNotification(
|
159
|
+
class PayloadEventNotification(Payload):
|
209
160
|
"""Dataclass that holds an event notification packet."""
|
210
161
|
|
211
|
-
metadata: list[
|
162
|
+
metadata: list[PayloadFieldMetadata] = dataclasses.field(
|
212
163
|
default_factory=lambda: [
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
PacketFieldMetadata(
|
164
|
+
PayloadFieldMetadata(name="timestamp", disp="ts", length=4),
|
165
|
+
PayloadFieldMetadata(name="count", disp="len."),
|
166
|
+
PayloadFieldMetadata(
|
217
167
|
name="data", disp="data", type_=bytes, length=0
|
218
168
|
),
|
219
169
|
]
|
220
170
|
)
|
221
171
|
|
222
|
-
device_id: int = 0x0000000000000000
|
223
172
|
timestamp: int = 0
|
224
173
|
count: int = 0
|
225
174
|
data: bytes = dataclasses.field(default_factory=lambda: bytearray)
|
226
175
|
|
227
176
|
|
228
177
|
@dataclass
|
229
|
-
class PayloadMessage(
|
178
|
+
class PayloadMessage(Payload):
|
230
179
|
"""Dataclass that holds a message packet."""
|
231
180
|
|
232
|
-
metadata: list[
|
181
|
+
metadata: list[PayloadFieldMetadata] = dataclasses.field(
|
233
182
|
default_factory=lambda: [
|
234
|
-
|
235
|
-
|
236
|
-
PacketFieldMetadata(
|
183
|
+
PayloadFieldMetadata(name="count", disp="len."),
|
184
|
+
PayloadFieldMetadata(
|
237
185
|
name="message", disp="msg", type_=bytes, length=0
|
238
186
|
),
|
239
187
|
]
|
240
188
|
)
|
241
189
|
|
242
|
-
device_id: int = 0x0000000000000000
|
243
190
|
count: int = 0
|
244
191
|
message: bytes = dataclasses.field(default_factory=lambda: bytearray)
|
245
192
|
|
@@ -269,14 +216,6 @@ def register_parsers():
|
|
269
216
|
SwarmitPayloadType.SWARMIT_NOTIFICATION_STATUS,
|
270
217
|
PayloadStatusNotification,
|
271
218
|
)
|
272
|
-
register_parser(
|
273
|
-
SwarmitPayloadType.SWARMIT_NOTIFICATION_STARTED,
|
274
|
-
PayloadStartedNotification,
|
275
|
-
)
|
276
|
-
register_parser(
|
277
|
-
SwarmitPayloadType.SWARMIT_NOTIFICATION_STOPPED,
|
278
|
-
PayloadStoppedNotification,
|
279
|
-
)
|
280
219
|
register_parser(
|
281
220
|
SwarmitPayloadType.SWARMIT_NOTIFICATION_OTA_START_ACK,
|
282
221
|
PayloadOTAStartAckNotification,
|
swarmit-0.3.0.dist-info/METADATA
DELETED
@@ -1,101 +0,0 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: swarmit
|
3
|
-
Version: 0.3.0
|
4
|
-
Summary: Run Your Own Robot Swarm Testbed.
|
5
|
-
Project-URL: Homepage, https://github.com/DotBots/swarmit
|
6
|
-
Project-URL: Bug Tracker, https://github.com/DotBots/swarmit/issues
|
7
|
-
Author-email: Alexandre Abadie <alexandre.abadie@inria.fr>
|
8
|
-
License: BSD
|
9
|
-
License-File: AUTHORS
|
10
|
-
License-File: LICENSE
|
11
|
-
Classifier: License :: OSI Approved :: BSD License
|
12
|
-
Classifier: Operating System :: MacOS
|
13
|
-
Classifier: Operating System :: Microsoft :: Windows
|
14
|
-
Classifier: Operating System :: POSIX :: Linux
|
15
|
-
Classifier: Programming Language :: Python :: 3
|
16
|
-
Requires-Python: >=3.7
|
17
|
-
Requires-Dist: click==8.1.7
|
18
|
-
Requires-Dist: cryptography==43.0.1
|
19
|
-
Requires-Dist: paho-mqtt>=2.1.0
|
20
|
-
Requires-Dist: pydotbot==0.22.0
|
21
|
-
Requires-Dist: pyserial==3.5
|
22
|
-
Requires-Dist: rich==13.8.1
|
23
|
-
Requires-Dist: structlog==24.4.0
|
24
|
-
Requires-Dist: tqdm==4.66.5
|
25
|
-
Description-Content-Type: text/markdown
|
26
|
-
|
27
|
-
# SwarmIT
|
28
|
-
|
29
|
-
SwarmIT provides a embedded C port for nRF53 as well as Python based services to
|
30
|
-
easily build and deploy a robotic swarm infrastructure testbed.
|
31
|
-
ARM TrustZone is used to create a sandboxed user environment on each device
|
32
|
-
under test, without requiring a control co-processor attached to it.
|
33
|
-
|
34
|
-
## Features
|
35
|
-
|
36
|
-
- Experiment management: start, stop, monitor and status check
|
37
|
-
- Deploy a custom firmware on all or on a subset of robots of a swarm testbed
|
38
|
-
- Resilient robot state: even when crashed by buggy user code, the robot can be reprogrammed remotely and wirelessly
|
39
|
-
|
40
|
-
## Usage
|
41
|
-
|
42
|
-
### Embedded C code
|
43
|
-
|
44
|
-
SwarmIT embedded C code can be built using
|
45
|
-
[Segger Embedded Studio (SES)](https://www.segger.com/products/development-tools/embedded-studio/).
|
46
|
-
|
47
|
-
To provision a device, follow the following steps:
|
48
|
-
1. open [netcore.emProject](device/network_core/netcore.emProject)
|
49
|
-
and [bootloader.emProject](device/bootloader/bootloader.emProject) in SES
|
50
|
-
2. build and load the netcore application on the nRF53 network core,
|
51
|
-
3. build and load the bootloader application on the nRF53 application core.
|
52
|
-
|
53
|
-
The device is now ready.
|
54
|
-
|
55
|
-
### Gateway
|
56
|
-
|
57
|
-
The communication between the computer and the swarm devices is performed via a
|
58
|
-
gateway board connected via USB to the computer.
|
59
|
-
The gateway board is a Nordic nRF53840DK.
|
60
|
-
|
61
|
-
The firmware to run on the gateway can also be compiled and flash using SES.
|
62
|
-
The SES project to open is located at [gateway.emProject](gateway/gateway.emProject).
|
63
|
-
|
64
|
-
After flashing the gateway firmware, LED1 on the DK should blink fast during 1s.
|
65
|
-
|
66
|
-
### Python CLI script
|
67
|
-
|
68
|
-
The Python CLI script provides commands for flashing, starting and stopping user
|
69
|
-
code on the device, as well as monitoring and checking the status of devices
|
70
|
-
in the swarm.
|
71
|
-
|
72
|
-
The Python CLI script connects via a virtual COM port to the gateway connected to
|
73
|
-
the computer.
|
74
|
-
|
75
|
-
The Python CLI script is available on PyPI. Install it using:
|
76
|
-
|
77
|
-
```
|
78
|
-
pip install swarmit
|
79
|
-
```
|
80
|
-
|
81
|
-
Default usage:
|
82
|
-
|
83
|
-
```
|
84
|
-
swarmit --help
|
85
|
-
Usage: swarmit [OPTIONS] COMMAND [ARGS]...
|
86
|
-
|
87
|
-
Options:
|
88
|
-
-p, --port TEXT Serial port to use to send the bitstream to the
|
89
|
-
gateway. Default: /dev/ttyACM0.
|
90
|
-
-b, --baudrate INTEGER Serial port baudrate. Default: 1000000.
|
91
|
-
-d, --devices TEXT Subset list of devices to interact with, separated
|
92
|
-
with ,
|
93
|
-
--help Show this message and exit.
|
94
|
-
|
95
|
-
Commands:
|
96
|
-
flash
|
97
|
-
monitor
|
98
|
-
start
|
99
|
-
status
|
100
|
-
stop
|
101
|
-
```
|
swarmit-0.3.0.dist-info/RECORD
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
dotbot-firmware/doc/sphinx/conf.py,sha256=uQJVglqE9HoqMXJf5nbmCVCLSSGbqfiSr5ZQbE7HsLk,6211
|
2
|
-
testbed/cli/main.py,sha256=FjGbeRkEKT48drOT79Tphfotl23lFV3RgNS_92fsnT4,10741
|
3
|
-
testbed/swarmit/__init__.py,sha256=VrXpHDu3erkzwl_WXrqINBm9xWkcyUy53IQOj042dOs,22
|
4
|
-
testbed/swarmit/adapter.py,sha256=jX3SJ_Z-cOqERa2Oh-KerzY-5eY6FFicbufGyDPapME,2899
|
5
|
-
testbed/swarmit/controller.py,sha256=o0rXvLC-9gyizlz73kr4Q2YQ3Tk5dd5cCAxaoBShh04,21451
|
6
|
-
testbed/swarmit/protocol.py,sha256=JOXUAGDBY2bI9exw7UMivtjm9a8hi0081_1s4haHx-4,8477
|
7
|
-
swarmit-0.3.0.dist-info/METADATA,sha256=-9rqDCAmXS7WwCVOquKYvDcjJCo8YpY7OX9QQz7tSAY,3324
|
8
|
-
swarmit-0.3.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
9
|
-
swarmit-0.3.0.dist-info/entry_points.txt,sha256=R6BGQe6I1FcI5B2jo7Dr-Gh6-Rjn1Ykx3uAGuV5rVTo,50
|
10
|
-
swarmit-0.3.0.dist-info/licenses/AUTHORS,sha256=o2cH3J5JkbZssK_1zYj0m8PHiGiILV0lySR6_hoWKK0,45
|
11
|
-
swarmit-0.3.0.dist-info/licenses/LICENSE,sha256=j97C1uBc5chpQWi4bv_2SrqExuvKaJK2Ch6L2LFkoc4,1492
|
12
|
-
swarmit-0.3.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|