swarmit 0.4.5__py3-none-any.whl → 0.5.0rc1__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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: swarmit
3
- Version: 0.4.5
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==8.1.7
17
+ Requires-Dist: click>=8.1.7
18
18
  Requires-Dist: cryptography==43.0.1
19
- Requires-Dist: marilib-pkg>=0.6.0
20
- Requires-Dist: pydotbot>=0.24.1
21
- Requires-Dist: rich==14.0.0
22
- Requires-Dist: structlog==24.4.0
23
- Requires-Dist: tqdm==4.66.5
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
@@ -0,0 +1,12 @@
1
+ dotbot-firmware/doc/sphinx/conf.py,sha256=uQJVglqE9HoqMXJf5nbmCVCLSSGbqfiSr5ZQbE7HsLk,6211
2
+ testbed/cli/main.py,sha256=2jix2xPzP4XLcnpk804gKGOJWnXAho73lbZXqJGk_6g,9399
3
+ testbed/swarmit/__init__.py,sha256=9WnHRrMe9HW-DxZwi-StMTVa8hbBeNHnZ2iyADAhHzg,25
4
+ testbed/swarmit/adapter.py,sha256=Qmx7ULkx0OfyU7PJh-VBQibEOhvnDfnB3_DmntQ2tfU,4616
5
+ testbed/swarmit/controller.py,sha256=JavaaRgwKxmiIvPGPIyxjEy4vGrt8Qt7hiHxv2wKz_g,23559
6
+ testbed/swarmit/protocol.py,sha256=6G-cZfbLqnffiEGw2uEgxjzid-kPP4deisDY5SEiTGo,6925
7
+ swarmit-0.5.0rc1.dist-info/METADATA,sha256=X0B9W3SDJTOR3x0etRQttOnHYOE2P8duhoV7yBR3yh0,4868
8
+ swarmit-0.5.0rc1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
+ swarmit-0.5.0rc1.dist-info/entry_points.txt,sha256=R6BGQe6I1FcI5B2jo7Dr-Gh6-Rjn1Ykx3uAGuV5rVTo,50
10
+ swarmit-0.5.0rc1.dist-info/licenses/AUTHORS,sha256=o2cH3J5JkbZssK_1zYj0m8PHiGiILV0lySR6_hoWKK0,45
11
+ swarmit-0.5.0rc1.dist-info/licenses/LICENSE,sha256=j97C1uBc5chpQWi4bv_2SrqExuvKaJK2Ch6L2LFkoc4,1492
12
+ swarmit-0.5.0rc1.dist-info/RECORD,,
@@ -1 +1 @@
1
- __version__ = "0.4.5"
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 = 3
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
- key: device
107
- for key, device in status_data.items()
108
- if (devices and key in devices) or (not devices)
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, status in sorted(data.items()):
161
+ for device_addr, device_data in sorted(data.items()):
162
+
126
163
  table.add_row(
127
164
  f"{device_addr}",
128
- f"{'[bold cyan]' if status == StatusType.Running else '[bold green]'}{status.name}",
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, StatusType] = {}
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, status in self.known_devices.items()
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, status in self.known_devices.items()
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, status in self.known_devices.items()
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
- self.status_data.update(
296
- {device_addr: StatusType(packet.payload.status)}
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,12 +0,0 @@
1
- dotbot-firmware/doc/sphinx/conf.py,sha256=uQJVglqE9HoqMXJf5nbmCVCLSSGbqfiSr5ZQbE7HsLk,6211
2
- testbed/cli/main.py,sha256=2jix2xPzP4XLcnpk804gKGOJWnXAho73lbZXqJGk_6g,9399
3
- testbed/swarmit/__init__.py,sha256=ErkLkI2TDBX1OIqi2GGa20CPeu4ZculEi-XffRbLU6M,22
4
- testbed/swarmit/adapter.py,sha256=Qmx7ULkx0OfyU7PJh-VBQibEOhvnDfnB3_DmntQ2tfU,4616
5
- testbed/swarmit/controller.py,sha256=7XTX0Px8hnzE-ebUsMLFuPs3uKOrdBSle2mkOuW_gVQ,22354
6
- testbed/swarmit/protocol.py,sha256=tkPMIGo_G1Fvo3zM6_zk4a3i3gqLtEzDFf97VRHa4B4,6344
7
- swarmit-0.4.5.dist-info/METADATA,sha256=5nRZ4oWcNkCxSNZxpBUtKteTIUA7ZwweM43gtLgIa4g,4862
8
- swarmit-0.4.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
- swarmit-0.4.5.dist-info/entry_points.txt,sha256=R6BGQe6I1FcI5B2jo7Dr-Gh6-Rjn1Ykx3uAGuV5rVTo,50
10
- swarmit-0.4.5.dist-info/licenses/AUTHORS,sha256=o2cH3J5JkbZssK_1zYj0m8PHiGiILV0lySR6_hoWKK0,45
11
- swarmit-0.4.5.dist-info/licenses/LICENSE,sha256=j97C1uBc5chpQWi4bv_2SrqExuvKaJK2Ch6L2LFkoc4,1492
12
- swarmit-0.4.5.dist-info/RECORD,,