swarmit 0.1.0__py3-none-any.whl → 0.2.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.
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: swarmit
3
- Version: 0.1.0
3
+ Version: 0.2.0
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
7
7
  Author-email: Alexandre Abadie <alexandre.abadie@inria.fr>
8
- License: BSD
8
+ License-File: AUTHORS
9
9
  License-File: LICENSE
10
10
  Classifier: License :: OSI Approved :: BSD License
11
11
  Classifier: Operating System :: MacOS
@@ -15,7 +15,7 @@ Classifier: Programming Language :: Python :: 3
15
15
  Requires-Python: >=3.7
16
16
  Requires-Dist: click==8.1.7
17
17
  Requires-Dist: cryptography==43.0.1
18
- Requires-Dist: pydotbot==0.21.2
18
+ Requires-Dist: pydotbot==0.22.0
19
19
  Requires-Dist: pyserial==3.5
20
20
  Requires-Dist: rich==13.8.1
21
21
  Requires-Dist: structlog==24.4.0
@@ -50,12 +50,32 @@ and [bootloader.emProject](device/bootloader/bootloader.emProject) in SES
50
50
 
51
51
  The device is now ready.
52
52
 
53
+ ### Gateway
54
+
55
+ The communication between the computer and the swarm devices is performed via a
56
+ gateway board connected via USB to the computer.
57
+ The gateway board is a Nordic nRF53840DK.
58
+
59
+ The firmware to run on the gateway can also be compiled and flash using SES.
60
+ The SES project to open is located at [gateway.emProject](gateway/gateway.emProject).
61
+
62
+ After flashing the gateway firmware, LED1 on the DK should blink fast during 1s.
63
+
53
64
  ### Python CLI script
54
65
 
55
66
  The Python CLI script provides commands for flashing, starting and stopping user
56
67
  code on the device, as well as monitoring and checking the status of devices
57
68
  in the swarm.
58
69
 
70
+ The Python CLI script connects via a virtual COM port to the gateway connected to
71
+ the computer.
72
+
73
+ The Python CLI script is available on PyPI. Install it using:
74
+
75
+ ```
76
+ pip install swarmit
77
+ ```
78
+
59
79
  Default usage:
60
80
 
61
81
  ```
@@ -0,0 +1,7 @@
1
+ testbed/cli/main.py,sha256=_mZJx_W549A_5FVMylU0jNXvCG_6cAcDj2fRMAoU65o,19689
2
+ swarmit-0.2.0.dist-info/METADATA,sha256=OkItUGFQ29DNW2xHUkOZLwYG0Mj9smwnmY9vjIlAt2Q,3279
3
+ swarmit-0.2.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
4
+ swarmit-0.2.0.dist-info/entry_points.txt,sha256=R6BGQe6I1FcI5B2jo7Dr-Gh6-Rjn1Ykx3uAGuV5rVTo,50
5
+ swarmit-0.2.0.dist-info/licenses/AUTHORS,sha256=o2cH3J5JkbZssK_1zYj0m8PHiGiILV0lySR6_hoWKK0,45
6
+ swarmit-0.2.0.dist-info/licenses/LICENSE,sha256=j97C1uBc5chpQWi4bv_2SrqExuvKaJK2Ch6L2LFkoc4,1492
7
+ swarmit-0.2.0.dist-info/RECORD,,
@@ -0,0 +1 @@
1
+ Alexandre Abadie <alexandre.abadie@inria.fr>
testbed/cli/main.py CHANGED
@@ -19,14 +19,18 @@ from rich.table import Table
19
19
 
20
20
  from dotbot.logger import LOGGER
21
21
  from dotbot.hdlc import hdlc_encode, HDLCHandler, HDLCState
22
- from dotbot.protocol import PROTOCOL_VERSION
23
- from dotbot.serial_interface import SerialInterface, SerialInterfaceException, get_default_port
22
+ from dotbot.protocol import PROTOCOL_VERSION, ProtocolHeader
23
+ from dotbot.serial_interface import (
24
+ SerialInterface,
25
+ SerialInterfaceException,
26
+ get_default_port,
27
+ )
24
28
 
25
29
 
26
30
  SERIAL_PORT = get_default_port()
27
31
  BAUDRATE = 1000000
28
32
  CHUNK_SIZE = 128
29
- SWARMIT_PREAMBLE = bytes([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07])
33
+ HEADER = ProtocolHeader()
30
34
 
31
35
 
32
36
  class NotificationType(Enum):
@@ -66,6 +70,17 @@ class DataChunk:
66
70
  data: bytes
67
71
 
68
72
 
73
+ def _header():
74
+ """Return the header for the protocol."""
75
+ buffer = bytearray()
76
+ for field in ProtocolHeader().fields:
77
+ buffer += int(field.value).to_bytes(
78
+ length=field.length, byteorder="little", signed=field.signed
79
+ )
80
+ buffer += int(16).to_bytes(length=1, byteorder="little")
81
+ return buffer
82
+
83
+
69
84
  class SwarmitFlash:
70
85
  """Class used to flash a firmware."""
71
86
 
@@ -79,13 +94,11 @@ class SwarmitFlash:
79
94
  self.chunks = []
80
95
  self.fw_hash = None
81
96
  self.acked_ids = []
82
- # Just write a single byte to fake a gateway handshake
83
- self.serial.write(int(PROTOCOL_VERSION).to_bytes(length=1))
84
97
 
85
98
  def on_byte_received(self, byte):
86
99
  self.hdlc_handler.handle_byte(byte)
87
100
  if self.hdlc_handler.state == HDLCState.READY:
88
- payload = self.hdlc_handler.payload
101
+ payload = self.hdlc_handler.payload[25:]
89
102
  if not payload:
90
103
  return
91
104
  deviceid_ack = hex(int.from_bytes(payload[0:8], byteorder="little"))
@@ -102,7 +115,7 @@ class SwarmitFlash:
102
115
 
103
116
  def _send_start_ota(self, device_id):
104
117
  buffer = bytearray()
105
- buffer += SWARMIT_PREAMBLE
118
+ buffer += _header()
106
119
  buffer += int(device_id, 16).to_bytes(length=8, byteorder="little")
107
120
  buffer += int(RequestType.SWARMIT_REQ_OTA_START.value).to_bytes(
108
121
  length=1, byteorder="little"
@@ -176,7 +189,7 @@ class SwarmitFlash:
176
189
  break
177
190
  if send is True:
178
191
  buffer = bytearray()
179
- buffer += SWARMIT_PREAMBLE
192
+ buffer += _header()
180
193
  buffer += int(device_id, 16).to_bytes(length=8, byteorder="little")
181
194
  buffer += int(RequestType.SWARMIT_REQ_OTA_CHUNK.value).to_bytes(
182
195
  length=1, byteorder="little"
@@ -222,7 +235,7 @@ class SwarmitStart:
222
235
 
223
236
  def _send_start(self, device_id):
224
237
  buffer = bytearray()
225
- buffer += SWARMIT_PREAMBLE
238
+ buffer += _header()
226
239
  buffer += int(device_id, 16).to_bytes(length=8, byteorder="little")
227
240
  buffer += int(RequestType.SWARMIT_REQ_EXPERIMENT_START.value).to_bytes(
228
241
  length=1, byteorder="little"
@@ -251,7 +264,7 @@ class SwarmitStop:
251
264
 
252
265
  def _send_stop(self, device_id):
253
266
  buffer = bytearray()
254
- buffer += SWARMIT_PREAMBLE
267
+ buffer += _header()
255
268
  buffer += int(device_id, 16).to_bytes(length=8, byteorder="little")
256
269
  buffer += int(RequestType.SWARMIT_REQ_EXPERIMENT_STOP.value).to_bytes(
257
270
  length=1, byteorder="little"
@@ -285,7 +298,7 @@ class SwarmitMonitor:
285
298
  return
286
299
  self.hdlc_handler.handle_byte(byte)
287
300
  if self.hdlc_handler.state == HDLCState.READY:
288
- payload = self.hdlc_handler.payload
301
+ payload = self.hdlc_handler.payload[25:]
289
302
  if not payload:
290
303
  return
291
304
  deviceid = int.from_bytes(payload[0:8], byteorder="little")
@@ -318,22 +331,22 @@ class SwarmitStatus:
318
331
  def __init__(self, port, baudrate):
319
332
  self.logger = LOGGER.bind(context=__name__)
320
333
  self.hdlc_handler = HDLCHandler()
321
- self.serial = SerialInterface(port, baudrate, self.on_byte_received)
322
334
  self.last_deviceid_notification = None
323
- # Just write a single byte to fake a DotBot gateway handshake
324
- self.serial.write(int(PROTOCOL_VERSION).to_bytes(length=1))
325
335
  self.status_data = {}
326
336
  self.resp_ids = []
327
337
  self.table = Table()
328
338
  self.table.add_column("Device ID", style="magenta", no_wrap=True)
329
339
  self.table.add_column("Status", style="green")
340
+ self.serial = SerialInterface(port, baudrate, self.on_byte_received)
341
+ # Just write a single byte to fake a DotBot gateway handshake
342
+ self.serial.write(int(PROTOCOL_VERSION).to_bytes(length=1))
330
343
 
331
344
  def on_byte_received(self, byte):
332
345
  if self.hdlc_handler is None:
333
346
  return
334
347
  self.hdlc_handler.handle_byte(byte)
335
348
  if self.hdlc_handler.state == HDLCState.READY:
336
- payload = self.hdlc_handler.payload
349
+ payload = self.hdlc_handler.payload[25:]
337
350
  if not payload:
338
351
  return
339
352
  deviceid_resp = hex(int.from_bytes(payload[0:8], byteorder="little"))
@@ -345,19 +358,19 @@ class SwarmitStatus:
345
358
  self.status_data[deviceid_resp] = status
346
359
  self.table.add_row(
347
360
  deviceid_resp,
348
- f"{"[bold cyan]" if status == StatusType.Running else "[bold green]"}{status.name}",
361
+ f'{"[bold cyan]" if status == StatusType.Running else "[bold green]"}{status.name}',
349
362
  )
350
363
 
351
364
  def status(self, display=True):
352
365
  buffer = bytearray()
353
- buffer += SWARMIT_PREAMBLE
366
+ buffer += _header()
354
367
  buffer += int("0", 16).to_bytes(length=8, byteorder="little")
355
368
  buffer += int(RequestType.SWARMIT_REQ_EXPERIMENT_STATUS.value).to_bytes(
356
369
  length=1, byteorder="little"
357
370
  )
358
371
  self.serial.write(hdlc_encode(buffer))
359
372
  timeout = 0 # ms
360
- while timeout < 200:
373
+ while timeout < 2000:
361
374
  timeout += 1
362
375
  time.sleep(0.0001)
363
376
  if self.status_data and display is True:
@@ -393,7 +406,7 @@ def swarmit_flash(port, baudrate, firmware, yes, devices, ready_devices):
393
406
  console = Console()
394
407
  console.print(
395
408
  "[bold red]Error:[/] some acknowledgment are missing "
396
- f"({", ".join(sorted(set(ready_devices).difference(set(ids))))}). "
409
+ f'({", ".join(sorted(set(ready_devices).difference(set(ids))))}). '
397
410
  "Aborting."
398
411
  )
399
412
  return False
@@ -1,6 +0,0 @@
1
- testbed/cli/main.py,sha256=wQgWFdR7IIdT7IqzHarWW6_PdXrvhu2wgJl3sehzAJ8,19518
2
- swarmit-0.1.0.dist-info/METADATA,sha256=H4oeGLCMoS7GcMrKrQ4sEC0hkKcqOee5aYC3t2FO0LY,2650
3
- swarmit-0.1.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
4
- swarmit-0.1.0.dist-info/entry_points.txt,sha256=R6BGQe6I1FcI5B2jo7Dr-Gh6-Rjn1Ykx3uAGuV5rVTo,50
5
- swarmit-0.1.0.dist-info/licenses/LICENSE,sha256=j97C1uBc5chpQWi4bv_2SrqExuvKaJK2Ch6L2LFkoc4,1492
6
- swarmit-0.1.0.dist-info/RECORD,,