Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,12 @@ jobs:
- run: python -m pytest python
- if: matrix.python-version == '3.14'
run: |
python -m ruff check python
python -m ruff check python benchmarks scripts
python -m mypy python/src
python scripts/check_docs.py

esp32:
name: ESP32 Arduino compile
name: ESP32 Arduino examples
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
Expand All @@ -46,23 +47,44 @@ jobs:
cache: pip
- run: python -m pip install platformio
- run: platformio run -e esp32dev
- run: platformio ci examples/SecureTelemetryClient/SecureTelemetryClient.ino --board esp32dev --lib src
- run: platformio ci examples/BluetoothSerialClient/BluetoothSerialClient.ino --board esp32dev --lib src

arduino-native:
name: Arduino native tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.14"
- run: python -m pip install platformio
- run: platformio test -e native

package:
name: Reproducible packages
runs-on: ubuntu-latest
env:
SOURCE_DATE_EPOCH: "1700000000"
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v7
with:
python-version: "3.14"
cache: pip
- run: python -m pip install build
- run: python scripts/build_release.py
- run: python -m build python
- run: python scripts/build_release.py
- run: python scripts/build_linux_bundle.py
- run: python scripts/build_checksums.py
- run: python scripts/verify_reproducible.py
- run: sh -n packaging/linux/install.sh packaging/linux/uninstall.sh
- uses: actions/upload-artifact@v7
with:
name: packages
path: |
dist/OpenNet-*.zip
dist/OpenNet-linux-*.tar.gz
dist/SHA256SUMS
python/dist/*
if-no-files-found: error
15 changes: 12 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ permissions:
jobs:
release:
runs-on: ubuntu-latest
env:
SOURCE_DATE_EPOCH: "1700000000"
steps:
- uses: actions/checkout@v7
with:
Expand All @@ -22,17 +24,24 @@ jobs:
run: |
python -m pip install -e "./python[dev]" build
python -m pytest python
python -m ruff check python
python -m ruff check python benchmarks scripts
python -m mypy python/src
python scripts/build_release.py --expected-version "${GITHUB_REF_NAME#v}"
python scripts/check_docs.py
python -m build python
python scripts/build_release.py --expected-version "${GITHUB_REF_NAME#v}"
python scripts/build_linux_bundle.py --expected-version "${GITHUB_REF_NAME#v}"
python scripts/build_checksums.py
python scripts/verify_reproducible.py
sh -n packaging/linux/install.sh packaging/linux/uninstall.sh
- name: Create GitHub release
env:
GH_TOKEN: ${{ github.token }}
run: >-
gh release create "$GITHUB_REF_NAME"
dist/OpenNet-*.zip
dist/OpenNet-linux-*.tar.gz
dist/SHA256SUMS
python/dist/*
--generate-notes
--notes-file "docs/releases/$GITHUB_REF_NAME.md"
--verify-tag
--title "OpenNet $GITHUB_REF_NAME"
29 changes: 28 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,31 @@ All notable changes are documented here. OpenNet follows

## [Unreleased]

## [0.1.1] - 2026-07-29

### Added

- Unified `opennet` CLI with `serve`, `send`, `ping`, and `benchmark` commands.
- Acknowledgement retries using stable IDs and the ONP/1 `DUPLICATE` flag.
- Bounded server duplicate suppression, connection limits, operational counters,
receive queues, and connect timeouts.
- Mutual TLS options and secure-by-default remote CLI behavior.
- Generic Arduino `Stream` support for UART and Bluetooth Classic SPP transports.
- Typed Arduino receive accessors, readable error names, and ACK lookup helper.
- Hardened Linux/systemd installer bundle, checksums, and deterministic packages.
- Native C++ protocol tests, malformed-control tests, and retry/disconnect tests.
- Measured TCP/TLS/load benchmarks, protocol comparisons, tutorials, tips,
transport boundaries, security guidance, and honest adoption analytics.

### Fixed

- Partial Arduino transport writes now complete the whole frame.
- Python receivers now wake with an error when a peer disconnects.
- Handler errors no longer expose exception details to remote peers.
- Control-frame validation is consistent across Python and Arduino.

## [0.1.0] - 2026-07-29

### Added

- ONP/1 protocol specification and typed binary framing.
Expand All @@ -13,4 +38,6 @@ All notable changes are documented here. OpenNet follows
- Arduino IDE, PlatformIO, and Python examples.
- Cross-platform tests, CI, packaging, and contributor documentation.

[Unreleased]: https://github.com/devkyato/OpenNet/compare/v0.1.0...HEAD
[Unreleased]: https://github.com/devkyato/OpenNet/compare/v0.1.1...HEAD
[0.1.1]: https://github.com/devkyato/OpenNet/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/devkyato/OpenNet/releases/tag/v0.1.0
150 changes: 97 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,78 +3,122 @@
![OpenNet cover](docs/assets/opennet-cover.png)

[![CI](https://github.com/devkyato/OpenNet/actions/workflows/ci.yml/badge.svg)](https://github.com/devkyato/OpenNet/actions/workflows/ci.yml)
[![Release](https://img.shields.io/github/v/release/devkyato/OpenNet)](https://github.com/devkyato/OpenNet/releases)
[![License: MIT](https://img.shields.io/badge/license-MIT-4a638f.svg)](LICENSE)
[![Protocol](https://img.shields.io/badge/protocol-ONP%2F1-4a638f.svg)](docs/protocol.md)

OpenNet is a small, typed messaging protocol and library for sending JSON, text,
numbers, and arbitrary binary data between ESP32 devices, Raspberry Pi computers,
and backend services over Wi-Fi or Ethernet.
OpenNet is a dependency-free typed messaging protocol for direct communication
between ESP32 devices, Raspberry Pi computers, and backend services. It sends
JSON, text, signed integers, finite doubles, booleans, null, and arbitrary binary
data over TCP/TLS or another reliable ordered stream.

Version 0.1.1 is an alpha release for real projects and learning. It has a
documented wire format, bounded resource use, retries and duplicate suppression,
native Arduino protocol tests, Python tests across 3.9–3.14, reproducible release
packages, measured local performance, and security guidance. It does not claim
that a radio or internet route exists when the underlying hardware/network is
unavailable.

## Why OpenNet

- One small API and one frame format across ESP32 and Python.
- Typed values without a JSON dependency for every scalar or binary payload.
- Optional application ACKs, retry with stable message IDs, and bounded
duplicate suppression.
- TCP/TLS over Wi-Fi, Ethernet, or routed networks.
- Generic Arduino `Stream` support for UART, USB serial, and Bluetooth Classic
SPP on compatible ESP32 hardware.
- Strict control frames, CRC-32 corruption detection, payload limits, bounded
queues, connection limits, and partial transport-write handling.
- CLI tools to serve, send, ping, and benchmark.
- Arduino IDE, PlatformIO/VS Code, Python, Linux/systemd, and security tutorials.

## Install

Python wheel from the release page:

```sh
python -m pip install \
https://github.com/devkyato/OpenNet/releases/download/v0.1.1/opennet_protocol-0.1.1-py3-none-any.whl
opennet --version
```

For an isolated command:

The first release deliberately targets one dependable path: an ESP32 client and a
Python 3.9+ client/server communicating over TCP. The wire format is documented and
language-neutral, so additional transports and language bindings can be added
without inventing incompatible message formats.
```sh
pipx install \
https://github.com/devkyato/OpenNet/releases/download/v0.1.1/opennet_protocol-0.1.1-py3-none-any.whl
```

## What it provides
For Raspberry Pi/Linux, extract `OpenNet-linux-0.1.1.tar.gz` and run
`sudo ./install.sh`. It creates a hardened, unprivileged systemd service with a
loopback-only default. For Arduino IDE, install `OpenNet-0.1.1.zip` through
**Sketch > Include Library > Add .ZIP Library**.

- A compact binary frame with versioning, message IDs, type information, CRC-32,
and a 16 MiB defensive payload limit.
- JSON, UTF-8 text, signed integers, IEEE-754 doubles, booleans, null, and raw bytes.
- Async Python client/server APIs for Raspberry Pi and backend systems.
- An Arduino-compatible ESP32 client with reconnect, heartbeat, and delivery ACKs.
- Optional TLS at the transport layer.
- Arduino IDE, PlatformIO, Python, and VS Code examples.
- Protocol conformance tests and cross-platform CI.
The Python distribution is installable with pip, but v0.1.1 is distributed from
GitHub Releases rather than the public PyPI index.

## Five-minute start
## Five-minute local test

Run the Python server:
Terminal one:

```bash
python -m pip install -e "./python[dev]"
opennet-server --host 0.0.0.0 --port 8765
```sh
opennet serve --echo
```

Install this repository as an Arduino library, open
`File > Examples > OpenNet > TelemetryClient`, set the Wi-Fi credentials and
server address, then upload it to an ESP32.
Terminal two:

Python clients are equally small:
```sh
opennet ping --count 5
opennet send sensor/temperature 24.7 --type float
opennet send device/state '{"online":true}' --type json
opennet benchmark --count 1000 --payload-size 64
```

Python code is equally small:

```python
import asyncio
from opennet import OpenNetClient

async def main():
async with OpenNetClient("192.168.1.50", 8765) as client:
await client.send("temperature", {"celsius": 24.7})
async with OpenNetClient("127.0.0.1") as client:
message_id = await client.send(
"lab/temperature", 24.7, retries=2
)
print("acknowledged", message_id)

asyncio.run(main())
```

See the [getting-started guide](docs/getting-started.md), [protocol
specification](docs/protocol.md), and [compatibility policy](docs/compatibility.md).

## Project status

OpenNet is pre-1.0 software. ONP/1 framing is stable for the v0.x series, while
higher-level APIs may improve based on real hardware feedback. Do not represent
untested boards or operating systems as supported; add a compatibility report when
you test one.

## Contributing

Student contributions are welcome. Good first tasks are labeled in the issue
tracker, and every feature should include tests or a reproducible hardware test
report. Read [CONTRIBUTING.md](CONTRIBUTING.md) and the
[code of conduct](CODE_OF_CONDUCT.md) before opening a pull request.

## Security

CRC detects accidental corruption; it is not encryption or authentication. Use TLS
on untrusted networks. See [SECURITY.md](SECURITY.md) for the threat model and
private reporting instructions.

## License

OpenNet is available under the [MIT License](LICENSE).
The CLI defaults to loopback and refuses remote plaintext unless it is explicitly
allowed for a trusted development network. Use verified TLS—and mutual TLS when
device identity matters—outside isolated local testing.

## Evidence and design

- [Measured TCP/TLS and 20-client load results](docs/benchmarks.md)
- [Comparison with raw TCP, MQTT, WebSocket, and HTTP](docs/comparison.md)
- [Architecture, ACK retry, and defensive boundaries](docs/architecture.md)
- [Actual GitHub adoption counters and analytics limits](docs/adoption-analytics.md)
- [Transport support, including Bluetooth boundaries](docs/transports.md)

Measured loopback results are software baselines, not invented Wi-Fi or hardware
claims. Hardware field reports are welcome through the
[compatibility process](docs/compatibility.md).

## Learn and build

- [Tutorials](docs/tutorials.md)
- [CLI reference](docs/cli.md)
- [Linux/Raspberry Pi service guide](docs/linux-service.md)
- [Getting started](docs/getting-started.md)
- [Development tips](docs/tips.md)
- [Security guide](docs/security.md)
- [ONP/1 protocol specification](docs/protocol.md)
- [Contributing](CONTRIBUTING.md)

Student contributions are welcome. Good changes include a reproducible test,
clear documentation, or a complete compatibility report. OpenNet follows
[Semantic Versioning](https://semver.org/) and is licensed under the
[MIT License](LICENSE).
4 changes: 4 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,7 @@ coordinate disclosure after a fix is available.
- Applications must authorize topics and validate payloads.
- The 16 MiB frame limit reduces memory-exhaustion risk; deployments should choose
a smaller application limit appropriate for their hardware.

The CLI defaults to loopback and requires an explicit flag for remote plaintext.
Mutual TLS is available when deployments must authenticate client devices. See the
[security guide](docs/security.md) for commands, limits, and deployment checklists.
Loading
Loading