meshcore 1.9.8.dev2__tar.gz → 1.9.8.dev5__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.
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/PKG-INFO +1 -1
- meshcore-1.9.8.dev5/examples/tcp_login_status.py +94 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/pyproject.toml +1 -1
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/src/meshcore/ble_cx.py +6 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/src/meshcore/commands.py +31 -7
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/src/meshcore/events.py +11 -3
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/src/meshcore/meshcore.py +15 -9
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/src/meshcore/reader.py +23 -7
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/src/meshcore/serial_cx.py +8 -1
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/src/meshcore/tcp_cx.py +7 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/.gitignore +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/LICENSE +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/README.md +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/ble_chat.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/ble_t1000_chan_msg.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/ble_t1000_custom_vars.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/ble_t1000_infos.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/ble_t1000_msg.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/ble_t1000_set_cv.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/mepo_mc_gps.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/pubsub_example.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/rf_packet_monitor.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/serial_battery_monitor.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/serial_chat.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/serial_contacts.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/serial_infos.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/serial_msg.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/serial_repeater_status.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/serial_repeater_telemetry.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/serial_trace.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/tcp_chat.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/tcp_mchome_contacts.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/tcp_mchome_infos.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/tcp_mchome_msg.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/examples/tcp_mchome_readmsgs.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/pytest.ini +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/src/meshcore/__init__.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/src/meshcore/packets.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/tests/README.md +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/tests/unit/test_commands.py +0 -0
- {meshcore-1.9.8.dev2 → meshcore-1.9.8.dev5}/tests/unit/test_events.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: meshcore
|
|
3
|
-
Version: 1.9.8.
|
|
3
|
+
Version: 1.9.8.dev5
|
|
4
4
|
Summary: Base classes for communicating with meshcore companion radios
|
|
5
5
|
Project-URL: Homepage, https://github.com/fdlamotte/meshcore_py
|
|
6
6
|
Project-URL: Issues, https://github.com/fdlamotte/meshcore_py/issues
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import argparse
|
|
5
|
+
import logging
|
|
6
|
+
from math import log
|
|
7
|
+
|
|
8
|
+
from meshcore import MeshCore
|
|
9
|
+
from meshcore.events import EventType
|
|
10
|
+
|
|
11
|
+
# Set up logging
|
|
12
|
+
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
async def main():
|
|
16
|
+
# Parse command line arguments
|
|
17
|
+
parser = argparse.ArgumentParser(description='Get status from a repeater via TCP connection')
|
|
18
|
+
parser.add_argument('-host', '--hostname', required=True, help='TCP hostname or IP address')
|
|
19
|
+
parser.add_argument('-port', '--port', type=int, required=True, help='TCP port number')
|
|
20
|
+
parser.add_argument('-r', '--repeater', required=True, help='Repeater name')
|
|
21
|
+
parser.add_argument('-pw', '--password', required=True, help='Password for login')
|
|
22
|
+
args = parser.parse_args()
|
|
23
|
+
|
|
24
|
+
# Connect to the device
|
|
25
|
+
print(f"Connecting to TCP {args.hostname}:{args.port}...")
|
|
26
|
+
mc = await MeshCore.create_tcp(args.hostname, args.port, debug=True)
|
|
27
|
+
|
|
28
|
+
try:
|
|
29
|
+
# Set up a simple event handler to log all events
|
|
30
|
+
async def log_event(event):
|
|
31
|
+
print(f"EVENT: {event.type.name} - Payload: {event.payload}")
|
|
32
|
+
|
|
33
|
+
# Subscribe to login events
|
|
34
|
+
mc.subscribe(EventType.LOGIN_SUCCESS, log_event)
|
|
35
|
+
mc.subscribe(EventType.LOGIN_FAILED, log_event)
|
|
36
|
+
mc.subscribe(EventType.STATUS_RESPONSE, log_event)
|
|
37
|
+
|
|
38
|
+
# Get contacts
|
|
39
|
+
await mc.ensure_contacts()
|
|
40
|
+
|
|
41
|
+
repeater = mc.get_contact_by_name(args.repeater)
|
|
42
|
+
|
|
43
|
+
if repeater is None:
|
|
44
|
+
print(f"Repeater '{args.repeater}' not found in contacts.")
|
|
45
|
+
print(f"Available contacts: {mc.contacts}")
|
|
46
|
+
return
|
|
47
|
+
|
|
48
|
+
print(f"Found repeater: {repeater}")
|
|
49
|
+
|
|
50
|
+
# Send login request
|
|
51
|
+
print(f"Sending login request to '{args.repeater}'...")
|
|
52
|
+
login_cmd = await mc.commands.send_login(repeater, args.password)
|
|
53
|
+
if login_cmd.type == EventType.ERROR:
|
|
54
|
+
print(f"Login failed: {login_cmd.payload}")
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
filter = {"pubkey_prefix": repeater["public_key"][0:12]}
|
|
58
|
+
login_result = await mc.wait_for_event(EventType.LOGIN_SUCCESS, filter, timeout=10)
|
|
59
|
+
print(f"Login result: {login_result}")
|
|
60
|
+
|
|
61
|
+
send_ver = await mc.commands.send_cmd(repeater, "ver")
|
|
62
|
+
if send_ver.type == EventType.ERROR:
|
|
63
|
+
print(f"Error sending version command: {send_ver.payload}")
|
|
64
|
+
return
|
|
65
|
+
await mc.wait_for_event(EventType.MESSAGES_WAITING)
|
|
66
|
+
ver_msg = await mc.commands.get_msg()
|
|
67
|
+
print(f"Version message: {ver_msg.payload}")
|
|
68
|
+
|
|
69
|
+
# Send status request
|
|
70
|
+
print("Sending status request...")
|
|
71
|
+
await mc.commands.send_statusreq(repeater)
|
|
72
|
+
|
|
73
|
+
# Wait for status response
|
|
74
|
+
print("Waiting for status response event...")
|
|
75
|
+
status_event = await mc.wait_for_event(EventType.STATUS_RESPONSE, timeout=5.0)
|
|
76
|
+
|
|
77
|
+
if status_event:
|
|
78
|
+
print(f"Status response received: {status_event.payload}")
|
|
79
|
+
else:
|
|
80
|
+
print("No status response received within timeout")
|
|
81
|
+
|
|
82
|
+
finally:
|
|
83
|
+
# Always disconnect properly
|
|
84
|
+
print("Disconnecting...")
|
|
85
|
+
await mc.disconnect()
|
|
86
|
+
print("Disconnected from device")
|
|
87
|
+
|
|
88
|
+
if __name__ == "__main__":
|
|
89
|
+
try:
|
|
90
|
+
asyncio.run(main())
|
|
91
|
+
except KeyboardInterrupt:
|
|
92
|
+
print("\nOperation cancelled by user")
|
|
93
|
+
except Exception as e:
|
|
94
|
+
print(f"Error: {e}")
|
|
@@ -91,3 +91,9 @@ class BLEConnection:
|
|
|
91
91
|
logger.error("RX characteristic not found")
|
|
92
92
|
return False
|
|
93
93
|
await self.client.write_gatt_char(self.rx_char, bytes(data), response=False)
|
|
94
|
+
|
|
95
|
+
async def disconnect(self):
|
|
96
|
+
"""Disconnect from the BLE device."""
|
|
97
|
+
if self.client and self.client.is_connected:
|
|
98
|
+
await self.client.disconnect()
|
|
99
|
+
logger.debug("BLE Connection closed")
|
|
@@ -195,7 +195,33 @@ class CommandHandler:
|
|
|
195
195
|
+ int(af).to_bytes(4, 'little')\
|
|
196
196
|
+ int(0).to_bytes(1, 'little')\
|
|
197
197
|
+ int(0).to_bytes(1, 'little'), [EventType.OK, EventType.ERROR])
|
|
198
|
-
|
|
198
|
+
|
|
199
|
+
async def set_other_params(self, manual_add_contacts : bool, telemetry_mode_base : int, telemetry_mode_loc : int) :
|
|
200
|
+
telemetry_mode = (telemetry_mode_base & 0b11) | ((telemetry_mode_loc & 0b11) << 2)
|
|
201
|
+
data = b"\x26" + manual_add_contacts.to_bytes(1) + telemetry_mode.to_bytes(1)
|
|
202
|
+
return await self.send(data, [EventType.OK, EventType.ERROR])
|
|
203
|
+
|
|
204
|
+
async def set_telemetry_mode_base(self, telemetry_mode_base : int) :
|
|
205
|
+
infos = (await self.send_appstart()).payload
|
|
206
|
+
return await self.set_other_params(
|
|
207
|
+
infos["manual_add_contacts"],
|
|
208
|
+
telemetry_mode_base,
|
|
209
|
+
infos["telemetry_mode_loc"])
|
|
210
|
+
|
|
211
|
+
async def set_telemetry_mode_loc(self, telemetry_mode_loc : int) :
|
|
212
|
+
infos = (await self.send_appstart()).payload
|
|
213
|
+
return await self.set_other_params(
|
|
214
|
+
infos["manual_add_contacts"],
|
|
215
|
+
infos["telemetry_mode_base"],
|
|
216
|
+
telemetry_mode_loc)
|
|
217
|
+
|
|
218
|
+
async def set_manual_add_contacts(self, manual_add_contacts:bool) :
|
|
219
|
+
infos = (await self.send_appstart()).payload
|
|
220
|
+
return await self.set_other_params(
|
|
221
|
+
manual_add_contacts,
|
|
222
|
+
infos["telemetry_mode_base"],
|
|
223
|
+
infos["telemetry_mode_loc"])
|
|
224
|
+
|
|
199
225
|
async def set_devicepin(self, pin: int) -> Event:
|
|
200
226
|
logger.debug(f"Setting device PIN to: {pin}")
|
|
201
227
|
return await self.send(b"\x25" \
|
|
@@ -227,6 +253,10 @@ class CommandHandler:
|
|
|
227
253
|
data = b"\x11"
|
|
228
254
|
return await self.send(data, [EventType.CONTACT_URI, EventType.ERROR])
|
|
229
255
|
|
|
256
|
+
async def import_contact(self, card_data) -> Event:
|
|
257
|
+
data = b"\x12" + card_data
|
|
258
|
+
return await self.send(data, [EventType.OK, EventType.ERROR])
|
|
259
|
+
|
|
230
260
|
async def remove_contact(self, key: DestinationType) -> Event:
|
|
231
261
|
key_bytes = _validate_destination(key, prefix_length=32)
|
|
232
262
|
logger.debug(f"Removing contact: {key_bytes.hex()}")
|
|
@@ -306,15 +336,9 @@ class CommandHandler:
|
|
|
306
336
|
data = b"\x03\x00" + chan.to_bytes(1, 'little') + timestamp + msg.encode("utf-8")
|
|
307
337
|
return await self.send(data, [EventType.OK, EventType.ERROR])
|
|
308
338
|
|
|
309
|
-
async def send_other_params(self, manual_add_contacts : bool, telemetry_mode_base : bool, telemetry_mode_loc : bool) :
|
|
310
|
-
telemetry_mode = (telemetry_mode_base & 0b11) | ((telemetry_mode_loc & 0b11) << 2)
|
|
311
|
-
data = b"\x26" + manual_add_contacts.to_bytes(1) + telemetry_mode.to_bytes(1)
|
|
312
|
-
return await self.send(data, [EventType.OK, EventType.ERROR])
|
|
313
|
-
|
|
314
339
|
async def send_telemetry_req(self, dst: DestinationType) -> Event :
|
|
315
340
|
dst_bytes = _validate_destination(dst, prefix_length=32)
|
|
316
341
|
logger.debug(f"Asking telemetry to {dst_bytes.hex()}")
|
|
317
|
-
|
|
318
342
|
data = b"\x27\x00\x00\x00" + dst_bytes
|
|
319
343
|
return await self.send(data, [EventType.MSG_SENT, EventType.ERROR])
|
|
320
344
|
|
|
@@ -64,6 +64,15 @@ class Event:
|
|
|
64
64
|
# Add any keyword arguments to the attributes dictionary
|
|
65
65
|
if kwargs:
|
|
66
66
|
self.attributes.update(kwargs)
|
|
67
|
+
def clone(self):
|
|
68
|
+
"""
|
|
69
|
+
Create a copy of the event.
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
A new Event object with the same type, payload, and attributes.
|
|
73
|
+
"""
|
|
74
|
+
copied_payload = self.payload.copy() if isinstance(self.payload, dict) else self.payload
|
|
75
|
+
return Event(self.type, copied_payload, self.attributes.copy())
|
|
67
76
|
|
|
68
77
|
|
|
69
78
|
class Subscription:
|
|
@@ -79,7 +88,7 @@ class Subscription:
|
|
|
79
88
|
|
|
80
89
|
class EventDispatcher:
|
|
81
90
|
def __init__(self):
|
|
82
|
-
self.queue = asyncio.Queue()
|
|
91
|
+
self.queue: asyncio.Queue[Event] = asyncio.Queue()
|
|
83
92
|
self.subscriptions: List[Subscription] = []
|
|
84
93
|
self.running = False
|
|
85
94
|
self._task = None
|
|
@@ -118,7 +127,6 @@ class EventDispatcher:
|
|
|
118
127
|
event = await self.queue.get()
|
|
119
128
|
logger.debug(f"Dispatching event: {event.type}, {event.payload}, {event.attributes}")
|
|
120
129
|
for subscription in self.subscriptions.copy():
|
|
121
|
-
logger.debug(f"Checking subscription: {subscription.event_type}, {subscription.attribute_filters}")
|
|
122
130
|
# Check if event type matches
|
|
123
131
|
if subscription.event_type is None or subscription.event_type == event.type:
|
|
124
132
|
# Check if all attribute filters match
|
|
@@ -128,7 +136,7 @@ class EventDispatcher:
|
|
|
128
136
|
for key, value in subscription.attribute_filters.items()):
|
|
129
137
|
continue
|
|
130
138
|
try:
|
|
131
|
-
result = subscription.callback(event)
|
|
139
|
+
result = subscription.callback(event.clone())
|
|
132
140
|
if asyncio.iscoroutine(result):
|
|
133
141
|
await result
|
|
134
142
|
except Exception as e:
|
|
@@ -5,7 +5,9 @@ from typing import Optional, Dict, Any, Union
|
|
|
5
5
|
from .events import EventDispatcher, EventType
|
|
6
6
|
from .reader import MessageReader
|
|
7
7
|
from .commands import CommandHandler
|
|
8
|
-
|
|
8
|
+
from .ble_cx import BLEConnection
|
|
9
|
+
from .tcp_cx import TCPConnection
|
|
10
|
+
from .serial_cx import SerialConnection
|
|
9
11
|
|
|
10
12
|
# Setup default logger
|
|
11
13
|
logger = logging.getLogger("meshcore")
|
|
@@ -45,9 +47,7 @@ class MeshCore:
|
|
|
45
47
|
|
|
46
48
|
@classmethod
|
|
47
49
|
async def create_tcp(cls, host: str, port: int, debug: bool = False, default_timeout=None) -> 'MeshCore':
|
|
48
|
-
"""Create and connect a MeshCore instance using TCP connection"""
|
|
49
|
-
from .tcp_cx import TCPConnection
|
|
50
|
-
|
|
50
|
+
"""Create and connect a MeshCore instance using TCP connection"""
|
|
51
51
|
connection = TCPConnection(host, port)
|
|
52
52
|
await connection.connect()
|
|
53
53
|
|
|
@@ -58,9 +58,6 @@ class MeshCore:
|
|
|
58
58
|
@classmethod
|
|
59
59
|
async def create_serial(cls, port: str, baudrate: int = 115200, debug: bool = False, default_timeout=None) -> 'MeshCore':
|
|
60
60
|
"""Create and connect a MeshCore instance using serial connection"""
|
|
61
|
-
from .serial_cx import SerialConnection
|
|
62
|
-
import asyncio
|
|
63
|
-
|
|
64
61
|
connection = SerialConnection(port, baudrate)
|
|
65
62
|
await connection.connect()
|
|
66
63
|
await asyncio.sleep(0.1) # Time for transport to establish
|
|
@@ -75,7 +72,6 @@ class MeshCore:
|
|
|
75
72
|
|
|
76
73
|
If address is None, it will scan for and connect to the first available MeshCore device.
|
|
77
74
|
"""
|
|
78
|
-
from .ble_cx import BLEConnection
|
|
79
75
|
|
|
80
76
|
connection = BLEConnection(address)
|
|
81
77
|
result = await connection.connect()
|
|
@@ -91,7 +87,17 @@ class MeshCore:
|
|
|
91
87
|
return await self.commands.send_appstart()
|
|
92
88
|
|
|
93
89
|
async def disconnect(self):
|
|
90
|
+
"""Disconnect from the device and clean up resources."""
|
|
91
|
+
# First stop the dispatcher to prevent any new events
|
|
94
92
|
await self.dispatcher.stop()
|
|
93
|
+
|
|
94
|
+
# Stop auto message fetching if it's running
|
|
95
|
+
if hasattr(self, '_auto_fetch_subscription') and self._auto_fetch_subscription:
|
|
96
|
+
await self.stop_auto_message_fetching()
|
|
97
|
+
|
|
98
|
+
# Disconnect the connection object
|
|
99
|
+
if self.cx:
|
|
100
|
+
await self.cx.disconnect()
|
|
95
101
|
|
|
96
102
|
def stop(self):
|
|
97
103
|
"""Synchronously stop the event dispatcher task"""
|
|
@@ -99,7 +105,7 @@ class MeshCore:
|
|
|
99
105
|
self.dispatcher.running = False
|
|
100
106
|
self.dispatcher._task.cancel()
|
|
101
107
|
|
|
102
|
-
def subscribe(self, event_type: EventType, callback, attribute_filters: Optional[Dict[str, Any]] = None):
|
|
108
|
+
def subscribe(self, event_type: Union[EventType, None], callback, attribute_filters: Optional[Dict[str, Any]] = None):
|
|
103
109
|
"""
|
|
104
110
|
Subscribe to events using EventType enum with optional attribute filtering
|
|
105
111
|
|
|
@@ -256,14 +256,31 @@ class MessageReader:
|
|
|
256
256
|
await self.dispatcher.dispatch(Event(EventType.RAW_DATA, res))
|
|
257
257
|
|
|
258
258
|
elif packet_type_value == PacketType.LOGIN_SUCCESS.value:
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
259
|
+
res = {}
|
|
260
|
+
if len(data) > 1:
|
|
261
|
+
res["permissions"] = data[1]
|
|
262
|
+
res["is_admin"] = (data[1] & 1) == 1 # Check if admin bit is set
|
|
263
|
+
|
|
264
|
+
if len(data) > 7:
|
|
265
|
+
res["pubkey_prefix"] = data[2:8].hex()
|
|
266
|
+
|
|
267
|
+
attributes = {
|
|
268
|
+
"pubkey_prefix": res.get("pubkey_prefix")
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
await self.dispatcher.dispatch(Event(EventType.LOGIN_SUCCESS, res, attributes))
|
|
262
272
|
|
|
263
273
|
elif packet_type_value == PacketType.LOGIN_FAILED.value:
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
274
|
+
res = {}
|
|
275
|
+
|
|
276
|
+
if len(data) > 7:
|
|
277
|
+
res["pubkey_prefix"] = data[2:8].hex()
|
|
278
|
+
|
|
279
|
+
attributes = {
|
|
280
|
+
"pubkey_prefix": res.get("pubkey_prefix")
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
await self.dispatcher.dispatch(Event(EventType.LOGIN_FAILED, res, attributes))
|
|
267
284
|
|
|
268
285
|
elif packet_type_value == PacketType.STATUS_RESPONSE.value:
|
|
269
286
|
res = {}
|
|
@@ -382,7 +399,6 @@ class MessageReader:
|
|
|
382
399
|
|
|
383
400
|
res["pubkey_pre"] = data[2:8].hex()
|
|
384
401
|
buf = data[8:]
|
|
385
|
-
res["data"] = buf.hex()
|
|
386
402
|
|
|
387
403
|
"""Parse a given byte string and return as a LppFrame object."""
|
|
388
404
|
i = 0
|
|
@@ -86,4 +86,11 @@ class SerialConnection:
|
|
|
86
86
|
size = len(data)
|
|
87
87
|
pkt = b"\x3c" + size.to_bytes(2, byteorder="little") + data
|
|
88
88
|
logger.debug(f"sending pkt : {pkt}")
|
|
89
|
-
self.transport.write(pkt)
|
|
89
|
+
self.transport.write(pkt)
|
|
90
|
+
|
|
91
|
+
async def disconnect(self):
|
|
92
|
+
"""Close the serial connection."""
|
|
93
|
+
if self.transport:
|
|
94
|
+
self.transport.close()
|
|
95
|
+
self.transport = None
|
|
96
|
+
logger.debug("Serial Connection closed")
|
|
@@ -85,3 +85,10 @@ class TCPConnection:
|
|
|
85
85
|
pkt = b"\x3c" + size.to_bytes(2, byteorder="little") + data
|
|
86
86
|
logger.debug(f"sending pkt : {pkt}")
|
|
87
87
|
self.transport.write(pkt)
|
|
88
|
+
|
|
89
|
+
async def disconnect(self):
|
|
90
|
+
"""Close the TCP connection."""
|
|
91
|
+
if self.transport:
|
|
92
|
+
self.transport.close()
|
|
93
|
+
self.transport = None
|
|
94
|
+
logger.debug("TCP Connection closed")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|