Skip to content

Commit f223834

Browse files
authored
ftespnow (#1)
* ftespnow: Initial commit * ftespnow: Added function docstrings * ftespnow-server: Added JSON support, and write to dictionary functionality Added the receive_to_json() function, that supports exporting received data to a JSON file, and the receive_to_dict() function, that returns the received data as a dictionary * ftespnow: Fixed typo when importing ".client" extension in __init__.py * ftespnow: Added examples and updated docstrings * ftespnow: Moved manifests.py to the correct folder * ftespnow: Moved __init__.py to the correct folder * ftespnow: Fix .ftespnow/manifest.py. * ftespnow: Fix .ftespnow-client/manifest.py and .ftespnow-server/manifest.py, code formatting, and fixed spelling mistakes. ... Signed-off-by: Guilherme Schneck <guilhermeschneck@gmail.com> * ftespnow: Fix .ftespnow-client/manifest.py and .ftespnow-server/manifest.py, code formatting, and fixed spelling mistakes. * ftespnow: Fix code formatting errors. * ftespnow: Fix code formatting errors. --------- Signed-off-by: Guilherme Schneck <guilhermeschneck@gmail.com>
1 parent a1a9e57 commit f223834

9 files changed

Lines changed: 570 additions & 0 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
MANIFEST
22
__pycache__
3+
.vscode/
34
*.egg-info
45
*/dist/
56
*.org
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import ftespnow
2+
3+
# Initialize ESP-NOW client
4+
esp = ftespnow.CLIENT()
5+
6+
# Connect to ESP-NOW server
7+
esp.connect("a4f00f772d15") # Change to actual server mac address
8+
9+
# Send a message
10+
message = "Hello"
11+
sent = esp.send_message(message)
12+
if sent: # Check if server received the data
13+
print("Message received by server")
14+
else:
15+
print("Message not received by server")
16+
17+
# Receive a message
18+
received_data = esp.receive_message()
19+
if received_data is None: # Check if any data was received
20+
print("No message was received (timed out)")
21+
else:
22+
print(f"Here is the received data: {received_data}")
23+
24+
# Send a .txt file
25+
txt_sent = esp.send_txt("filepath/filename.txt")
26+
if txt_sent: # Check if server received the data
27+
print("File received by server")
28+
else:
29+
print("File not received by server")
30+
31+
# Send a .json file
32+
json_sent = esp.send_json("filepath/filename.json")
33+
if json_sent: # Check if server received the data
34+
print("File received by server")
35+
else:
36+
print("File not received by server")
37+
38+
# Write received data to .txt file
39+
txt_received = esp.receive_to_txt("filepath/filename.txt", mode='w') # Set mode to 'w' so file is truncated before writing
40+
if txt_received:
41+
print("File received successfully")
42+
else:
43+
print("No file received. Destination file was not created/modified")
44+
45+
# Write received data to .json file
46+
json_received = esp.receive_to_json("filepath/filename.json", mode='w') # Set mode to 'w' so file is truncated before writing
47+
if json_received:
48+
print("File received successfully")
49+
else:
50+
print("No file received. Destination file was not created/modified")
51+
52+
# Write received data to a python dictionary
53+
data_dict = esp.receive_to_dict()
54+
print(data_dict)
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import ftespnow
2+
3+
# Initialize ESP-NOW client
4+
esp = ftespnow.SERVER()
5+
6+
# Send a message
7+
message = "Hello"
8+
peer = "a4f00f772d15" # Mac address of the client that you want to send data to
9+
sent = esp.send_message(peer, message)
10+
if sent: # Check if client received the data
11+
print("Message received by clientclient")
12+
else:
13+
print("Message not received by client")
14+
15+
# Receive a message
16+
received_data = esp.receive_message()
17+
if received_data is None: # Check if any data was received
18+
print("No message was received (timed out)")
19+
else:
20+
print(f"Here is the received data: {received_data}")
21+
22+
# Send a .txt file
23+
txt_sent = esp.send_txt(peer, "filepath/filename.txt")
24+
if txt_sent: # Check if client received the data
25+
print("File received by client")
26+
else:
27+
print("File not received by client")
28+
29+
# Send a .json file
30+
json_sent = esp.send_json(peer, "filepath/filename.json")
31+
if json_sent: # Check if client received the data
32+
print("File received by client")
33+
else:
34+
print("File not received by client")
35+
36+
# Write received data to .txt file
37+
txt_received = esp.receive_to_txt("filepath/filename.txt", mode='w') # Set mode to 'w' so file is truncated before writing
38+
if txt_received:
39+
print("File received successfully")
40+
else:
41+
print("No file received. Destination file was not created/modified")
42+
43+
# Write received data to .json file
44+
json_received = esp.receive_to_json("filepath/filename.json", mode='w') # Set mode to 'w' so file is truncated before writing
45+
if json_received: # Check if any data was received
46+
print("File received successfully")
47+
else:
48+
print("No file received. Destination file was not created/modified")
49+
50+
# Write received data to a python dictionary
51+
data_dict = esp.receive_to_dict() # Will return {} if no data was received
52+
print(data_dict)
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
import espnow
2+
import json
3+
4+
class CLIENT:
5+
def __init__(self, *, timeout: int=5) -> None:
6+
self.esp = espnow.ESPNow()
7+
self.timeout = timeout
8+
9+
def configure(self, *, timeout: int=5) -> None:
10+
self.timeout: int = timeout
11+
12+
def connect(self, peer: str) -> None:
13+
self.peer: str = peer
14+
self.esp.active(True)
15+
self.esp.add_peer(self.peer)
16+
17+
def send_message(self, data: str) -> bool:
18+
"""
19+
Send a string
20+
21+
Args:
22+
23+
data (str): Data to be sent
24+
25+
Returns:
26+
27+
bool: Confirmation flag (`True` if data was received, `False` otherwise)
28+
"""
29+
30+
ack: bool = self.esp.send(self.peer, data)
31+
return ack
32+
33+
def receive_message(self, recv_timeout :int= 5) -> list | None:
34+
"""
35+
Receive a string
36+
37+
Args:
38+
39+
recv_timeout (int, optional): Reception timeout. Defaults to 5.
40+
41+
Returns:
42+
43+
list | None: `[<sender's mac address (str)>, <message (str)>]` | `None` if no message is received
44+
"""
45+
46+
received = self.esp.recv(recv_timeout)
47+
if received[0] is None:
48+
return
49+
return received
50+
51+
def send_txt(self, filename: str) -> bool:
52+
"""
53+
Parse and send a `.txt` file as a `string`
54+
55+
Args:
56+
57+
filename (str): Filepath of the desired file to be sent with file name and extension
58+
59+
Returns:
60+
61+
sent (bool): Confirmation flag (`True` if data was received, `False` otherwise)
62+
"""
63+
64+
with open(filename, 'r') as f:
65+
data: str = str(f.readlines())
66+
sent: bool = self.send_message(data)
67+
return sent
68+
69+
def send_json(self, filename: str, *, indent: int=4) -> bool:
70+
"""
71+
Parse and send a `.json` file as a `string`
72+
73+
Args:
74+
75+
filename (str): Filepath of the desired file to be sent with file name and extension
76+
77+
indent (int, optional): Desired indent of the resulting parsed `string` (for formatting purposes). Defaults to 4.
78+
79+
Returns:
80+
81+
sent (bool): Confirmation flag (`True` if data was received, `False` otherwise)
82+
"""
83+
84+
with open(filename, 'r') as f:
85+
unparsed = json.load(f)
86+
parsed: str = json.dumps(unparsed, indent=indent)
87+
sent: bool = self.send_message(parsed)
88+
return sent
89+
90+
def receive_to_txt(self, target_file: str, mode: str='a') -> bool:
91+
"""
92+
Write received `string` into a `.txt` file.
93+
94+
**Will not write or create file if no data is received**
95+
96+
Args:
97+
98+
target_file (str): Filepath of the destination file for the received data with file name and extension.
99+
100+
mode (str, optional): Editing mode
101+
102+
- `r` - Read only
103+
104+
- `w` - Write only (truncates file before writing)
105+
106+
- `x` - Create a new file and open it for writing (raises `FileExistsError` if file already exists)
107+
108+
- `a` - Append to the end of the file (default)
109+
110+
- `b` - Binary mode
111+
112+
- `t` - Text mode
113+
114+
- `+` - Update (read and write)
115+
116+
Read `open()`_ for more information
117+
118+
Returns:
119+
120+
received (bool): Confirmation flag (`True` if data was received, `False` otherwise)
121+
122+
.. _open(): https://docs.python.org/3/library/functions.html#open
123+
"""
124+
125+
if ".txt" not in target_file:
126+
raise SyntaxError("File format must be .txt")
127+
try:
128+
received: bool = False
129+
data: list | None = self.receive_message()
130+
if data is None:
131+
return received
132+
data_list: list[str] = str(data[-1]).split("\n")
133+
if data_list[-1] == "":
134+
data_list = data_list[:-1]
135+
with open(target_file, mode) as f:
136+
f.writelines(data_list)
137+
return not received
138+
except SyntaxError:
139+
raise
140+
141+
def receive_to_json(self, target_file: str, mode: str='a') -> bool:
142+
"""
143+
Write received `string` into a `.json` file.
144+
145+
**Will not write or create file if no data is received**
146+
147+
Args:
148+
149+
target_file (str): Filepath of the destination file for the received data with file name and extension.
150+
151+
mode (str, optional): Editing mode
152+
153+
- `r` - Read only
154+
155+
- `w` - Write only (truncates file before writing)
156+
157+
- `x` - Create a new file and open it for writing (raises `FileExistsError` if file already exists)
158+
159+
- `a` - Append to the end of the file (default)
160+
161+
- `b` - Binary mode
162+
163+
- `t` - Text mode
164+
165+
- `+` - Update (read and write)
166+
167+
Read `open()`_ for more information
168+
169+
Returns:
170+
171+
received (bool): Confirmation flag (`True` if data was received, `False` otherwise)
172+
173+
.. _open(): https://docs.python.org/3/library/functions.html#open
174+
"""
175+
176+
if ".json" not in target_file:
177+
raise SyntaxError("File format must be .json")
178+
try:
179+
received: bool = False
180+
data: list | None = self.receive_message()
181+
if data is None:
182+
return received
183+
mac: str = str(data[0])
184+
message = json.loads(str(data[-1]))
185+
unparsed: dict = {
186+
"mac": mac,
187+
"message": message
188+
}
189+
with open(target_file, mode) as f:
190+
json.dump(unparsed, f)
191+
return not received
192+
except SyntaxError:
193+
raise
194+
195+
def receive_to_dict(self) -> dict:
196+
"""
197+
Unparses received `string` into a `dict` object
198+
199+
Args:
200+
201+
None:
202+
203+
Returns:
204+
205+
unparsed (dict): `dictionary` object containing unparsed equivalent of the received `.json`
206+
"""
207+
208+
data: list | None = self.receive_message()
209+
if data is None:
210+
return {}
211+
mac: str = str(data[0])
212+
message = json.loads(str(data[-1]))
213+
unparsed: dict = {
214+
"mac": mac,
215+
"message": message
216+
}
217+
return unparsed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
metadata(
2+
description="Client-side commands",
3+
version="0.1.0",
4+
)
5+
6+
require("ftespnow")
7+
package("ftespnow")

0 commit comments

Comments
 (0)