Skip to content

Commit

Permalink
Update README with detailed package information, add .gitignore entri…
Browse files Browse the repository at this point in the history
…es for Protobuf files, refactor TowerComms message handling methods, and adjust data types in packets.proto.
  • Loading branch information
TylerFlar committed Jan 24, 2025
1 parent e808393 commit 1ae1125
Show file tree
Hide file tree
Showing 9 changed files with 255 additions and 17 deletions.
40 changes: 40 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Run Ruff Linter

on:
pull_request:
branches:
- main
- dev

jobs:
lint:
runs-on: ubuntu-latest

steps:
- name: Check out code
uses: actions/checkout@v3

- name: Set up Python 3.12
uses: actions/setup-python@v4
with:
python-version: '3.12'

- name: Cache dependencies
uses: actions/cache@v3
with:
path: |
~/.cache/pypoetry
~/.cache/pip
key: ${{ runner.os }}-poetry-${{ hashFiles('poetry.lock') }}
restore-keys: |
${{ runner.os }}-poetry-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install poetry
poetry install --with dev
- name: Run ruff linter
run: |
poetry run ruff check .
40 changes: 40 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Run Tests

on:
pull_request:
branches:
- main
- dev

jobs:
test:
runs-on: ubuntu-latest

steps:
- name: Check out code
uses: actions/checkout@v3

- name: Set up Python 3.12
uses: actions/setup-python@v4
with:
python-version: '3.12'

- name: Cache dependencies
uses: actions/cache@v3
with:
path: |
~/.cache/pypoetry
~/.cache/pip
key: ${{ runner.os }}-poetry-${{ hashFiles('poetry.lock') }}
restore-keys: |
${{ runner.os }}-poetry-
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install poetry
poetry install --with dev
- name: Run tests
run: |
poetry run pytest
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,7 @@ cython_debug/

# Poetry
poetry.lock

# Protobuf
*_pb2.py

11 changes: 11 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
This software is Copyright © 2024 The Regents of the University of California. All Rights Reserved. Permission to copy, modify, and distribute this software and its documentation for educational, research and non-profit purposes, without fee, and without a written agreement is hereby granted, provided that the above copyright notice, this paragraph and the following three paragraphs appear in all copies. Permission to make commercial use of this software may be obtained by contacting:

Office of Innovation and Commercialization
9500 Gilman Drive, Mail Code 0910
University of California
La Jolla, CA 92093-0910
innovation@ucsd.edu

This software program and documentation are copyrighted by The Regents of the University of California. The software program and documentation are supplied “as is”, without any accompanying services from The Regents. The Regents does not warrant that the operation of the program will be uninterrupted or error-free. The end-user understands that the program was developed for research purposes and is advised not to rely exclusively on the program for any reason.

IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN “AS IS” BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
144 changes: 143 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,143 @@
# radio-telemetry-tracker-tower-comms-package
# Radio Telemetry Tracker Tower Communications Package (Comms Package)

The **Radio Telemetry Tracker Tower Communications Package** is a Python-based library designed to facilitate mesh network communication between radio telemetry towers using Meshtastic devices. It provides a robust framework for configuration management, ping data transmission, and error handling between towers in a distributed network.

> Note: This package is intended as a shared component for tower-based radio telemetry systems. It provides the communication infrastructure between towers but is not meant for standalone use.
## Table of Contents
- [Radio Telemetry Tracker Tower Communications Package (Comms Package)](#radio-telemetry-tracker-tower-communications-package-comms-package)
- [Table of Contents](#table-of-contents)
- [Overview](#overview)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Configuration](#configuration)
- [Usage](#usage)
- [Message Types](#message-types)
- [Development](#development)
- [License](#license)

## Overview

This package provides:

- **Mesh Network Communication**: Interface with Meshtastic devices for tower-to-tower communication
- **Message Types**: Protobuf-defined messages for configuration, pings, and errors
- **Acknowledgments**: Built-in support for message acknowledgments and retries
- **Position Tracking**: Integration with GPS data from Meshtastic devices
- **Simulation Support**: Simulated mesh interface for development and testing

## Prerequisites

- Python 3.13
- Poetry for dependency management
- Meshtastic-compatible device for real deployment
- Protocol Buffers compiler for development

## Installation

1. Add as a dependency to your project:
```bash
poetry add git+https://github.com/UCSD-E4E/radio-telemetry-tracker-tower-comms-package.git
```
2. Or clone for development:
```bash
bash
git clone https://github.com/UCSD-E4E/radio-telemetry-tracker-tower-comms-package.git
cd radio-telemetry-tracker-tower-comms-package
poetry install
```

## Configuration

The library supports two interface types:

1. **Meshtastic Interface**:
```python
from radio_telemetry_tracker_tower_comms_package import NodeConfig, TowerComms
config = NodeConfig(
interface_type="meshtastic",
device="/dev/ttyUSB0", # Serial port for Meshtastic device
)
```
2. **Simulated Interface** (for testing):
```python
from radio_telemetry_tracker_tower_comms_package import NodeConfig, TowerComms
config = NodeConfig(
interface_type="simulated",
numeric_id=1, # Unique node ID
user_id="Tower1" # Human-readable name
)
```

## Usage

Basic usage pattern:

1. **Initialize communications**:
```python
from radio_telemetry_tracker_tower_comms_package import TowerComms, NodeConfig
def on_ack_success(packet_id: int):
print(f"Packet {packet_id} acknowledged")
def on_ack_failure(packet_id: int):
print(f"Packet {packet_id} failed")
config = NodeConfig(interface_type="meshtastic", device="/dev/ttyUSB0")
comms = TowerComms(config, on_ack_success, on_ack_failure)
```
2. **Register message handlers**:
```python
def handle_ping(data: PingData):
print(f"Ping received from {data.node_id} at freq {data.frequency}")
comms.register_ping_handler(handle_ping)
```
3. **Start communication**:
```python
comms.start() # Opens the mesh interface
```
4. **Send messages**:
```python
comms.send_request_config(destination=2, want_ack=True)
ping_data = PingData(frequency=915000000, amplitude=0.8, latitude=32.7, longitude=-117.1, altitude=100)
comms.send_ping(ping_data, destination=None) # Broadcast
```
5. **Stop communication**:
```python
comms.stop() # Closes the mesh interface
```


## Message Types

- **ConfigData**: Tower configuration parameters
- **PingData**: Radio ping detection data with GPS coordinates
- **ErrorData**: Error messages and diagnostics
- **RequestConfigData**: Configuration request messages

## Development

1. Install development dependencies:
```bash
poetry install --with dev
```
2. Run tests:
```bash
poetry run pytest
```
3. Check code style:
```bash
poetry run ruff check . --fix
```

## License

This project is licensed under the terms specified in the [LICENSE](LICENSE) file.
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ message ConfigPacket {
bool enable_test_data = 6;
int32 ping_width_ms = 7;
int32 ping_min_snr = 8;
int32 ping_max_len_mult = 9;
int32 ping_min_len_mult = 10;
float ping_max_len_mult = 9;
float ping_min_len_mult = 10;
repeated int32 target_frequencies = 11;
}

Expand Down
8 changes: 4 additions & 4 deletions radio_telemetry_tracker_tower_comms_package/tower_comms.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,16 +389,16 @@ def _on_raw_packet(self, raw_data: bytes) -> None:
which = pb.WhichOneof("msg")
if which == "request_config":
data = self._extract_request_config(pb.request_config)
self._handle_request_config(data)
self._invoke_request_config(data)
elif which == "config":
data = self._extract_config(pb.config)
self._handle_config(data)
self._invoke_config(data)
elif which == "ping":
data = self._extract_ping(pb.ping)
self._handle_ping(data)
self._invoke_ping(data)
elif which == "error":
data = self._extract_error(pb.error)
self._handle_error(data)
self._invoke_error(data)
else:
logger.debug("Received unknown message type: %s", which)
except Exception:
Expand Down
15 changes: 8 additions & 7 deletions tests/test_meshtastic_mesh.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""Tests for MeshtasticMeshInterface implementation."""

from unittest.mock import MagicMock, patch
from unittest.mock import MagicMock, create_autospec, patch

import pytest
from meshtastic.serial_interface import SerialInterface

from radio_telemetry_tracker_tower_comms_package.mesh_interface import MeshConnectionError
from radio_telemetry_tracker_tower_comms_package.meshtastic_mesh import MeshtasticMeshInterface
Expand All @@ -20,11 +21,11 @@ def test_meshtastic_mesh_connect_success(mock_serial_interface: MagicMock) -> No
mock_serial_interface.assert_called_once_with("test_device")


@pytest.mark.usefixtures("mock_serial_interface")
@patch("meshtastic.serial_interface.SerialInterface", side_effect=Exception("Port not found"))
def test_meshtastic_mesh_connect_failure() -> None:
"""Test handling of connection failure to Meshtastic device."""
mesh = MeshtasticMeshInterface(serial_device="nonexistent")
with pytest.raises(MeshConnectionError) as exc:
mesh.connect()
assert "Failed to connect" in str(exc.value) # noqa: S101
with patch("meshtastic.serial_interface.SerialInterface", create_autospec(SerialInterface)) as mock:
mock.side_effect = Exception("Port not found")
mesh = MeshtasticMeshInterface(serial_device="nonexistent")
with pytest.raises(MeshConnectionError) as exc:
mesh.connect()
assert "Failed to connect" in str(exc.value) # noqa: S101
6 changes: 3 additions & 3 deletions tests/test_tower_comms.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@
TEST_SAMPLE_RATE = 48000
TEST_CENTER_FREQ = 915000000
TEST_RUN_NUM = 999
TEST_PING_WIDTH = 15.0
TEST_MIN_SNR = 5.0
TEST_PING_WIDTH = 15
TEST_MIN_SNR = 5
TEST_MAX_LEN_MULT = 2.0
TEST_MIN_LEN_MULT = 1.0
TEST_TARGET_FREQS = [100, 200, 300]
TEST_PING_FREQ = 440.0
TEST_PING_FREQ = 440
TEST_PING_AMP = 0.75
TEST_PING_LAT = 37.0
TEST_PING_LON = -122.0
Expand Down

0 comments on commit 1ae1125

Please sign in to comment.