meshcore 0.3.2__tar.gz → 0.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshcore
3
- Version: 0.3.2
3
+ Version: 0.4
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
@@ -18,5 +18,7 @@ Description-Content-Type: text/markdown
18
18
 
19
19
  Bindings to access your [MeshCore](https://meshcore.co.uk) companion radio nodes in python.
20
20
 
21
+ Can be installed via `pip` using `pip install meshcore`
22
+
21
23
  Used by [mccli](https://github.com/fdlamotte/mccli).
22
24
 
@@ -2,5 +2,7 @@
2
2
 
3
3
  Bindings to access your [MeshCore](https://meshcore.co.uk) companion radio nodes in python.
4
4
 
5
+ Can be installed via `pip` using `pip install meshcore`
6
+
5
7
  Used by [mccli](https://github.com/fdlamotte/mccli).
6
8
 
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/python
2
+
3
+ import asyncio
4
+
5
+ from meshcore import MeshCore
6
+ from meshcore import BLEConnection
7
+
8
+ ADDRESS = "t1000"
9
+
10
+ async def main () :
11
+ con = BLEConnection(ADDRESS)
12
+ await con.connect()
13
+ mc = MeshCore(con)
14
+ await mc.connect()
15
+
16
+ print(mc.self_info)
17
+
18
+ asyncio.run(main())
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/python
2
+
3
+ import asyncio
4
+ import json
5
+ from meshcore import MeshCore
6
+ from meshcore import BLEConnection
7
+
8
+ ADDRESS = "t1000" # node ble adress or name
9
+ DEST = "mchome"
10
+ MSG = "Hello World"
11
+
12
+ async def main () :
13
+ con = BLEConnection(ADDRESS)
14
+ await con.connect()
15
+ mc = MeshCore(con)
16
+ await mc.connect()
17
+
18
+ await mc.ensure_contacts()
19
+ await mc.send_msg(bytes.fromhex(mc.contacts[DEST]["public_key"])[0:6],MSG)
20
+
21
+ asyncio.run(main())
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/python
2
+ DISPLAYNAME="Center at MC node location"
3
+
4
+ import asyncio
5
+
6
+ from meshcore import MeshCore
7
+ from meshcore import BLEConnection
8
+
9
+ ADDRESS = "t1000"
10
+
11
+ async def main () :
12
+ con = BLEConnection(ADDRESS)
13
+ await con.connect()
14
+ mc = MeshCore(con)
15
+ await mc.connect()
16
+
17
+ infos = mc.self_info
18
+
19
+ lat=infos["adv_lat"]
20
+ lon=infos["adv_lon"]
21
+
22
+ print('[{"cmd":"prefset_n","args":{"pref":"lat","value":' + str(lat) + '}},')
23
+ print('{"cmd":"prefset_n","args":{"pref":"lon","value":' + str(lon) + '}}]')
24
+
25
+ asyncio.run(main())
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/python
2
+
3
+ import asyncio
4
+ import json
5
+ from meshcore import MeshCore
6
+ from meshcore import SerialConnection
7
+
8
+ PORT = "/dev/ttyUSB0"
9
+ BAUDRATE = 115200
10
+
11
+ async def main () :
12
+ con = SerialConnection(PORT, BAUDRATE)
13
+ await con.connect()
14
+ await asyncio.sleep(0.1)
15
+ mc = MeshCore(con)
16
+ await mc.connect()
17
+
18
+ print(json.dumps(await mc.get_contacts(),indent=4))
19
+
20
+ asyncio.run(main())
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/python
2
+
3
+ import asyncio
4
+
5
+ from meshcore import MeshCore
6
+ from meshcore import SerialConnection
7
+
8
+ PORT = "/dev/ttyUSB0"
9
+ BAUDRATE = 115200
10
+
11
+ async def main () :
12
+ con = SerialConnection(PORT, BAUDRATE)
13
+ await con.connect()
14
+ await asyncio.sleep(0.1) # time for transport to establish
15
+
16
+ mc = MeshCore(con)
17
+ await mc.connect()
18
+
19
+ print(mc.self_info)
20
+
21
+ asyncio.run(main())
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/python
2
+
3
+ import asyncio
4
+ import json
5
+ from meshcore import MeshCore
6
+ from meshcore import SerialConnection
7
+
8
+ PORT = "/dev/ttyUSB0"
9
+ BAUDRATE = 115200
10
+ DEST = "mchome"
11
+ MSG = "hello from serial"
12
+
13
+ async def main () :
14
+ con = SerialConnection(PORT, BAUDRATE)
15
+ await con.connect()
16
+ await asyncio.sleep(0.1) # time for transport to establish
17
+
18
+ mc = MeshCore(con)
19
+ await mc.connect()
20
+
21
+ await mc.ensure_contacts()
22
+ await mc.send_msg(bytes.fromhex(mc.contacts[DEST]["public_key"])[0:6],MSG)
23
+
24
+ asyncio.run(main())
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/python
2
+
3
+ import asyncio
4
+
5
+ from meshcore import MeshCore
6
+ from meshcore import printerr
7
+ from meshcore import SerialConnection
8
+
9
+ PORT = "/dev/ttyUSB0"
10
+ BAUDRATE = 115200
11
+
12
+ REPEATER="FdlRoom"
13
+ PASSWORD="password"
14
+
15
+ async def main () :
16
+ con = SerialConnection(PORT, BAUDRATE)
17
+ await con.connect()
18
+ await asyncio.sleep(0.1) # time for transport to establish
19
+
20
+ mc = MeshCore(con)
21
+ await mc.connect()
22
+
23
+ contacts = await mc.get_contacts()
24
+ repeater = contacts[REPEATER]
25
+ await mc.send_login(bytes.fromhex(repeater["public_key"]), PASSWORD)
26
+
27
+ printerr("Login sent ... awaiting")
28
+
29
+ if await mc.wait_login() :
30
+ await mc.send_statusreq(bytes.fromhex(repeater["public_key"]))
31
+ print(await mc.wait_status())
32
+
33
+ asyncio.run(main())
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/python
2
+
3
+ import asyncio
4
+ import json
5
+ from meshcore import TCPConnection
6
+ from meshcore import MeshCore
7
+
8
+ HOSTNAME = "mchome"
9
+ PORT = 5000
10
+
11
+ async def main () :
12
+ con = TCPConnection(HOSTNAME, PORT)
13
+ await con.connect()
14
+ mc = MeshCore(con)
15
+ await mc.connect()
16
+
17
+ print(json.dumps(await mc.get_contacts(),indent=4))
18
+ asyncio.run(main())
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/python
2
+
3
+ import asyncio
4
+
5
+ from meshcore import MeshCore
6
+ from meshcore import TCPConnection
7
+
8
+ HOSTNAME = "mchome"
9
+ PORT = 5000
10
+
11
+ async def main () :
12
+ con = TCPConnection(HOSTNAME, PORT)
13
+ await con.connect()
14
+ mc = MeshCore(con)
15
+ await mc.connect()
16
+
17
+ print(mc.self_info)
18
+
19
+ asyncio.run(main())
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/python
2
+
3
+ import asyncio
4
+ import json
5
+ from meshcore import MeshCore
6
+ from meshcore import TCPConnection
7
+
8
+ HOSTNAME = "mchome"
9
+ PORT = 5000
10
+ DEST = "t1000"
11
+ MSG = "Hello World"
12
+
13
+ async def main () :
14
+ con = TCPConnection(HOSTNAME, PORT)
15
+ await con.connect()
16
+ mc = MeshCore(con)
17
+ await mc.connect()
18
+
19
+ await mc.ensure_contacts()
20
+ await mc.send_msg(bytes.fromhex(mc.contacts[DEST]["public_key"])[0:6],MSG)
21
+
22
+ asyncio.run(main())
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/python
2
+
3
+ import asyncio
4
+ import json
5
+ from meshcore import TCPConnection
6
+ from meshcore import MeshCore
7
+
8
+ HOSTNAME = "mchome"
9
+ PORT = 5000
10
+ DEST = "t1000"
11
+ MSG = "Hello World"
12
+
13
+ async def main () :
14
+ con = TCPConnection(HOSTNAME, PORT)
15
+ await con.connect()
16
+ mc = MeshCore(con)
17
+ await mc.connect()
18
+
19
+ res = True
20
+ while res:
21
+ res = await mc.get_msg()
22
+ if res :
23
+ print (res)
24
+
25
+ asyncio.run(main())
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "meshcore"
7
- version = "0.3.2"
7
+ version = "0.4"
8
8
  authors = [
9
9
  { name="Florent de Lamotte", email="florent@frizoncorrea.fr" },
10
10
  ]
@@ -0,0 +1,5 @@
1
+ from meshcore.meshcore import printerr
2
+ from meshcore.meshcore import MeshCore
3
+ from meshcore.tcp_cx import TCPConnection
4
+ from meshcore.ble_cx import BLEConnection
5
+ from meshcore.serial_cx import SerialConnection
@@ -0,0 +1,83 @@
1
+ """
2
+ mccli.py : CLI interface to MeschCore BLE companion app
3
+ """
4
+ import asyncio
5
+ import sys
6
+
7
+ from meshcore import printerr
8
+
9
+ from bleak import BleakClient, BleakScanner
10
+ from bleak.backends.characteristic import BleakGATTCharacteristic
11
+ from bleak.backends.device import BLEDevice
12
+ from bleak.backends.scanner import AdvertisementData
13
+ from bleak.exc import BleakDeviceNotFoundError
14
+
15
+ UART_SERVICE_UUID = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
16
+ UART_RX_CHAR_UUID = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
17
+ UART_TX_CHAR_UUID = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
18
+
19
+ class BLEConnection:
20
+ def __init__(self, address):
21
+ """ Constructor : specify address """
22
+ self.address = address
23
+ self.client = None
24
+ self.rx_char = None
25
+ self.mc = None
26
+
27
+ async def connect(self):
28
+ """
29
+ Connects to the device
30
+
31
+ Returns : the address used for connection
32
+ """
33
+ def match_meshcore_device(_: BLEDevice, adv: AdvertisementData):
34
+ """ Filter to mach MeshCore devices """
35
+ if not adv.local_name is None\
36
+ and adv.local_name.startswith("MeshCore")\
37
+ and (self.address is None or self.address in adv.local_name) :
38
+ return True
39
+ return False
40
+
41
+ if self.address is None or self.address == "" or len(self.address.split(":")) != 6 :
42
+ scanner = BleakScanner()
43
+ printerr("Scanning for devices")
44
+ device = await scanner.find_device_by_filter(match_meshcore_device)
45
+ if device is None :
46
+ return None
47
+ printerr(f"Found device : {device}")
48
+ self.client = BleakClient(device)
49
+ self.address = self.client.address
50
+ else:
51
+ self.client = BleakClient(self.address)
52
+
53
+ try:
54
+ await self.client.connect(disconnected_callback=self.handle_disconnect)
55
+ except BleakDeviceNotFoundError:
56
+ return None
57
+ except TimeoutError:
58
+ return None
59
+
60
+ await self.client.start_notify(UART_TX_CHAR_UUID, self.handle_rx)
61
+
62
+ nus = self.client.services.get_service(UART_SERVICE_UUID)
63
+ self.rx_char = nus.get_characteristic(UART_RX_CHAR_UUID)
64
+
65
+ printerr("BLE Connexion started")
66
+ return self.address
67
+
68
+ def handle_disconnect(self, _: BleakClient):
69
+ """ Callback to handle disconnection """
70
+ printerr ("Device was disconnected, goodbye.")
71
+ # cancelling all tasks effectively ends the program
72
+ for task in asyncio.all_tasks():
73
+ task.cancel()
74
+
75
+ def set_mc(self, mc) :
76
+ self.mc = mc
77
+
78
+ def handle_rx(self, _: BleakGATTCharacteristic, data: bytearray):
79
+ if not self.mc is None:
80
+ self.mc.handle_rx(data)
81
+
82
+ async def send(self, data):
83
+ await self.client.write_gatt_char(self.rx_char, bytes(data), response=False)
@@ -3,235 +3,12 @@
3
3
  """
4
4
  import asyncio
5
5
  import sys
6
- import serial_asyncio
7
-
8
- from bleak import BleakClient, BleakScanner
9
- from bleak.backends.characteristic import BleakGATTCharacteristic
10
- from bleak.backends.device import BLEDevice
11
- from bleak.backends.scanner import AdvertisementData
12
- from bleak.exc import BleakDeviceNotFoundError
13
-
14
- UART_SERVICE_UUID = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"
15
- UART_RX_CHAR_UUID = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
16
- UART_TX_CHAR_UUID = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
17
6
 
18
7
  def printerr (s) :
19
8
  sys.stderr.write(str(s))
20
9
  sys.stderr.write("\n")
21
10
  sys.stderr.flush()
22
11
 
23
- class SerialConnection:
24
- def __init__(self, port, baudrate):
25
- self.port = port
26
- self.baudrate = baudrate
27
- self.frame_started = False
28
- self.frame_size = 0
29
- self.header = b""
30
- self.inframe = b""
31
-
32
- class MCSerialClientProtocol(asyncio.Protocol):
33
- def __init__(self, cx):
34
- self.cx = cx
35
-
36
- def connection_made(self, transport):
37
- self.cx.transport = transport
38
- # printerr('port opened')
39
- transport.serial.rts = False # You can manipulate Serial object via transport
40
-
41
- def data_received(self, data):
42
- # printerr('data received')
43
- self.cx.handle_rx(data)
44
-
45
- def connection_lost(self, exc):
46
- printerr('port closed')
47
-
48
- def pause_writing(self):
49
- printerr('pause writing')
50
-
51
- def resume_writing(self):
52
- printerr('resume writing')
53
-
54
- async def connect(self):
55
- """
56
- Connects to the device
57
- """
58
- loop = asyncio.get_running_loop()
59
- await serial_asyncio.create_serial_connection(
60
- loop, lambda: self.MCSerialClientProtocol(self),
61
- self.port, baudrate=self.baudrate)
62
-
63
- printerr("Serial Connexion started")
64
- return self.port
65
-
66
- def set_mc(self, mc) :
67
- self.mc = mc
68
-
69
- def handle_rx(self, data: bytearray):
70
- headerlen = len(self.header)
71
- framelen = len(self.inframe)
72
- if not self.frame_started : # wait start of frame
73
- if len(data) >= 3 - headerlen:
74
- self.header = self.header + data[:3-headerlen]
75
- self.frame_started = True
76
- self.frame_size = int.from_bytes(self.header[1:], byteorder='little')
77
- self.handle_rx(data[3-headerlen:])
78
- else:
79
- self.header = self.header + data
80
- else:
81
- if framelen + len(data) < self.frame_size:
82
- self.inframe = self.inframe + data
83
- else:
84
- self.inframe = self.inframe + data[:self.frame_size-framelen]
85
- if not self.mc is None:
86
- self.mc.handle_rx(self.inframe)
87
- self.frame_started = False
88
- self.header = b""
89
- self.inframe = b""
90
- if framelen + len(data) > self.frame_size:
91
- self.handle_rx(data[self.frame_size-framelen:])
92
-
93
- async def send(self, data):
94
- size = len(data)
95
- pkt = b"\x3c" + size.to_bytes(2, byteorder="little") + data
96
- # printerr(f"sending pkt : {pkt}")
97
- self.transport.write(pkt)
98
-
99
- class TCPConnection:
100
- def __init__(self, host, port):
101
- self.host = host
102
- self.port = port
103
- self.transport = None
104
- self.frame_started = False
105
- self.frame_size = 0
106
- self.header = b""
107
- self.inframe = b""
108
-
109
- class MCClientProtocol:
110
- def __init__(self, cx):
111
- self.cx = cx
112
-
113
- def connection_made(self, transport):
114
- self.cx.transport = transport
115
-
116
- def data_received(self, data):
117
- self.cx.handle_rx(data)
118
-
119
- def error_received(self, exc):
120
- printerr(f'Error received: {exc}')
121
-
122
- def connection_lost(self, exc):
123
- printerr('The server closed the connection')
124
-
125
- async def connect(self):
126
- """
127
- Connects to the device
128
- """
129
- loop = asyncio.get_running_loop()
130
- await loop.create_connection(
131
- lambda: self.MCClientProtocol(self),
132
- self.host, self.port)
133
-
134
- printerr("TCP Connexion started")
135
- return self.host
136
-
137
- def set_mc(self, mc) :
138
- self.mc = mc
139
-
140
- def handle_rx(self, data: bytearray):
141
- headerlen = len(self.header)
142
- framelen = len(self.inframe)
143
- if not self.frame_started : # wait start of frame
144
- if len(data) >= 3 - headerlen:
145
- self.header = self.header + data[:3-headerlen]
146
- self.frame_started = True
147
- self.frame_size = int.from_bytes(self.header[1:], byteorder='little')
148
- self.handle_rx(data[3-headerlen:])
149
- else:
150
- self.header = self.header + data
151
- else:
152
- if framelen + len(data) < self.frame_size:
153
- self.inframe = self.inframe + data
154
- else:
155
- self.inframe = self.inframe + data[:self.frame_size-framelen]
156
- if not self.mc is None:
157
- self.mc.handle_rx(self.inframe)
158
- self.frame_started = False
159
- self.header = b""
160
- self.inframe = b""
161
- if framelen + len(data) > self.frame_size:
162
- self.handle_rx(data[self.frame_size-framelen:])
163
-
164
- async def send(self, data):
165
- size = len(data)
166
- pkt = b"\x3c" + size.to_bytes(2, byteorder="little") + data
167
- self.transport.write(pkt)
168
-
169
- class BLEConnection:
170
- def __init__(self, address):
171
- """ Constructor : specify address """
172
- self.address = address
173
- self.client = None
174
- self.rx_char = None
175
- self.mc = None
176
-
177
- async def connect(self):
178
- """
179
- Connects to the device
180
-
181
- Returns : the address used for connection
182
- """
183
- def match_meshcore_device(_: BLEDevice, adv: AdvertisementData):
184
- """ Filter to mach MeshCore devices """
185
- if not adv.local_name is None\
186
- and adv.local_name.startswith("MeshCore")\
187
- and (self.address is None or self.address in adv.local_name) :
188
- return True
189
- return False
190
-
191
- if self.address is None or self.address == "" or len(self.address.split(":")) != 6 :
192
- scanner = BleakScanner()
193
- printerr("Scanning for devices")
194
- device = await scanner.find_device_by_filter(match_meshcore_device)
195
- if device is None :
196
- return None
197
- printerr(f"Found device : {device}")
198
- self.client = BleakClient(device)
199
- self.address = self.client.address
200
- else:
201
- self.client = BleakClient(self.address)
202
-
203
- try:
204
- await self.client.connect(disconnected_callback=self.handle_disconnect)
205
- except BleakDeviceNotFoundError:
206
- return None
207
- except TimeoutError:
208
- return None
209
-
210
- await self.client.start_notify(UART_TX_CHAR_UUID, self.handle_rx)
211
-
212
- nus = self.client.services.get_service(UART_SERVICE_UUID)
213
- self.rx_char = nus.get_characteristic(UART_RX_CHAR_UUID)
214
-
215
- printerr("BLE Connexion started")
216
- return self.address
217
-
218
- def handle_disconnect(self, _: BleakClient):
219
- """ Callback to handle disconnection """
220
- printerr ("Device was disconnected, goodbye.")
221
- # cancelling all tasks effectively ends the program
222
- for task in asyncio.all_tasks():
223
- task.cancel()
224
-
225
- def set_mc(self, mc) :
226
- self.mc = mc
227
-
228
- def handle_rx(self, _: BleakGATTCharacteristic, data: bytearray):
229
- if not self.mc is None:
230
- self.mc.handle_rx(data)
231
-
232
- async def send(self, data):
233
- await self.client.write_gatt_char(self.rx_char, bytes(data), response=False)
234
-
235
12
  class MeshCore:
236
13
  """
237
14
  Interface to a BLE MeshCore device
@@ -364,7 +141,7 @@ class MeshCore:
364
141
  case 11: # contact
365
142
  self.result.set_result("meshcore://" + data[1:].hex())
366
143
  case 12: # battery voltage
367
- self.result.set_result(int.from_bytes(data[1:2], byteorder='little'))
144
+ self.result.set_result(int.from_bytes(data[1:3], byteorder='little'))
368
145
  case 13: # device info
369
146
  res = {}
370
147
  res["fw ver"] = data[1]
@@ -0,0 +1,84 @@
1
+ """
2
+ mccli.py : CLI interface to MeschCore BLE companion app
3
+ """
4
+ import asyncio
5
+ import sys
6
+ import serial_asyncio
7
+
8
+ from meshcore import printerr
9
+
10
+ class SerialConnection:
11
+ def __init__(self, port, baudrate):
12
+ self.port = port
13
+ self.baudrate = baudrate
14
+ self.frame_started = False
15
+ self.frame_size = 0
16
+ self.header = b""
17
+ self.inframe = b""
18
+
19
+ class MCSerialClientProtocol(asyncio.Protocol):
20
+ def __init__(self, cx):
21
+ self.cx = cx
22
+
23
+ def connection_made(self, transport):
24
+ self.cx.transport = transport
25
+ # printerr('port opened')
26
+ transport.serial.rts = False # You can manipulate Serial object via transport
27
+
28
+ def data_received(self, data):
29
+ # printerr('data received')
30
+ self.cx.handle_rx(data)
31
+
32
+ def connection_lost(self, exc):
33
+ printerr('port closed')
34
+
35
+ def pause_writing(self):
36
+ printerr('pause writing')
37
+
38
+ def resume_writing(self):
39
+ printerr('resume writing')
40
+
41
+ async def connect(self):
42
+ """
43
+ Connects to the device
44
+ """
45
+ loop = asyncio.get_running_loop()
46
+ await serial_asyncio.create_serial_connection(
47
+ loop, lambda: self.MCSerialClientProtocol(self),
48
+ self.port, baudrate=self.baudrate)
49
+
50
+ printerr("Serial Connexion started")
51
+ return self.port
52
+
53
+ def set_mc(self, mc) :
54
+ self.mc = mc
55
+
56
+ def handle_rx(self, data: bytearray):
57
+ headerlen = len(self.header)
58
+ framelen = len(self.inframe)
59
+ if not self.frame_started : # wait start of frame
60
+ if len(data) >= 3 - headerlen:
61
+ self.header = self.header + data[:3-headerlen]
62
+ self.frame_started = True
63
+ self.frame_size = int.from_bytes(self.header[1:], byteorder='little')
64
+ self.handle_rx(data[3-headerlen:])
65
+ else:
66
+ self.header = self.header + data
67
+ else:
68
+ if framelen + len(data) < self.frame_size:
69
+ self.inframe = self.inframe + data
70
+ else:
71
+ self.inframe = self.inframe + data[:self.frame_size-framelen]
72
+ if not self.mc is None:
73
+ self.mc.handle_rx(self.inframe)
74
+ self.frame_started = False
75
+ self.header = b""
76
+ self.inframe = b""
77
+ if framelen + len(data) > self.frame_size:
78
+ self.handle_rx(data[self.frame_size-framelen:])
79
+
80
+ async def send(self, data):
81
+ size = len(data)
82
+ pkt = b"\x3c" + size.to_bytes(2, byteorder="little") + data
83
+ # printerr(f"sending pkt : {pkt}")
84
+ self.transport.write(pkt)
@@ -0,0 +1,77 @@
1
+ """
2
+ mccli.py : CLI interface to MeschCore BLE companion app
3
+ """
4
+ import asyncio
5
+ import sys
6
+
7
+ from meshcore import printerr
8
+
9
+ class TCPConnection:
10
+ def __init__(self, host, port):
11
+ self.host = host
12
+ self.port = port
13
+ self.transport = None
14
+ self.frame_started = False
15
+ self.frame_size = 0
16
+ self.header = b""
17
+ self.inframe = b""
18
+
19
+ class MCClientProtocol:
20
+ def __init__(self, cx):
21
+ self.cx = cx
22
+
23
+ def connection_made(self, transport):
24
+ self.cx.transport = transport
25
+
26
+ def data_received(self, data):
27
+ self.cx.handle_rx(data)
28
+
29
+ def error_received(self, exc):
30
+ printerr(f'Error received: {exc}')
31
+
32
+ def connection_lost(self, exc):
33
+ printerr('The server closed the connection')
34
+
35
+ async def connect(self):
36
+ """
37
+ Connects to the device
38
+ """
39
+ loop = asyncio.get_running_loop()
40
+ await loop.create_connection(
41
+ lambda: self.MCClientProtocol(self),
42
+ self.host, self.port)
43
+
44
+ printerr("TCP Connexion started")
45
+ return self.host
46
+
47
+ def set_mc(self, mc) :
48
+ self.mc = mc
49
+
50
+ def handle_rx(self, data: bytearray):
51
+ headerlen = len(self.header)
52
+ framelen = len(self.inframe)
53
+ if not self.frame_started : # wait start of frame
54
+ if len(data) >= 3 - headerlen:
55
+ self.header = self.header + data[:3-headerlen]
56
+ self.frame_started = True
57
+ self.frame_size = int.from_bytes(self.header[1:], byteorder='little')
58
+ self.handle_rx(data[3-headerlen:])
59
+ else:
60
+ self.header = self.header + data
61
+ else:
62
+ if framelen + len(data) < self.frame_size:
63
+ self.inframe = self.inframe + data
64
+ else:
65
+ self.inframe = self.inframe + data[:self.frame_size-framelen]
66
+ if not self.mc is None:
67
+ self.mc.handle_rx(self.inframe)
68
+ self.frame_started = False
69
+ self.header = b""
70
+ self.inframe = b""
71
+ if framelen + len(data) > self.frame_size:
72
+ self.handle_rx(data[self.frame_size-framelen:])
73
+
74
+ async def send(self, data):
75
+ size = len(data)
76
+ pkt = b"\x3c" + size.to_bytes(2, byteorder="little") + data
77
+ self.transport.write(pkt)
@@ -1,5 +0,0 @@
1
- from meshcore.mclib import printerr
2
- from meshcore.mclib import MeshCore
3
- from meshcore.mclib import TCPConnection
4
- from meshcore.mclib import BLEConnection
5
- from meshcore.mclib import SerialConnection
File without changes