openhop-core 1.1.1__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.
- openhop_core-1.1.1/LICENSE +21 -0
- openhop_core-1.1.1/MANIFEST.in +7 -0
- openhop_core-1.1.1/PKG-INFO +246 -0
- openhop_core-1.1.1/README.md +188 -0
- openhop_core-1.1.1/pyproject.toml +110 -0
- openhop_core-1.1.1/setup.cfg +4 -0
- openhop_core-1.1.1/src/openhop_core/__init__.py +37 -0
- openhop_core-1.1.1/src/openhop_core/companion/__init__.py +103 -0
- openhop_core-1.1.1/src/openhop_core/companion/binary_parsing.py +217 -0
- openhop_core-1.1.1/src/openhop_core/companion/channel_store.py +85 -0
- openhop_core-1.1.1/src/openhop_core/companion/companion_base.py +2369 -0
- openhop_core-1.1.1/src/openhop_core/companion/companion_bridge.py +369 -0
- openhop_core-1.1.1/src/openhop_core/companion/companion_radio.py +314 -0
- openhop_core-1.1.1/src/openhop_core/companion/constants.py +269 -0
- openhop_core-1.1.1/src/openhop_core/companion/contact_store.py +319 -0
- openhop_core-1.1.1/src/openhop_core/companion/frame_server.py +2131 -0
- openhop_core-1.1.1/src/openhop_core/companion/message_queue.py +66 -0
- openhop_core-1.1.1/src/openhop_core/companion/models.py +195 -0
- openhop_core-1.1.1/src/openhop_core/companion/path_cache.py +59 -0
- openhop_core-1.1.1/src/openhop_core/companion/stats_collector.py +59 -0
- openhop_core-1.1.1/src/openhop_core/companion/timing.py +103 -0
- openhop_core-1.1.1/src/openhop_core/hardware/__init__.py +85 -0
- openhop_core-1.1.1/src/openhop_core/hardware/base.py +33 -0
- openhop_core-1.1.1/src/openhop_core/hardware/ch341/__init__.py +6 -0
- openhop_core-1.1.1/src/openhop_core/hardware/ch341/ch341_async.py +398 -0
- openhop_core-1.1.1/src/openhop_core/hardware/ch341/ch341_gpio_manager.py +488 -0
- openhop_core-1.1.1/src/openhop_core/hardware/gpio_manager.py +743 -0
- openhop_core-1.1.1/src/openhop_core/hardware/kiss_modem_wrapper.py +2210 -0
- openhop_core-1.1.1/src/openhop_core/hardware/kiss_serial_wrapper.py +832 -0
- openhop_core-1.1.1/src/openhop_core/hardware/lora/LoRaRF/SX126x.py +1530 -0
- openhop_core-1.1.1/src/openhop_core/hardware/lora/LoRaRF/SX127x.py +1412 -0
- openhop_core-1.1.1/src/openhop_core/hardware/lora/LoRaRF/__init__.py +5 -0
- openhop_core-1.1.1/src/openhop_core/hardware/lora/LoRaRF/base.py +33 -0
- openhop_core-1.1.1/src/openhop_core/hardware/protocol_constants.py +152 -0
- openhop_core-1.1.1/src/openhop_core/hardware/signal_utils.py +27 -0
- openhop_core-1.1.1/src/openhop_core/hardware/sx1262_wrapper.py +1772 -0
- openhop_core-1.1.1/src/openhop_core/hardware/tcp_radio.py +1106 -0
- openhop_core-1.1.1/src/openhop_core/hardware/transports/__init__.py +15 -0
- openhop_core-1.1.1/src/openhop_core/hardware/transports/ch341_spi_transport.py +250 -0
- openhop_core-1.1.1/src/openhop_core/hardware/transports/spi_transport.py +90 -0
- openhop_core-1.1.1/src/openhop_core/hardware/transports/spidev_transport.py +154 -0
- openhop_core-1.1.1/src/openhop_core/hardware/usb_radio.py +1033 -0
- openhop_core-1.1.1/src/openhop_core/hardware/wsradio.py +199 -0
- openhop_core-1.1.1/src/openhop_core/node/__init__.py +39 -0
- openhop_core-1.1.1/src/openhop_core/node/dispatcher.py +784 -0
- openhop_core-1.1.1/src/openhop_core/node/events/__init__.py +12 -0
- openhop_core-1.1.1/src/openhop_core/node/events/event_service.py +96 -0
- openhop_core-1.1.1/src/openhop_core/node/events/events.py +30 -0
- openhop_core-1.1.1/src/openhop_core/node/handlers/__init__.py +38 -0
- openhop_core-1.1.1/src/openhop_core/node/handlers/ack.py +178 -0
- openhop_core-1.1.1/src/openhop_core/node/handlers/advert.py +173 -0
- openhop_core-1.1.1/src/openhop_core/node/handlers/anon_request.py +304 -0
- openhop_core-1.1.1/src/openhop_core/node/handlers/base.py +14 -0
- openhop_core-1.1.1/src/openhop_core/node/handlers/control.py +206 -0
- openhop_core-1.1.1/src/openhop_core/node/handlers/group_text.py +365 -0
- openhop_core-1.1.1/src/openhop_core/node/handlers/login_response.py +263 -0
- openhop_core-1.1.1/src/openhop_core/node/handlers/login_server.py +317 -0
- openhop_core-1.1.1/src/openhop_core/node/handlers/multipart.py +69 -0
- openhop_core-1.1.1/src/openhop_core/node/handlers/path.py +97 -0
- openhop_core-1.1.1/src/openhop_core/node/handlers/protocol_request.py +330 -0
- openhop_core-1.1.1/src/openhop_core/node/handlers/protocol_response.py +915 -0
- openhop_core-1.1.1/src/openhop_core/node/handlers/registry.py +105 -0
- openhop_core-1.1.1/src/openhop_core/node/handlers/text.py +306 -0
- openhop_core-1.1.1/src/openhop_core/node/handlers/trace.py +184 -0
- openhop_core-1.1.1/src/openhop_core/node/node.py +176 -0
- openhop_core-1.1.1/src/openhop_core/protocol/__init__.py +168 -0
- openhop_core-1.1.1/src/openhop_core/protocol/constants.py +121 -0
- openhop_core-1.1.1/src/openhop_core/protocol/crypto.py +124 -0
- openhop_core-1.1.1/src/openhop_core/protocol/identity.py +220 -0
- openhop_core-1.1.1/src/openhop_core/protocol/modem_identity.py +278 -0
- openhop_core-1.1.1/src/openhop_core/protocol/packet.py +602 -0
- openhop_core-1.1.1/src/openhop_core/protocol/packet_builder.py +1326 -0
- openhop_core-1.1.1/src/openhop_core/protocol/packet_filter.py +68 -0
- openhop_core-1.1.1/src/openhop_core/protocol/packet_utils.py +451 -0
- openhop_core-1.1.1/src/openhop_core/protocol/region_map.py +106 -0
- openhop_core-1.1.1/src/openhop_core/protocol/transport_keys.py +74 -0
- openhop_core-1.1.1/src/openhop_core/protocol/utils.py +199 -0
- openhop_core-1.1.1/src/openhop_core.egg-info/PKG-INFO +246 -0
- openhop_core-1.1.1/src/openhop_core.egg-info/SOURCES.txt +106 -0
- openhop_core-1.1.1/src/openhop_core.egg-info/dependency_links.txt +1 -0
- openhop_core-1.1.1/src/openhop_core.egg-info/requires.txt +38 -0
- openhop_core-1.1.1/src/openhop_core.egg-info/top_level.txt +1 -0
- openhop_core-1.1.1/tests/test_anon_request_handler.py +213 -0
- openhop_core-1.1.1/tests/test_basic.py +12 -0
- openhop_core-1.1.1/tests/test_companion_base.py +543 -0
- openhop_core-1.1.1/tests/test_companion_bridge.py +717 -0
- openhop_core-1.1.1/tests/test_companion_radio.py +435 -0
- openhop_core-1.1.1/tests/test_companion_regions.py +339 -0
- openhop_core-1.1.1/tests/test_companion_stores.py +472 -0
- openhop_core-1.1.1/tests/test_crypto.py +124 -0
- openhop_core-1.1.1/tests/test_dispatcher.py +905 -0
- openhop_core-1.1.1/tests/test_events.py +269 -0
- openhop_core-1.1.1/tests/test_frame_server.py +1164 -0
- openhop_core-1.1.1/tests/test_handlers.py +1278 -0
- openhop_core-1.1.1/tests/test_identity.py +87 -0
- openhop_core-1.1.1/tests/test_kiss_modem_wrapper.py +2122 -0
- openhop_core-1.1.1/tests/test_mesh_node.py +93 -0
- openhop_core-1.1.1/tests/test_modem_identity.py +265 -0
- openhop_core-1.1.1/tests/test_packet.py +320 -0
- openhop_core-1.1.1/tests/test_packet_builder.py +500 -0
- openhop_core-1.1.1/tests/test_packet_filter.py +154 -0
- openhop_core-1.1.1/tests/test_packet_path_and_hash.py +918 -0
- openhop_core-1.1.1/tests/test_packet_utils.py +349 -0
- openhop_core-1.1.1/tests/test_region_map.py +69 -0
- openhop_core-1.1.1/tests/test_sx1262_wrapper.py +46 -0
- openhop_core-1.1.1/tests/test_sx1262_wrapper_concurrency.py +2840 -0
- openhop_core-1.1.1/tests/test_timing.py +63 -0
- openhop_core-1.1.1/tests/test_transport_compat.py +202 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Lloyd Newton
|
|
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,246 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: openhop_core
|
|
3
|
+
Version: 1.1.1
|
|
4
|
+
Summary: A Python MeshCore library with SPI LoRa radio support
|
|
5
|
+
Author-email: Rightup <rightup@openhop.dev>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/pyMC-dev/openhop-core/
|
|
8
|
+
Project-URL: Documentation, https://rightup.github.io/pymc_dev/openhop-core
|
|
9
|
+
Project-URL: Repository, https://github.com/pyMC-dev/openhop-core.git
|
|
10
|
+
Project-URL: Issues, https://github.com/pyMC-dev/openhop-core/issues
|
|
11
|
+
Keywords: mesh,networking,lora,radio,iot,communication
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Communications
|
|
22
|
+
Classifier: Topic :: System :: Networking
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: pycryptodome>=3.23.0
|
|
27
|
+
Requires-Dist: PyNaCl>=1.5.0
|
|
28
|
+
Requires-Dist: pyyaml>=6.0.0
|
|
29
|
+
Provides-Extra: radio
|
|
30
|
+
Requires-Dist: pyserial>=3.5; extra == "radio"
|
|
31
|
+
Provides-Extra: hardware
|
|
32
|
+
Requires-Dist: python-periphery>=2.4.1; extra == "hardware"
|
|
33
|
+
Requires-Dist: spidev>=3.5; extra == "hardware"
|
|
34
|
+
Requires-Dist: pyserial>=3.5; extra == "hardware"
|
|
35
|
+
Requires-Dist: pyusb>=1.2.1; extra == "hardware"
|
|
36
|
+
Provides-Extra: gpiod
|
|
37
|
+
Requires-Dist: gpiod>=2.4.0; extra == "gpiod"
|
|
38
|
+
Provides-Extra: websocket
|
|
39
|
+
Requires-Dist: websockets>=11.0.0; extra == "websocket"
|
|
40
|
+
Provides-Extra: dev
|
|
41
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
42
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
43
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
44
|
+
Requires-Dist: pyserial>=3.5; extra == "dev"
|
|
45
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
46
|
+
Requires-Dist: isort>=5.12.0; extra == "dev"
|
|
47
|
+
Requires-Dist: flake8>=6.0.0; extra == "dev"
|
|
48
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
49
|
+
Requires-Dist: pre-commit>=3.0.0; extra == "dev"
|
|
50
|
+
Provides-Extra: docs
|
|
51
|
+
Requires-Dist: mkdocs>=1.5.0; extra == "docs"
|
|
52
|
+
Requires-Dist: mkdocs-material>=9.0.0; extra == "docs"
|
|
53
|
+
Requires-Dist: mkdocs-git-revision-date-localized-plugin>=1.2.0; extra == "docs"
|
|
54
|
+
Requires-Dist: mkdocs-git-committers-plugin-2>=1.2.0; extra == "docs"
|
|
55
|
+
Provides-Extra: all
|
|
56
|
+
Requires-Dist: openhop_core[dev,docs,hardware,websocket]; extra == "all"
|
|
57
|
+
Dynamic: license-file
|
|
58
|
+
|
|
59
|
+
# openHop Core
|
|
60
|
+
|
|
61
|
+
[](https://pymc-dev.github.io/openhop-core/)
|
|
62
|
+
[](https://pypi.org/project/openhop-core/)
|
|
63
|
+
[](LICENSE)
|
|
64
|
+
|
|
65
|
+
**openHop Core** is a Python reimplementation of [MeshCore](https://github.com/meshcore-dev/meshcore) — a lightweight, portable C++ library for multi-hop packet routing using LoRa radios. Designed for **Raspberry Pi** and similar hardware, openHop Core communicates with LoRa modules over **SPI**.
|
|
66
|
+
|
|
67
|
+
> openHop Core is under active development. It's compatible with the original MeshCore protocol, but not yet as optimized or elegant as its C++ counterpart.
|
|
68
|
+
|
|
69
|
+
## Documentation
|
|
70
|
+
|
|
71
|
+
**Complete documentation is available at **[https://rightup.github.io/openhop-core/](https://pymc-dev.github.io/openhop-core/)**
|
|
72
|
+
|
|
73
|
+
### Quick Links
|
|
74
|
+
- [Node Usage Guide](https://pymc-dev.github.io/openhop-core/node/) - Guide for using MeshNode
|
|
75
|
+
- [Examples](https://pymc-dev.github.io/openhop-core/examples/) - Working code examples
|
|
76
|
+
- [API Reference](https://pymc-dev.github.io/openhop-core/api/) - Detailed API documentation
|
|
77
|
+
|
|
78
|
+
## Quick Start
|
|
79
|
+
|
|
80
|
+
### Installation
|
|
81
|
+
|
|
82
|
+
> **Important**: On modern Python installations (Ubuntu 22.04+, Debian 12+), you may encounter `externally-managed-environment` errors when installing packages system-wide. Create a virtual environment first:
|
|
83
|
+
>
|
|
84
|
+
> ```bash
|
|
85
|
+
> # Create virtual environment
|
|
86
|
+
> python3 -m venv openhop_env
|
|
87
|
+
>
|
|
88
|
+
> # Activate virtual environment
|
|
89
|
+
> # On Linux/Mac:
|
|
90
|
+
> source openhop_env/bin/activate
|
|
91
|
+
> # On Windows:
|
|
92
|
+
> openhop_env\Scripts\activate
|
|
93
|
+
> ```
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
# Install from PyPI
|
|
97
|
+
pip install openhop-core
|
|
98
|
+
|
|
99
|
+
# For hardware support (SX1262 radios)
|
|
100
|
+
pip install openhop-core[hardware]
|
|
101
|
+
|
|
102
|
+
# Install all dependencies
|
|
103
|
+
pip install openhop-core[all]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Basic Usage
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
import asyncio
|
|
110
|
+
from openhop_core import MeshNode, LocalIdentity
|
|
111
|
+
from openhop_core.hardware.sx1262_wrapper import SX1262Radio
|
|
112
|
+
|
|
113
|
+
async def main():
|
|
114
|
+
# Create radio (Waveshare HAT example)
|
|
115
|
+
radio = SX1262Radio(
|
|
116
|
+
bus_id=0, cs_pin=21, reset_pin=18,
|
|
117
|
+
busy_pin=20, irq_pin=16, txen_pin=6,
|
|
118
|
+
frequency=869525000, tx_power=22
|
|
119
|
+
)
|
|
120
|
+
radio.begin()
|
|
121
|
+
|
|
122
|
+
# Create mesh node
|
|
123
|
+
identity = LocalIdentity()
|
|
124
|
+
node = MeshNode(radio=radio, local_identity=identity)
|
|
125
|
+
await node.start()
|
|
126
|
+
|
|
127
|
+
print("Mesh node started!")
|
|
128
|
+
|
|
129
|
+
asyncio.run(main())
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
For examples, see the [documentation](https://pymc-dev.github.io/openhop-core/examples/).
|
|
133
|
+
|
|
134
|
+
## Hardware Support
|
|
135
|
+
|
|
136
|
+
### Supported Radios
|
|
137
|
+
- **Waveshare SX1262 LoRaWAN/GNSS HAT** - Popular Raspberry Pi LoRa module
|
|
138
|
+
- **HackerGadgets uConsole** - All-in-one extension board with LoRa support
|
|
139
|
+
- **FrequencyLabs meshadv-mini** - Raspberry Pi hat with E22-900M22S LoRa module
|
|
140
|
+
|
|
141
|
+
### Requirements
|
|
142
|
+
- Raspberry Pi (or compatible SBC)
|
|
143
|
+
- SX1262 LoRa module
|
|
144
|
+
- SPI interface enabled
|
|
145
|
+
- Python 3.8+
|
|
146
|
+
|
|
147
|
+
## What is MeshCore?
|
|
148
|
+
|
|
149
|
+
MeshCore enables **long-range, decentralized communication** using **multi-hop packet routing**. Devices (nodes) forward packets through neighboring nodes to reach distant ones — no central infrastructure required.
|
|
150
|
+
|
|
151
|
+
It occupies a middle ground between:
|
|
152
|
+
|
|
153
|
+
| Project | Focus |
|
|
154
|
+
|---------|-------|
|
|
155
|
+
| [Meshtastic](https://meshtastic.org/) | Casual LoRa messaging |
|
|
156
|
+
| [Reticulum](https://reticulum.network/) | Full encrypted networking stack |
|
|
157
|
+
|
|
158
|
+
### Use Cases
|
|
159
|
+
- Off-grid and emergency communication
|
|
160
|
+
- Tactical or field mesh deployments
|
|
161
|
+
- IoT mesh networks
|
|
162
|
+
- Remote monitoring systems
|
|
163
|
+
|
|
164
|
+
## Architecture
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
168
|
+
│ Application │ │ MeshNode │ │ Hardware │
|
|
169
|
+
│ │ │ │ │ │
|
|
170
|
+
│ • Text Messages │◄──►│ • Packet Routing│◄──►│ • SX1262 Radio │
|
|
171
|
+
│ • Advertisements│ │ • Identity Mgmt │ │ • SPI Interface │
|
|
172
|
+
│ • Telemetry │ │ • Event Service │ │ • GPIO Control │
|
|
173
|
+
│ • Group Channels│ │ • Repeater Mgmt │ │ │
|
|
174
|
+
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Security
|
|
178
|
+
|
|
179
|
+
- **Ed25519/X25519 cryptographic identities**
|
|
180
|
+
- **End-to-end encryption** for messages
|
|
181
|
+
- **CRC validation** for data integrity
|
|
182
|
+
- **Secure key exchange** protocols
|
|
183
|
+
|
|
184
|
+
## Project Structure
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
openHop Core/
|
|
188
|
+
├── src/openhop_core/ # Main package
|
|
189
|
+
│ ├── hardware/ # Radio hardware interfaces
|
|
190
|
+
│ ├── node/ # MeshNode implementation
|
|
191
|
+
│ ├── protocol/ # Packet protocols
|
|
192
|
+
│ └── events/ # Event handling
|
|
193
|
+
├── examples/ # Working examples
|
|
194
|
+
│ ├── common.py # Shared utilities
|
|
195
|
+
│ ├── send_flood_advert.py
|
|
196
|
+
│ ├── send_direct_advert.py
|
|
197
|
+
│ └── ...
|
|
198
|
+
├── docs/ # MkDocs documentation
|
|
199
|
+
│ ├── docs/ # Documentation source files
|
|
200
|
+
│ ├── mkdocs.yml # MkDocs configuration
|
|
201
|
+
│ ├── requirements.txt # Documentation dependencies
|
|
202
|
+
│ └── serve-docs.sh # Local development script
|
|
203
|
+
├── .github/workflows/ # GitHub Actions
|
|
204
|
+
│ └── deploy-docs.yml # Documentation deployment pipeline
|
|
205
|
+
└── tests/ # Unit tests
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Contributing
|
|
209
|
+
|
|
210
|
+
Contributions are welcome! Please see our [contributing guide](https://pymc-dev.github.io/openhop-core/contributing/) for details.
|
|
211
|
+
|
|
212
|
+
### Development Setup
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
# Clone the repository
|
|
216
|
+
git clone https://github.com/rightup/openHop Core.git
|
|
217
|
+
cd openHop Core
|
|
218
|
+
|
|
219
|
+
# Install development dependencies
|
|
220
|
+
pip install -e .[dev]
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
## License
|
|
228
|
+
|
|
229
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
230
|
+
|
|
231
|
+
## Acknowledgments
|
|
232
|
+
|
|
233
|
+
- Original [MeshCore](https://github.com/meshcore-dev/meshcore) C++ implementation
|
|
234
|
+
- Waveshare and HackerGadgets for hardware support
|
|
235
|
+
|
|
236
|
+
## Support
|
|
237
|
+
|
|
238
|
+
- [Documentation](https://pymc-dev.github.io/openhop-core/)
|
|
239
|
+
- [Issues](https://github.com/pymc-dev/openHop Core/issues)
|
|
240
|
+
- [Discussions](https://github.com/pymc-dev/openHop Core/discussions)
|
|
241
|
+
- [pyMC Discord](https://discord.gg/3s8MMaSTzq)
|
|
242
|
+
- [Meshcore Discord](https://meshcore.gg/)
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
*Built with ❤️ for mesh networking enthusiasts*</content>
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# openHop Core
|
|
2
|
+
|
|
3
|
+
[](https://pymc-dev.github.io/openhop-core/)
|
|
4
|
+
[](https://pypi.org/project/openhop-core/)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
|
|
7
|
+
**openHop Core** is a Python reimplementation of [MeshCore](https://github.com/meshcore-dev/meshcore) — a lightweight, portable C++ library for multi-hop packet routing using LoRa radios. Designed for **Raspberry Pi** and similar hardware, openHop Core communicates with LoRa modules over **SPI**.
|
|
8
|
+
|
|
9
|
+
> openHop Core is under active development. It's compatible with the original MeshCore protocol, but not yet as optimized or elegant as its C++ counterpart.
|
|
10
|
+
|
|
11
|
+
## Documentation
|
|
12
|
+
|
|
13
|
+
**Complete documentation is available at **[https://rightup.github.io/openhop-core/](https://pymc-dev.github.io/openhop-core/)**
|
|
14
|
+
|
|
15
|
+
### Quick Links
|
|
16
|
+
- [Node Usage Guide](https://pymc-dev.github.io/openhop-core/node/) - Guide for using MeshNode
|
|
17
|
+
- [Examples](https://pymc-dev.github.io/openhop-core/examples/) - Working code examples
|
|
18
|
+
- [API Reference](https://pymc-dev.github.io/openhop-core/api/) - Detailed API documentation
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### Installation
|
|
23
|
+
|
|
24
|
+
> **Important**: On modern Python installations (Ubuntu 22.04+, Debian 12+), you may encounter `externally-managed-environment` errors when installing packages system-wide. Create a virtual environment first:
|
|
25
|
+
>
|
|
26
|
+
> ```bash
|
|
27
|
+
> # Create virtual environment
|
|
28
|
+
> python3 -m venv openhop_env
|
|
29
|
+
>
|
|
30
|
+
> # Activate virtual environment
|
|
31
|
+
> # On Linux/Mac:
|
|
32
|
+
> source openhop_env/bin/activate
|
|
33
|
+
> # On Windows:
|
|
34
|
+
> openhop_env\Scripts\activate
|
|
35
|
+
> ```
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Install from PyPI
|
|
39
|
+
pip install openhop-core
|
|
40
|
+
|
|
41
|
+
# For hardware support (SX1262 radios)
|
|
42
|
+
pip install openhop-core[hardware]
|
|
43
|
+
|
|
44
|
+
# Install all dependencies
|
|
45
|
+
pip install openhop-core[all]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Basic Usage
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
import asyncio
|
|
52
|
+
from openhop_core import MeshNode, LocalIdentity
|
|
53
|
+
from openhop_core.hardware.sx1262_wrapper import SX1262Radio
|
|
54
|
+
|
|
55
|
+
async def main():
|
|
56
|
+
# Create radio (Waveshare HAT example)
|
|
57
|
+
radio = SX1262Radio(
|
|
58
|
+
bus_id=0, cs_pin=21, reset_pin=18,
|
|
59
|
+
busy_pin=20, irq_pin=16, txen_pin=6,
|
|
60
|
+
frequency=869525000, tx_power=22
|
|
61
|
+
)
|
|
62
|
+
radio.begin()
|
|
63
|
+
|
|
64
|
+
# Create mesh node
|
|
65
|
+
identity = LocalIdentity()
|
|
66
|
+
node = MeshNode(radio=radio, local_identity=identity)
|
|
67
|
+
await node.start()
|
|
68
|
+
|
|
69
|
+
print("Mesh node started!")
|
|
70
|
+
|
|
71
|
+
asyncio.run(main())
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
For examples, see the [documentation](https://pymc-dev.github.io/openhop-core/examples/).
|
|
75
|
+
|
|
76
|
+
## Hardware Support
|
|
77
|
+
|
|
78
|
+
### Supported Radios
|
|
79
|
+
- **Waveshare SX1262 LoRaWAN/GNSS HAT** - Popular Raspberry Pi LoRa module
|
|
80
|
+
- **HackerGadgets uConsole** - All-in-one extension board with LoRa support
|
|
81
|
+
- **FrequencyLabs meshadv-mini** - Raspberry Pi hat with E22-900M22S LoRa module
|
|
82
|
+
|
|
83
|
+
### Requirements
|
|
84
|
+
- Raspberry Pi (or compatible SBC)
|
|
85
|
+
- SX1262 LoRa module
|
|
86
|
+
- SPI interface enabled
|
|
87
|
+
- Python 3.8+
|
|
88
|
+
|
|
89
|
+
## What is MeshCore?
|
|
90
|
+
|
|
91
|
+
MeshCore enables **long-range, decentralized communication** using **multi-hop packet routing**. Devices (nodes) forward packets through neighboring nodes to reach distant ones — no central infrastructure required.
|
|
92
|
+
|
|
93
|
+
It occupies a middle ground between:
|
|
94
|
+
|
|
95
|
+
| Project | Focus |
|
|
96
|
+
|---------|-------|
|
|
97
|
+
| [Meshtastic](https://meshtastic.org/) | Casual LoRa messaging |
|
|
98
|
+
| [Reticulum](https://reticulum.network/) | Full encrypted networking stack |
|
|
99
|
+
|
|
100
|
+
### Use Cases
|
|
101
|
+
- Off-grid and emergency communication
|
|
102
|
+
- Tactical or field mesh deployments
|
|
103
|
+
- IoT mesh networks
|
|
104
|
+
- Remote monitoring systems
|
|
105
|
+
|
|
106
|
+
## Architecture
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
110
|
+
│ Application │ │ MeshNode │ │ Hardware │
|
|
111
|
+
│ │ │ │ │ │
|
|
112
|
+
│ • Text Messages │◄──►│ • Packet Routing│◄──►│ • SX1262 Radio │
|
|
113
|
+
│ • Advertisements│ │ • Identity Mgmt │ │ • SPI Interface │
|
|
114
|
+
│ • Telemetry │ │ • Event Service │ │ • GPIO Control │
|
|
115
|
+
│ • Group Channels│ │ • Repeater Mgmt │ │ │
|
|
116
|
+
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Security
|
|
120
|
+
|
|
121
|
+
- **Ed25519/X25519 cryptographic identities**
|
|
122
|
+
- **End-to-end encryption** for messages
|
|
123
|
+
- **CRC validation** for data integrity
|
|
124
|
+
- **Secure key exchange** protocols
|
|
125
|
+
|
|
126
|
+
## Project Structure
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
openHop Core/
|
|
130
|
+
├── src/openhop_core/ # Main package
|
|
131
|
+
│ ├── hardware/ # Radio hardware interfaces
|
|
132
|
+
│ ├── node/ # MeshNode implementation
|
|
133
|
+
│ ├── protocol/ # Packet protocols
|
|
134
|
+
│ └── events/ # Event handling
|
|
135
|
+
├── examples/ # Working examples
|
|
136
|
+
│ ├── common.py # Shared utilities
|
|
137
|
+
│ ├── send_flood_advert.py
|
|
138
|
+
│ ├── send_direct_advert.py
|
|
139
|
+
│ └── ...
|
|
140
|
+
├── docs/ # MkDocs documentation
|
|
141
|
+
│ ├── docs/ # Documentation source files
|
|
142
|
+
│ ├── mkdocs.yml # MkDocs configuration
|
|
143
|
+
│ ├── requirements.txt # Documentation dependencies
|
|
144
|
+
│ └── serve-docs.sh # Local development script
|
|
145
|
+
├── .github/workflows/ # GitHub Actions
|
|
146
|
+
│ └── deploy-docs.yml # Documentation deployment pipeline
|
|
147
|
+
└── tests/ # Unit tests
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Contributing
|
|
151
|
+
|
|
152
|
+
Contributions are welcome! Please see our [contributing guide](https://pymc-dev.github.io/openhop-core/contributing/) for details.
|
|
153
|
+
|
|
154
|
+
### Development Setup
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# Clone the repository
|
|
158
|
+
git clone https://github.com/rightup/openHop Core.git
|
|
159
|
+
cd openHop Core
|
|
160
|
+
|
|
161
|
+
# Install development dependencies
|
|
162
|
+
pip install -e .[dev]
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
## License
|
|
170
|
+
|
|
171
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
172
|
+
|
|
173
|
+
## Acknowledgments
|
|
174
|
+
|
|
175
|
+
- Original [MeshCore](https://github.com/meshcore-dev/meshcore) C++ implementation
|
|
176
|
+
- Waveshare and HackerGadgets for hardware support
|
|
177
|
+
|
|
178
|
+
## Support
|
|
179
|
+
|
|
180
|
+
- [Documentation](https://pymc-dev.github.io/openhop-core/)
|
|
181
|
+
- [Issues](https://github.com/pymc-dev/openHop Core/issues)
|
|
182
|
+
- [Discussions](https://github.com/pymc-dev/openHop Core/discussions)
|
|
183
|
+
- [pyMC Discord](https://discord.gg/3s8MMaSTzq)
|
|
184
|
+
- [Meshcore Discord](https://meshcore.gg/)
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
*Built with ❤️ for mesh networking enthusiasts*</content>
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "openhop_core"
|
|
7
|
+
version = "1.1.1"
|
|
8
|
+
authors = [
|
|
9
|
+
{name = "Rightup", email = "rightup@openhop.dev"},
|
|
10
|
+
]
|
|
11
|
+
description = "A Python MeshCore library with SPI LoRa radio support"
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
license = {text = "MIT"}
|
|
14
|
+
requires-python = ">=3.9"
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.9",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Topic :: Communications",
|
|
26
|
+
"Topic :: System :: Networking",
|
|
27
|
+
]
|
|
28
|
+
keywords = ["mesh", "networking", "lora", "radio", "iot", "communication"]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"pycryptodome>=3.23.0",
|
|
31
|
+
"PyNaCl>=1.5.0",
|
|
32
|
+
"pyyaml>=6.0.0",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[project.optional-dependencies]
|
|
36
|
+
radio = ["pyserial>=3.5"]
|
|
37
|
+
hardware = [
|
|
38
|
+
"python-periphery>=2.4.1",
|
|
39
|
+
"spidev>=3.5",
|
|
40
|
+
"pyserial>=3.5",
|
|
41
|
+
"pyusb>=1.2.1",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
gpiod = ["gpiod>=2.4.0"]
|
|
45
|
+
|
|
46
|
+
websocket = [
|
|
47
|
+
"websockets>=11.0.0",
|
|
48
|
+
]
|
|
49
|
+
dev = [
|
|
50
|
+
"pytest>=7.0.0",
|
|
51
|
+
"pytest-cov>=4.0.0",
|
|
52
|
+
"pytest-asyncio>=0.21.0",
|
|
53
|
+
"pyserial>=3.5",
|
|
54
|
+
"black>=23.0.0",
|
|
55
|
+
"isort>=5.12.0",
|
|
56
|
+
"flake8>=6.0.0",
|
|
57
|
+
"mypy>=1.0.0",
|
|
58
|
+
"pre-commit>=3.0.0",
|
|
59
|
+
]
|
|
60
|
+
docs = [
|
|
61
|
+
"mkdocs>=1.5.0",
|
|
62
|
+
"mkdocs-material>=9.0.0",
|
|
63
|
+
"mkdocs-git-revision-date-localized-plugin>=1.2.0",
|
|
64
|
+
"mkdocs-git-committers-plugin-2>=1.2.0",
|
|
65
|
+
]
|
|
66
|
+
all = ["openhop_core[hardware,websocket,dev,docs]"]
|
|
67
|
+
|
|
68
|
+
[project.urls]
|
|
69
|
+
Homepage = "https://github.com/pyMC-dev/openhop-core/"
|
|
70
|
+
Documentation = "https://rightup.github.io/pymc_dev/openhop-core"
|
|
71
|
+
Repository = "https://github.com/pyMC-dev/openhop-core.git"
|
|
72
|
+
Issues = "https://github.com/pyMC-dev/openhop-core/issues"
|
|
73
|
+
|
|
74
|
+
[tool.setuptools]
|
|
75
|
+
package-dir = {"" = "src"}
|
|
76
|
+
|
|
77
|
+
[tool.setuptools.packages.find]
|
|
78
|
+
where = ["src"]
|
|
79
|
+
include = ["openhop_core*"]
|
|
80
|
+
exclude = ["__pycache__*", "*.pyc", "*.pyo"]
|
|
81
|
+
|
|
82
|
+
[tool.black]
|
|
83
|
+
line-length = 100
|
|
84
|
+
target-version = ['py38']
|
|
85
|
+
|
|
86
|
+
[tool.isort]
|
|
87
|
+
profile = "black"
|
|
88
|
+
line_length = 100
|
|
89
|
+
|
|
90
|
+
[tool.flake8]
|
|
91
|
+
max-line-length = 100
|
|
92
|
+
extend-ignore = ["E203", "W503"]
|
|
93
|
+
exclude = [
|
|
94
|
+
"src/openhop_core/hardware/lora/",
|
|
95
|
+
"examples/",
|
|
96
|
+
"__pycache__",
|
|
97
|
+
".git",
|
|
98
|
+
".tox",
|
|
99
|
+
"dist",
|
|
100
|
+
"*.egg-info"
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
[tool.pytest.ini_options]
|
|
104
|
+
minversion = "7.0"
|
|
105
|
+
addopts = "-ra -q"
|
|
106
|
+
testpaths = ["tests"]
|
|
107
|
+
python_files = ["test_*.py"]
|
|
108
|
+
python_classes = ["Test*"]
|
|
109
|
+
python_functions = ["test_*"]
|
|
110
|
+
asyncio_mode = "auto"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""
|
|
2
|
+
openHop Core - A Python MeshCore library with SPI LoRa radio support
|
|
3
|
+
Clean, simple API for building mesh network applications.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
__version__ = "1.1.1"
|
|
7
|
+
|
|
8
|
+
# Core mesh functionality
|
|
9
|
+
from .node.node import MeshNode
|
|
10
|
+
from .protocol.crypto import CryptoUtils
|
|
11
|
+
from .protocol.identity import LocalIdentity
|
|
12
|
+
from .protocol.packet import Packet
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
# Core API
|
|
16
|
+
"MeshNode",
|
|
17
|
+
"LocalIdentity",
|
|
18
|
+
"Packet",
|
|
19
|
+
"CryptoUtils",
|
|
20
|
+
# Version
|
|
21
|
+
"__version__",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
# Conditional import for CompanionRadio
|
|
25
|
+
try:
|
|
26
|
+
from .companion.companion_radio import CompanionRadio
|
|
27
|
+
|
|
28
|
+
_COMPANION_AVAILABLE = True
|
|
29
|
+
except ImportError:
|
|
30
|
+
_COMPANION_AVAILABLE = False
|
|
31
|
+
CompanionRadio = None
|
|
32
|
+
|
|
33
|
+
if _COMPANION_AVAILABLE:
|
|
34
|
+
__all__.append("CompanionRadio")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# End of mesh package exports
|