swarmit 0.3.0__py3-none-any.whl → 0.4.5__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,19 +1,27 @@
1
1
  """Module containing classes for interfacing with the DotBot gateway."""
2
2
 
3
- import base64
3
+ import time
4
4
  from abc import ABC, abstractmethod
5
5
 
6
- import paho.mqtt.client as mqtt
7
- from dotbot.hdlc import HDLCHandler, HDLCState, hdlc_encode
8
- from dotbot.protocol import PROTOCOL_VERSION
9
- from dotbot.serial_interface import SerialInterface
6
+ from dotbot.protocol import (
7
+ Packet,
8
+ Payload,
9
+ ProtocolPayloadParserException,
10
+ )
11
+ from marilib.communication_adapter import MQTTAdapter as MarilibMQTTAdapter
12
+ from marilib.communication_adapter import SerialAdapter as MarilibSerialAdapter
13
+ from marilib.mari_protocol import Frame as MariFrame
14
+ from marilib.marilib_cloud import MarilibCloud
15
+ from marilib.marilib_edge import MarilibEdge
16
+ from marilib.model import EdgeEvent, MariNode
17
+ from rich import print
10
18
 
11
19
 
12
20
  class GatewayAdapterBase(ABC):
13
21
  """Base class for interface adapters."""
14
22
 
15
23
  @abstractmethod
16
- def init(self, on_data_received: callable):
24
+ def init(self, on_frame_received: callable):
17
25
  """Initialize the interface."""
18
26
 
19
27
  @abstractmethod
@@ -21,74 +29,114 @@ class GatewayAdapterBase(ABC):
21
29
  """Close the interface."""
22
30
 
23
31
  @abstractmethod
24
- def send_data(self, data):
25
- """Send data to the interface."""
26
-
27
-
28
- class SerialAdapter(GatewayAdapterBase):
29
- """Class used to interface with the serial port."""
30
-
31
- def __init__(self, port, baudrate):
32
- self.port = port
33
- self.baudrate = baudrate
34
- self.hdlc_handler = HDLCHandler()
35
-
36
- def on_byte_received(self, byte):
37
- self.hdlc_handler.handle_byte(byte)
38
- if self.hdlc_handler.state == HDLCState.READY:
39
- self.on_data_received(self.hdlc_handler.payload)
40
-
41
- def init(self, on_data_received: callable):
42
- self.serial = SerialInterface(
43
- self.port, self.baudrate, self.on_byte_received
32
+ def send_payload(self, destination: int, payload: Payload):
33
+ """Send payload to the interface."""
34
+
35
+
36
+ class MarilibEdgeAdapter(GatewayAdapterBase):
37
+ """Class used to interface with Marilib."""
38
+
39
+ def on_event(self, event: EdgeEvent, event_data: MariNode | MariFrame):
40
+ if event == EdgeEvent.NODE_JOINED:
41
+ if self.verbose:
42
+ print("[green]Node joined:[/]", event_data)
43
+ elif event == EdgeEvent.NODE_LEFT:
44
+ if self.verbose:
45
+ print("[orange]Node left:[/]", event_data)
46
+ elif event == EdgeEvent.NODE_DATA:
47
+ try:
48
+ packet = Packet.from_bytes(event_data.payload)
49
+ except (ValueError, ProtocolPayloadParserException) as exc:
50
+ print(f"[red]Error parsing packet: {exc}[/]")
51
+ return
52
+ if not hasattr(self, "on_frame_received"):
53
+ return
54
+ self.on_frame_received(event_data.header, packet)
55
+
56
+ def __init__(self, port: str, baudrate: int, verbose: bool = False):
57
+ self.verbose = verbose
58
+ self.mari = MarilibEdge(
59
+ self.on_event, MarilibSerialAdapter(port, baudrate)
44
60
  )
45
- self.on_data_received = on_data_received
46
- # Just write a single byte to fake a DotBot gateway handshake
47
- self.serial.write(int(PROTOCOL_VERSION).to_bytes(length=1))
48
61
 
49
- def close(self):
50
- self.serial.stop()
62
+ def _busy_wait(self, timeout: int):
63
+ """Wait for the condition to be met."""
64
+ while timeout > 0:
65
+ self.mari.update()
66
+ timeout -= 0.1
67
+ time.sleep(0.1)
51
68
 
52
- def send_data(self, data):
53
- self.serial.write(hdlc_encode(data))
69
+ def init(self, on_frame_received: callable):
70
+ self.on_frame_received = on_frame_received
71
+ if self.verbose:
72
+ self._busy_wait(3)
73
+ print("[yellow]Mari nodes available:[/]")
74
+ print(self.mari.nodes)
54
75
 
76
+ def close(self):
77
+ pass
55
78
 
56
- class MQTTAdapter(GatewayAdapterBase):
57
- """Class used to interface with MQTT."""
58
-
59
- def __init__(self, host, port):
60
- self.host = host
61
- self.port = port
62
- self.client = None
79
+ def send_payload(self, destination: int, payload: Payload):
80
+ self.mari.send_frame(
81
+ dst=destination,
82
+ payload=Packet.from_payload(payload).to_bytes(),
83
+ )
63
84
 
64
- def on_message(self, client, userdata, message):
65
- self.on_data_received(base64.b64decode(message.payload))
66
85
 
67
- def on_log(self, client, userdata, paho_log_level, messages):
68
- print(messages)
86
+ class MarilibCloudAdapter(GatewayAdapterBase):
87
+ """Class used to interface with Marilib."""
88
+
89
+ def on_event(self, event: EdgeEvent, event_data: MariNode | MariFrame):
90
+ if event == EdgeEvent.NODE_JOINED:
91
+ if self.verbose:
92
+ print("[green]Node joined:[/]", event_data)
93
+ elif event == EdgeEvent.NODE_LEFT:
94
+ if self.verbose:
95
+ print("[orange]Node left:[/]", event_data)
96
+ elif event == EdgeEvent.NODE_DATA:
97
+ try:
98
+ packet = Packet.from_bytes(event_data.payload)
99
+ except (ValueError, ProtocolPayloadParserException) as exc:
100
+ print(f"[red]Error parsing packet: {exc}[/]")
101
+ return
102
+ if not hasattr(self, "on_frame_received"):
103
+ return
104
+ self.on_frame_received(event_data.header, packet)
105
+
106
+ def __init__(
107
+ self,
108
+ host: str,
109
+ port: int,
110
+ use_tls: bool,
111
+ network_id: int,
112
+ verbose: bool = False,
113
+ ):
114
+ self.verbose = verbose
115
+ self.mari = MarilibCloud(
116
+ self.on_event,
117
+ MarilibMQTTAdapter(host, port, use_tls=use_tls, is_edge=False),
118
+ network_id,
119
+ )
69
120
 
70
- def on_connect(self, client, userdata, flags, reason_code, properties):
71
- self.client.subscribe("/pydotbot/edge_to_controller")
121
+ def _busy_wait(self, timeout):
122
+ """Wait for the condition to be met."""
123
+ while timeout > 0:
124
+ self.mari.update()
125
+ timeout -= 0.1
126
+ time.sleep(0.1)
72
127
 
73
- def init(self, on_data_received: callable):
74
- self.on_data_received = on_data_received
75
- self.client = mqtt.Client(
76
- mqtt.CallbackAPIVersion.VERSION2,
77
- protocol=mqtt.MQTTProtocolVersion.MQTTv5,
78
- )
79
- self.client.tls_set_context(context=None)
80
- # self.client.on_log = self.on_log
81
- self.client.on_connect = self.on_connect
82
- self.client.on_message = self.on_message
83
- self.client.connect(self.host, self.port, 60)
84
- self.client.loop_start()
128
+ def init(self, on_frame_received: callable):
129
+ self.on_frame_received = on_frame_received
130
+ if self.verbose:
131
+ self._busy_wait(3)
132
+ print("[yellow]Mari nodes available:[/]")
133
+ print(self.mari.nodes)
85
134
 
86
135
  def close(self):
87
- self.client.disconnect()
88
- self.client.loop_stop()
136
+ pass
89
137
 
90
- def send_data(self, data):
91
- self.client.publish(
92
- "/pydotbot/controller_to_edge",
93
- base64.b64encode(data).decode(),
138
+ def send_payload(self, destination: int, payload: Payload):
139
+ self.mari.send_frame(
140
+ dst=destination,
141
+ payload=Packet.from_payload(payload).to_bytes(),
94
142
  )