easyhttp-python 0.3.2__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.
- easyhttp_python-0.3.2/LICENSE +21 -0
- easyhttp_python-0.3.2/PKG-INFO +152 -0
- easyhttp_python-0.3.2/README.md +309 -0
- easyhttp_python-0.3.2/README_PY.md +117 -0
- easyhttp_python-0.3.2/easyhttp/__init__.py +9 -0
- easyhttp_python-0.3.2/easyhttp/core.py +517 -0
- easyhttp_python-0.3.2/easyhttp/wrapper.py +153 -0
- easyhttp_python-0.3.2/easyhttp_python.egg-info/PKG-INFO +152 -0
- easyhttp_python-0.3.2/easyhttp_python.egg-info/SOURCES.txt +12 -0
- easyhttp_python-0.3.2/easyhttp_python.egg-info/dependency_links.txt +1 -0
- easyhttp_python-0.3.2/easyhttp_python.egg-info/requires.txt +8 -0
- easyhttp_python-0.3.2/easyhttp_python.egg-info/top_level.txt +1 -0
- easyhttp_python-0.3.2/pyproject.toml +51 -0
- easyhttp_python-0.3.2/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 slpuk
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: easyhttp-python
|
|
3
|
+
Version: 0.3.2
|
|
4
|
+
Summary: Simple HTTP-based P2P framework for IoT
|
|
5
|
+
Author-email: slpuk <yarik6052@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/slpuk/easyhttp-python
|
|
8
|
+
Project-URL: Documentation, https://github.com/slpuk/easyhttp-python#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/slpuk/easyhttp-python
|
|
10
|
+
Project-URL: Issue Tracker, https://github.com/slpuk/easyhttp-python/issues
|
|
11
|
+
Keywords: iot,p2p,http,framework
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
15
|
+
Classifier: Topic :: Communications
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Requires-Python: >=3.7
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: fastapi>=0.103.2
|
|
28
|
+
Requires-Dist: uvicorn[standard]>=0.22.0
|
|
29
|
+
Requires-Dist: aiohttp>=3.7.0
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
32
|
+
Requires-Dist: black; extra == "dev"
|
|
33
|
+
Requires-Dist: flake8; extra == "dev"
|
|
34
|
+
Dynamic: license-file
|
|
35
|
+
|
|
36
|
+
# EasyHTTP
|
|
37
|
+
|
|
38
|
+
[](https://github.com/slpuk/easyhttp-python)
|
|
39
|
+

|
|
40
|
+

|
|
41
|
+

|
|
42
|
+

|
|
43
|
+
|
|
44
|
+
> **A lightweight HTTP-based P2P framework for IoT and device-to-device communication**
|
|
45
|
+
|
|
46
|
+
## 🛠️ Changelog
|
|
47
|
+
- Added context managers support
|
|
48
|
+
- Fixed some bugs
|
|
49
|
+
|
|
50
|
+
## 📖 About
|
|
51
|
+
|
|
52
|
+
**EasyHTTP** is a simple yet powerful framework with asynchronous core that enables P2P (peer-to-peer) communication between devices using plain HTTP.
|
|
53
|
+
|
|
54
|
+
### Key Features:
|
|
55
|
+
- **🔄 P2P Architecture** - No central server required
|
|
56
|
+
- **🧩 Dual API:** `EasyHTTP` (synchronous) and `EasyHTTPAsync` (asynchronous) with the same methods
|
|
57
|
+
- **📡 Event-Driven Communication** - Callback-based architecture
|
|
58
|
+
- **🆔 Human-Readable Device IDs** - Base32 identifiers instead of IP addresses
|
|
59
|
+
- **✅ Easy to Use** - Simple API with minimal setup
|
|
60
|
+
- **🚀 Performance** - Asynchronous code and lightweight libraries(FastAPI/aiohttp)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
## 🏗️ Architecture
|
|
64
|
+
|
|
65
|
+
### Device Identification
|
|
66
|
+
Instead of using hard-to-remember IP addresses, each device in the EasyHTTP network has a unique 6-character identifier:
|
|
67
|
+
|
|
68
|
+
- **Format**: 6 characters from Base32 alphabet (without ambiguous characters)
|
|
69
|
+
- **Alphabet**: `23456789ABCDEFGHJKLMNPQRSTUVWXYZ`
|
|
70
|
+
- **Examples**: `7H8G2K`, `AB3F9Z`, `X4R7T2`
|
|
71
|
+
- **Generation**: Randomly generated on first boot, stored in device configuration
|
|
72
|
+
|
|
73
|
+
### Command System
|
|
74
|
+
EasyHTTP uses a simple JSON-based command system:
|
|
75
|
+
|
|
76
|
+
| Command | Value | Description |
|
|
77
|
+
|---------|-------|-------------|
|
|
78
|
+
| `PING` | 1 | Check if another device is reachable |
|
|
79
|
+
| `PONG` | 2 | Response to ping request |
|
|
80
|
+
| `FETCH` | 3 | Request data from a device |
|
|
81
|
+
| `DATA` | 4 | Send data or answer to FETCH |
|
|
82
|
+
| `PUSH` | 5 | Request to write/execute on remote device |
|
|
83
|
+
| `ACK` | 6 | Success/confirmation |
|
|
84
|
+
| `NACK` | 7 | Error/reject |
|
|
85
|
+
|
|
86
|
+
### Basic Example with Callbacks (synchronous)
|
|
87
|
+
```python
|
|
88
|
+
import time
|
|
89
|
+
from easyhttp import EasyHTTP
|
|
90
|
+
|
|
91
|
+
# Callback function
|
|
92
|
+
def handle_data(sender_id, data, timestamp):
|
|
93
|
+
# Callback for incoming DATA responses
|
|
94
|
+
print(f"From {sender_id}: {data}")
|
|
95
|
+
|
|
96
|
+
def handle_fetch(sender_id, query, timestamp):
|
|
97
|
+
# Callback for FETCH requests - returns data when someone requests it
|
|
98
|
+
print(f"FETCH request from {sender_id}")
|
|
99
|
+
return {
|
|
100
|
+
"temperature": 23.5,
|
|
101
|
+
"humidity": 45,
|
|
102
|
+
"status": "normal",
|
|
103
|
+
"timestamp": timestamp
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
def handle_push(sender_id, data, timestamp):
|
|
107
|
+
# Callback for PUSH requests - handle control commands
|
|
108
|
+
print(f"Control from {sender_id}: {data}")
|
|
109
|
+
if data and data.get("command") == "led":
|
|
110
|
+
state = data.get("state", "off")
|
|
111
|
+
print(f"[CONTROL] Turning LED {state}")
|
|
112
|
+
# Here you can add real GPIO control
|
|
113
|
+
return True # Successful → ACK
|
|
114
|
+
return False # Error → NACK
|
|
115
|
+
|
|
116
|
+
def main():
|
|
117
|
+
# Initializing EasyHTTP - sync wrapper of EasyHTTPAsync
|
|
118
|
+
easy = EasyHTTP(debug=True, port=5000)
|
|
119
|
+
|
|
120
|
+
# Setting up callback functions
|
|
121
|
+
easy.on('on_ping', handle_ping)
|
|
122
|
+
easy.on('on_pong', handle_pong)
|
|
123
|
+
easy.on('on_fetch', handle_fetch)
|
|
124
|
+
easy.on('on_data', handle_data)
|
|
125
|
+
easy.on('on_push', handle_push)
|
|
126
|
+
|
|
127
|
+
easy.start() # Starting server
|
|
128
|
+
print(f"Device {easy.id} is running on port 5000!")
|
|
129
|
+
|
|
130
|
+
# Adding device
|
|
131
|
+
easy.add("ABC123", "192.168.1.100", 5000)
|
|
132
|
+
print("Added device ABC123")
|
|
133
|
+
|
|
134
|
+
# Monitoring device's status
|
|
135
|
+
try:
|
|
136
|
+
while True:
|
|
137
|
+
if easy.ping("ABC123"):
|
|
138
|
+
print("Device ABC123 is online")
|
|
139
|
+
else:
|
|
140
|
+
print("Device ABC123 is offline")
|
|
141
|
+
|
|
142
|
+
time.sleep(5)
|
|
143
|
+
|
|
144
|
+
except KeyboardInterrupt:
|
|
145
|
+
print("\nStopping device...")
|
|
146
|
+
easy.stop() # Stopping server
|
|
147
|
+
|
|
148
|
+
# Starting main process
|
|
149
|
+
if __name__ == "__main__":
|
|
150
|
+
main()
|
|
151
|
+
```
|
|
152
|
+
**More examples available on [GitHub](https://github.com/slpuk/easyhttp-python)**
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# EasyHTTP
|
|
2
|
+
[EN README](README.md) | [RU README](README_RU.md)
|
|
3
|
+
> **A lightweight HTTP-based P2P framework for IoT and device-to-device communication**
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+
|
|
10
|
+
> [!WARNING]
|
|
11
|
+
> **Breaking Changes from 0.2.0**
|
|
12
|
+
>
|
|
13
|
+
> ### API Changes
|
|
14
|
+
> | 0.2.0 | 0.3.2 | Notes |
|
|
15
|
+
> |--------|--------|-------|
|
|
16
|
+
> | `get()` | `fetch()` | Same functionality |
|
|
17
|
+
> | `pull()` | `push()` | Same functionality |
|
|
18
|
+
> | `'on_get'` | `'on_fetch'` | Callback name |
|
|
19
|
+
> | `'on_data_response'` | `'on_data'` | Callback name |
|
|
20
|
+
> | `'on_pull'` | `'on_push'` | Callback name |
|
|
21
|
+
>
|
|
22
|
+
> ### Migration Example
|
|
23
|
+
> ```python
|
|
24
|
+
> # 0.2.0 (OLD):
|
|
25
|
+
> easy = EasyHTTP()
|
|
26
|
+
> easy.get("ABC123")
|
|
27
|
+
> easy.pull("ABC123", data)
|
|
28
|
+
>
|
|
29
|
+
> # 0.3.2 (NEW):
|
|
30
|
+
> # Sync
|
|
31
|
+
> easy = EasyHTTP()
|
|
32
|
+
> easy.fetch("ABC123")
|
|
33
|
+
> easy.push("ABC123", data)
|
|
34
|
+
>
|
|
35
|
+
> # Async
|
|
36
|
+
> easy = EasyHTTPAsync() # Async!
|
|
37
|
+
> await easy.fetch("ABC123") # Await!
|
|
38
|
+
> await easy.push("ABC123", data)
|
|
39
|
+
> ```
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
## 🚀 Quick Start
|
|
43
|
+
|
|
44
|
+
### Installation
|
|
45
|
+
> [!NOTE]
|
|
46
|
+
> Both methods require **Git** to be installed.<br>
|
|
47
|
+
> PyPI upload is **preparing**
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
# Clone and install
|
|
51
|
+
git clone https://github.com/slpuk/easyhttp-python.git
|
|
52
|
+
cd easyhttp-python
|
|
53
|
+
pip install -e .
|
|
54
|
+
|
|
55
|
+
# Or directly from GitHub
|
|
56
|
+
pip install git+https://github.com/slpuk/easyhttp-python.git
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Basic Usage (synchronous)
|
|
60
|
+
Syntax with context managers and full code is supported
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
from easyhttp import EasyHTTP
|
|
64
|
+
|
|
65
|
+
def main():
|
|
66
|
+
# Initialize a device with context manager
|
|
67
|
+
with EasyHTTP(debug=True, port=5000) as easy:
|
|
68
|
+
print(f"Device ID: {easy.id}")
|
|
69
|
+
|
|
70
|
+
# Manually add another device
|
|
71
|
+
easy.add("ABC123", "192.168.1.100", 5000)
|
|
72
|
+
|
|
73
|
+
# Ping to check if device is online
|
|
74
|
+
if easy.ping("ABC123"):
|
|
75
|
+
print("Device is online!")
|
|
76
|
+
|
|
77
|
+
# Request data from device
|
|
78
|
+
response = easy.fetch("ABC123")
|
|
79
|
+
if response:
|
|
80
|
+
print(f"Received: {response.get('data')}")
|
|
81
|
+
|
|
82
|
+
# Push data to device
|
|
83
|
+
success = easy.push("ABC123", {"led": "on"})
|
|
84
|
+
if success:
|
|
85
|
+
print("Command executed successfully")
|
|
86
|
+
|
|
87
|
+
# Starting main process
|
|
88
|
+
if __name__ == "__main__":
|
|
89
|
+
main()
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Or asynchronous
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
import asyncio
|
|
96
|
+
from easyhttp import EasyHTTPAsync
|
|
97
|
+
|
|
98
|
+
async def main():
|
|
99
|
+
# Initialize a device
|
|
100
|
+
easy = EasyHTTPAsync(debug=True, port=5000)
|
|
101
|
+
await easy.start()
|
|
102
|
+
|
|
103
|
+
print(f"Device ID: {easy.id}")
|
|
104
|
+
|
|
105
|
+
# Manually add another device
|
|
106
|
+
easy.add("ABC123", "192.168.1.100", 5000)
|
|
107
|
+
|
|
108
|
+
# Ping to check if device is online
|
|
109
|
+
if await easy.ping("ABC123"):
|
|
110
|
+
print("Device is online!")
|
|
111
|
+
|
|
112
|
+
# Request data from device
|
|
113
|
+
response = await easy.fetch("ABC123")
|
|
114
|
+
if response:
|
|
115
|
+
print(f"Received: {response.get('data')}")
|
|
116
|
+
|
|
117
|
+
# Push data to device
|
|
118
|
+
success = await easy.push("ABC123", {"led": "on"})
|
|
119
|
+
if success:
|
|
120
|
+
print("Command executed successfully")
|
|
121
|
+
|
|
122
|
+
# Starting main process
|
|
123
|
+
if __name__ == "__main__":
|
|
124
|
+
asyncio.run(main())
|
|
125
|
+
```
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 📖 About
|
|
129
|
+
|
|
130
|
+
**EasyHTTP** is a simple yet powerful framework with asynchronous core that enables P2P (peer-to-peer) communication between devices using plain HTTP.
|
|
131
|
+
|
|
132
|
+
### Key Features:
|
|
133
|
+
- **🔄 P2P Architecture** - No central server required
|
|
134
|
+
- **🧩 Dual API:** `EasyHTTP` (synchronous) and `EasyHTTPAsync` (asynchronous) with the same methods
|
|
135
|
+
- **📡 Event-Driven Communication** - Callback-based architecture
|
|
136
|
+
- **🆔 Human-Readable Device IDs** - Base32 identifiers instead of IP addresses
|
|
137
|
+
- **✅ Easy to Use** - Simple API with minimal setup
|
|
138
|
+
- **🚀 Performance** - Asynchronous code and lightweight libraries(FastAPI/aiohttp)
|
|
139
|
+
|
|
140
|
+
## Project Structure
|
|
141
|
+
```
|
|
142
|
+
easyhttp-python/
|
|
143
|
+
├── docs/
|
|
144
|
+
│ ├── EasyHTTP.md # Sync API reference
|
|
145
|
+
│ └── EasyHTTPAsync.md # Async API reference
|
|
146
|
+
├── easyhttp/
|
|
147
|
+
│ ├── __init__.py
|
|
148
|
+
│ ├── core.py # Main framework file/core
|
|
149
|
+
│ └── wrapper.py # Synchronous wrapper
|
|
150
|
+
├── examples/
|
|
151
|
+
│ ├── async/ # Asynchronous examples
|
|
152
|
+
│ │ ├── basic_ping.py
|
|
153
|
+
│ │ ├── callback_preview.py
|
|
154
|
+
│ │ ├── device_control.py
|
|
155
|
+
│ │ ├── sensor_simulator.py
|
|
156
|
+
│ │ └── two_devices.py
|
|
157
|
+
│ └── sync/ # Synchronous examples
|
|
158
|
+
│ ├── basic_ping.py
|
|
159
|
+
│ ├── callback_preview.py
|
|
160
|
+
│ ├── device_control.py
|
|
161
|
+
│ ├── sensor_simulator.py
|
|
162
|
+
│ └── two_devices.py
|
|
163
|
+
├── .gitignore
|
|
164
|
+
├── LICENSE # MIT license
|
|
165
|
+
├── pyproject.toml # Project config
|
|
166
|
+
├── README_RU.md # Russian documentation
|
|
167
|
+
├── README.md # This file
|
|
168
|
+
└── requirements.txt # Project dependencies
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## 🏗️ Architecture
|
|
172
|
+
|
|
173
|
+
### Device Identification
|
|
174
|
+
Instead of using hard-to-remember IP addresses, each device in the EasyHTTP network has a unique 6-character identifier:
|
|
175
|
+
|
|
176
|
+
- **Format**: 6 characters from Base32 alphabet (without ambiguous characters)
|
|
177
|
+
- **Alphabet**: `23456789ABCDEFGHJKLMNPQRSTUVWXYZ`
|
|
178
|
+
- **Examples**: `7H8G2K`, `AB3F9Z`, `X4R7T2`
|
|
179
|
+
- **Generation**: Randomly generated on first boot, stored in device configuration
|
|
180
|
+
|
|
181
|
+
### Command System
|
|
182
|
+
EasyHTTP uses a simple JSON-based command system:
|
|
183
|
+
|
|
184
|
+
| Command | Value | Description |
|
|
185
|
+
|---------|-------|-------------|
|
|
186
|
+
| `PING` | 1 | Check if another device is reachable |
|
|
187
|
+
| `PONG` | 2 | Response to ping request |
|
|
188
|
+
| `FETCH` | 3 | Request data from a device |
|
|
189
|
+
| `DATA` | 4 | Send data or answer to FETCH |
|
|
190
|
+
| `PUSH` | 5 | Request to write/execute on remote device |
|
|
191
|
+
| `ACK` | 6 | Success/confirmation |
|
|
192
|
+
| `NACK` | 7 | Error/reject |
|
|
193
|
+
|
|
194
|
+
### Communication Flow
|
|
195
|
+
```mermaid
|
|
196
|
+
sequenceDiagram
|
|
197
|
+
participant DeviceA
|
|
198
|
+
participant DeviceB
|
|
199
|
+
|
|
200
|
+
DeviceA->>DeviceB: PING
|
|
201
|
+
DeviceB-->>DeviceA: PONG
|
|
202
|
+
|
|
203
|
+
DeviceA->>DeviceB: FETCH
|
|
204
|
+
DeviceB-->>DeviceA: DATA
|
|
205
|
+
|
|
206
|
+
DeviceA->>DeviceB: PUSH
|
|
207
|
+
DeviceB-->>DeviceA: ACK/NACK
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
## 📦 Installation & Setup
|
|
211
|
+
|
|
212
|
+
### Python Installation
|
|
213
|
+
> [!NOTE]
|
|
214
|
+
> Both methods require **Git** to be installed.<br>
|
|
215
|
+
> PyPI upload is **preparing**
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
# Install directly from GitHub
|
|
219
|
+
pip install git+https://github.com/slpuk/easyhttp-python.git
|
|
220
|
+
|
|
221
|
+
# Or install from source
|
|
222
|
+
git clone https://github.com/slpuk/easyhttp-python
|
|
223
|
+
cd easyhttp-python
|
|
224
|
+
pip install -e .
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Basic Example with Callbacks(Synchronous)
|
|
228
|
+
```python
|
|
229
|
+
import time
|
|
230
|
+
from easyhttp import EasyHTTP
|
|
231
|
+
|
|
232
|
+
# Callback function
|
|
233
|
+
def handle_data(sender_id, data, timestamp):
|
|
234
|
+
# Callback for incoming DATA responses
|
|
235
|
+
print(f"From {sender_id}: {data}")
|
|
236
|
+
|
|
237
|
+
def handle_fetch(sender_id, query, timestamp):
|
|
238
|
+
# Callback for FETCH requests - returns data when someone requests it
|
|
239
|
+
print(f"FETCH request from {sender_id}")
|
|
240
|
+
return {
|
|
241
|
+
"temperature": 23.5,
|
|
242
|
+
"humidity": 45,
|
|
243
|
+
"status": "normal",
|
|
244
|
+
"timestamp": timestamp
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
def handle_push(sender_id, data, timestamp):
|
|
248
|
+
# Callback for PUSH requests - handle control commands
|
|
249
|
+
print(f"Control from {sender_id}: {data}")
|
|
250
|
+
if data and data.get("command") == "led":
|
|
251
|
+
state = data.get("state", "off")
|
|
252
|
+
print(f"[CONTROL] Turning LED {state}")
|
|
253
|
+
# Here you can add real GPIO control
|
|
254
|
+
return True # Successful → ACK
|
|
255
|
+
return False # Error → NACK
|
|
256
|
+
|
|
257
|
+
def main():
|
|
258
|
+
# Initializing EasyHTTP - sync wrapper of EasyHTTPAsync
|
|
259
|
+
easy = EasyHTTP(debug=True, port=5000)
|
|
260
|
+
|
|
261
|
+
# Setting up callback functions
|
|
262
|
+
easy.on('on_ping', handle_ping)
|
|
263
|
+
easy.on('on_pong', handle_pong)
|
|
264
|
+
easy.on('on_fetch', handle_fetch)
|
|
265
|
+
easy.on('on_data', handle_data)
|
|
266
|
+
easy.on('on_push', handle_push)
|
|
267
|
+
|
|
268
|
+
easy.start() # Starting server
|
|
269
|
+
print(f"Device {easy.id} is running on port 5000!")
|
|
270
|
+
|
|
271
|
+
# Adding device
|
|
272
|
+
easy.add("ABC123", "192.168.1.100", 5000)
|
|
273
|
+
print("Added device ABC123")
|
|
274
|
+
|
|
275
|
+
# Monitoring device's status
|
|
276
|
+
try:
|
|
277
|
+
while True:
|
|
278
|
+
if easy.ping("ABC123"):
|
|
279
|
+
print("Device ABC123 is online")
|
|
280
|
+
else:
|
|
281
|
+
print("Device ABC123 is offline")
|
|
282
|
+
|
|
283
|
+
time.sleep(5)
|
|
284
|
+
|
|
285
|
+
except KeyboardInterrupt:
|
|
286
|
+
print("\nStopping device...")
|
|
287
|
+
easy.stop() # Stopping server
|
|
288
|
+
|
|
289
|
+
# Starting main process
|
|
290
|
+
if __name__ == "__main__":
|
|
291
|
+
main()
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## 📚 Examples
|
|
295
|
+
|
|
296
|
+
Check the [`examples/`](examples/) directory for more:
|
|
297
|
+
<br> (synchronous examples below; check [`examples/async/`](examples/async/) for asynchronous versions)
|
|
298
|
+
|
|
299
|
+
- [`basic_ping.py`](examples/sync/basic_ping.py) - Basic device communication using context manager
|
|
300
|
+
- [`callback_preview.py`](examples/sync/callback_preview.py) - Callback events demo
|
|
301
|
+
- [`two_devices.py`](examples/sync/two_devices.py) - Two devices exchanging data
|
|
302
|
+
- [`sensor_simulator.py`](examples/sync/sensor_simulator.py) - Simulated IoT sensor
|
|
303
|
+
- [`device_control.py`](examples/sync/device_control.py) - Remote device control
|
|
304
|
+
|
|
305
|
+
## 🔧 API Reference
|
|
306
|
+
|
|
307
|
+
Check the directories for functions documentation:
|
|
308
|
+
- Synchronous wrapper: [`docs/EasyHTTP.md`](docs/EasyHTTP.md)
|
|
309
|
+
- Asynchronous core: [`docs/EasyHTTPAsync.md`](docs/EasyHTTPAsync.md)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# EasyHTTP
|
|
2
|
+
|
|
3
|
+
[](https://github.com/slpuk/easyhttp-python)
|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
> **A lightweight HTTP-based P2P framework for IoT and device-to-device communication**
|
|
10
|
+
|
|
11
|
+
## 🛠️ Changelog
|
|
12
|
+
- Added context managers support
|
|
13
|
+
- Fixed some bugs
|
|
14
|
+
|
|
15
|
+
## 📖 About
|
|
16
|
+
|
|
17
|
+
**EasyHTTP** is a simple yet powerful framework with asynchronous core that enables P2P (peer-to-peer) communication between devices using plain HTTP.
|
|
18
|
+
|
|
19
|
+
### Key Features:
|
|
20
|
+
- **🔄 P2P Architecture** - No central server required
|
|
21
|
+
- **🧩 Dual API:** `EasyHTTP` (synchronous) and `EasyHTTPAsync` (asynchronous) with the same methods
|
|
22
|
+
- **📡 Event-Driven Communication** - Callback-based architecture
|
|
23
|
+
- **🆔 Human-Readable Device IDs** - Base32 identifiers instead of IP addresses
|
|
24
|
+
- **✅ Easy to Use** - Simple API with minimal setup
|
|
25
|
+
- **🚀 Performance** - Asynchronous code and lightweight libraries(FastAPI/aiohttp)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
## 🏗️ Architecture
|
|
29
|
+
|
|
30
|
+
### Device Identification
|
|
31
|
+
Instead of using hard-to-remember IP addresses, each device in the EasyHTTP network has a unique 6-character identifier:
|
|
32
|
+
|
|
33
|
+
- **Format**: 6 characters from Base32 alphabet (without ambiguous characters)
|
|
34
|
+
- **Alphabet**: `23456789ABCDEFGHJKLMNPQRSTUVWXYZ`
|
|
35
|
+
- **Examples**: `7H8G2K`, `AB3F9Z`, `X4R7T2`
|
|
36
|
+
- **Generation**: Randomly generated on first boot, stored in device configuration
|
|
37
|
+
|
|
38
|
+
### Command System
|
|
39
|
+
EasyHTTP uses a simple JSON-based command system:
|
|
40
|
+
|
|
41
|
+
| Command | Value | Description |
|
|
42
|
+
|---------|-------|-------------|
|
|
43
|
+
| `PING` | 1 | Check if another device is reachable |
|
|
44
|
+
| `PONG` | 2 | Response to ping request |
|
|
45
|
+
| `FETCH` | 3 | Request data from a device |
|
|
46
|
+
| `DATA` | 4 | Send data or answer to FETCH |
|
|
47
|
+
| `PUSH` | 5 | Request to write/execute on remote device |
|
|
48
|
+
| `ACK` | 6 | Success/confirmation |
|
|
49
|
+
| `NACK` | 7 | Error/reject |
|
|
50
|
+
|
|
51
|
+
### Basic Example with Callbacks (synchronous)
|
|
52
|
+
```python
|
|
53
|
+
import time
|
|
54
|
+
from easyhttp import EasyHTTP
|
|
55
|
+
|
|
56
|
+
# Callback function
|
|
57
|
+
def handle_data(sender_id, data, timestamp):
|
|
58
|
+
# Callback for incoming DATA responses
|
|
59
|
+
print(f"From {sender_id}: {data}")
|
|
60
|
+
|
|
61
|
+
def handle_fetch(sender_id, query, timestamp):
|
|
62
|
+
# Callback for FETCH requests - returns data when someone requests it
|
|
63
|
+
print(f"FETCH request from {sender_id}")
|
|
64
|
+
return {
|
|
65
|
+
"temperature": 23.5,
|
|
66
|
+
"humidity": 45,
|
|
67
|
+
"status": "normal",
|
|
68
|
+
"timestamp": timestamp
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
def handle_push(sender_id, data, timestamp):
|
|
72
|
+
# Callback for PUSH requests - handle control commands
|
|
73
|
+
print(f"Control from {sender_id}: {data}")
|
|
74
|
+
if data and data.get("command") == "led":
|
|
75
|
+
state = data.get("state", "off")
|
|
76
|
+
print(f"[CONTROL] Turning LED {state}")
|
|
77
|
+
# Here you can add real GPIO control
|
|
78
|
+
return True # Successful → ACK
|
|
79
|
+
return False # Error → NACK
|
|
80
|
+
|
|
81
|
+
def main():
|
|
82
|
+
# Initializing EasyHTTP - sync wrapper of EasyHTTPAsync
|
|
83
|
+
easy = EasyHTTP(debug=True, port=5000)
|
|
84
|
+
|
|
85
|
+
# Setting up callback functions
|
|
86
|
+
easy.on('on_ping', handle_ping)
|
|
87
|
+
easy.on('on_pong', handle_pong)
|
|
88
|
+
easy.on('on_fetch', handle_fetch)
|
|
89
|
+
easy.on('on_data', handle_data)
|
|
90
|
+
easy.on('on_push', handle_push)
|
|
91
|
+
|
|
92
|
+
easy.start() # Starting server
|
|
93
|
+
print(f"Device {easy.id} is running on port 5000!")
|
|
94
|
+
|
|
95
|
+
# Adding device
|
|
96
|
+
easy.add("ABC123", "192.168.1.100", 5000)
|
|
97
|
+
print("Added device ABC123")
|
|
98
|
+
|
|
99
|
+
# Monitoring device's status
|
|
100
|
+
try:
|
|
101
|
+
while True:
|
|
102
|
+
if easy.ping("ABC123"):
|
|
103
|
+
print("Device ABC123 is online")
|
|
104
|
+
else:
|
|
105
|
+
print("Device ABC123 is offline")
|
|
106
|
+
|
|
107
|
+
time.sleep(5)
|
|
108
|
+
|
|
109
|
+
except KeyboardInterrupt:
|
|
110
|
+
print("\nStopping device...")
|
|
111
|
+
easy.stop() # Stopping server
|
|
112
|
+
|
|
113
|
+
# Starting main process
|
|
114
|
+
if __name__ == "__main__":
|
|
115
|
+
main()
|
|
116
|
+
```
|
|
117
|
+
**More examples available on [GitHub](https://github.com/slpuk/easyhttp-python)**
|