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
5 changes: 5 additions & 0 deletions .github/workflows/python-smoke.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ on:
push:
paths:
- "custom_components/**"
- "tests/**"
- "hacs.json"
- ".github/workflows/python-smoke.yaml"
pull_request:
paths:
- "custom_components/**"
- "tests/**"
- "hacs.json"
- ".github/workflows/python-smoke.yaml"
release:
Expand Down Expand Up @@ -40,3 +42,6 @@ jobs:

- name: Compile integration
run: python -m compileall custom_components/pymc_repeater

- name: Run contract tests
run: python -m unittest discover -s tests -v
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Changelog

## 1.1.6

- changed the integration-wide API refresh interval to a configurable option, defaulting to 15 seconds
- fixed GPS stream updates so they notify entities without continually postponing the coordinator's regular API refresh
- added support for Repeater dev neighbor-link snapshots and history, including aggregate Home Assistant diagnostics and response-returning actions
- added the Repeater dev manual CAD check action and aligned calibration options with known-signal, CAD symbol count, and timeout controls
- exposed the Repeater metrics storage source and RRD availability diagnostics introduced by the SQLite metrics fallback
- added contract tests for the new Repeater dev API coverage and run them in the Python smoke workflow
- renamed the example dashboard to `openhop_repeater_dashboard.yaml` and replaced it with an anonymized, single-placeholder view covering current telemetry, controls, external modem data, neighbor links, and metrics diagnostics
- reworked the README with relevant HACS, release, openHop Discord, validation, and test badges; streamlined installation and setup guidance; documented options, actions, dashboard use, persistent token storage, and community links
- updated the Python smoke workflow to `actions/setup-python@v7`

## 1.1.5

- fixed the Home Assistant options flow crash on newer Home Assistant versions by avoiding assignment to the read-only `OptionsFlow.config_entry` property
Expand Down
237 changes: 137 additions & 100 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,145 +1,182 @@
# openHop Repeater for Home Assistant
<p align="center">
<img src="custom_components/pymc_repeater/brand/icon.png" alt="openHop Repeater" width="150">
</p>

Custom Home Assistant integration for [openHop Repeater](https://github.com/openhop-dev/openhop_repeater).
<h1 align="center">openHop Repeater Integration for Home Assistant</h1>

This integration connects directly to the repeater's local HTTP API, signs in once with the admin password, creates a dedicated API token for Home Assistant, and then uses that token for ongoing polling and history-friendly logging inside HA.
<p align="center">
Monitor and control an <a href="https://github.com/openhop-dev/openhop_repeater">openHop Repeater</a> from Home Assistant.
</p>

The Home Assistant integration domain and folder remain `pymc_repeater` for compatibility with existing installations while the user-facing brand is openHop Repeater.
<p align="center">
<a href="https://github.com/hacs/integration"><img src="https://img.shields.io/badge/HACS-Custom-41BDF5?style=for-the-badge&logo=homeassistantcommunitystore&logoColor=white" alt="HACS Custom"></a>
<a href="https://github.com/openhop-dev/openHop-HA-Integration/releases"><img src="https://img.shields.io/github/v/release/openhop-dev/openHop-HA-Integration?style=for-the-badge" alt="Latest release"></a>
<a href="https://discord.gg/3s8MMaSTzq"><img src="https://img.shields.io/discord/1489331292309946508?style=for-the-badge&logo=discord&logoColor=white&label=Discord&color=5865F2" alt="openHop Discord"></a>
</p>

## Features
<p align="center">
<a href="https://github.com/openhop-dev/openHop-HA-Integration/actions/workflows/hacs.yaml"><img src="https://img.shields.io/github/actions/workflow/status/openhop-dev/openHop-HA-Integration/hacs.yaml?branch=main&style=for-the-badge&label=HACS" alt="HACS validation"></a>
<a href="https://github.com/openhop-dev/openHop-HA-Integration/actions/workflows/hassfest.yaml"><img src="https://img.shields.io/github/actions/workflow/status/openhop-dev/openHop-HA-Integration/hassfest.yaml?branch=main&style=for-the-badge&label=Hassfest" alt="Hassfest"></a>
<a href="https://github.com/openhop-dev/openHop-HA-Integration/actions/workflows/python-smoke.yaml"><img src="https://img.shields.io/github/actions/workflow/status/openhop-dev/openHop-HA-Integration/python-smoke.yaml?branch=main&style=for-the-badge&label=Tests" alt="Tests"></a>
</p>

- UI config flow inside Home Assistant
- Prompts for repeater IP or hostname, port, and admin password
- Automatically creates a dedicated API token for Home Assistant
- Stores the API token instead of the admin password after setup
- Polls repeater telemetry, packet stats, radio metrics, hardware stats, database stats, MQTT status, ACL stats, identity totals, and configured Repeater sensor-manager readings
- Exposes Home Assistant sensors and binary sensors for easy dashboards, history graphs, and automations
## About

This custom integration connects Home Assistant directly to the Repeater's local HTTP API. During setup it signs in once with the Repeater admin password, creates a dedicated API token, stores that token in the Home Assistant config entry, and discards the admin password.

The integration uses coordinated local polling instead of making a separate API request for every entity. The polling interval is configurable in the integration options and defaults to 15 seconds.

> [!NOTE]
> The integration domain and folder remain `pymc_repeater` so existing installations and entity registry entries continue to work. The user-facing name is **openHop Repeater**.

## Highlights

- UI-based setup and options flows
- Configurable integration-wide polling interval
- Repeater, radio, packet, routing, and signal-quality telemetry
- MQTT broker and handler status
- Hardware, process, network, database, and metrics diagnostics
- GPS position, fix, satellite, time-sync, and location-update data
- External sensor-manager entities, including supported modem and UPS readings
- Neighbor-link counts and on-demand neighbor history
- Default-region, duty-cycle, advert-rate, and Repeater-mode controls
- Update status, update-channel selection, and update actions
- CAD calibration controls and manual CAD checks
- Native Home Assistant diagnostics and an extensive example dashboard

## Requirements

- A running [openHop Repeater](https://github.com/openhop-dev/openhop_repeater) instance
- The repeater web/API port reachable from Home Assistant
- The repeater admin password
- A trusted local network, VPN, or other secure path between Home Assistant and the repeater
- Home Assistant 2024.1 or newer
- A running [openHop Repeater](https://github.com/openhop-dev/openhop_repeater)
- The Repeater HTTP API reachable from Home Assistant
- The Repeater admin password for initial setup or reauthentication
- A trusted local network, VPN, or another secure path between Home Assistant and the Repeater

## Installation

### Install with HACS
### HACS

[![Open your Home Assistant instance and add this repository to HACS.](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?owner=openhop-dev&repository=openHop-HA-Integration&category=Integration)

This integration is intended to be installed in HACS as a custom repository.
This integration is currently installed as a HACS custom repository:

1. Open Home Assistant.
2. Go to `HACS` -> `Integrations`.
3. Open the top-right menu and select `Custom repositories`.
4. Paste:
1. Open **HACS → Integrations**.
2. Open the top-right menu and select **Custom repositories**.
3. Add:

```text
https://github.com/openhop-dev/openHop-HA-Integration
```

5. Choose `Integration` as the category.
6. Add the repository.
7. Find `openHop Repeater` in HACS and install it.
8. Restart Home Assistant.
4. Select **Integration** as the category.
5. Install **openHop Repeater**.
6. Restart Home Assistant.

### Manual installation

1. Copy the `custom_components/pymc_repeater` folder into your Home Assistant config directory:
1. Download the latest release.
2. Copy `custom_components/pymc_repeater` into your Home Assistant configuration directory:

```text
/config/custom_components/pymc_repeater
```

2. Your final layout should look like this:

```text
/config/custom_components/pymc_repeater/__init__.py
/config/custom_components/pymc_repeater/manifest.json
/config/custom_components/pymc_repeater/config_flow.py
...
```

3. Restart Home Assistant.

## Setup inside Home Assistant
## Setup

After installation and restart:

1. Open `Settings` -> `Devices & Services`.
2. Click `Add Integration`.
3. Search for `openHop Repeater`.
4. Enter:
- Repeater IP address or hostname
- Repeater HTTP API port
- Repeater admin password
5. Click `Submit`.
1. Open **Settings → Devices & services**.
2. Select **Add integration**.
3. Search for **openHop Repeater**.
4. Enter the Repeater hostname or IP address, HTTP API port, and admin password.
5. Submit the form.

Home Assistant will create and retain a dedicated API token. The admin password is not stored after setup completes.

### Integration options

During setup the integration will:
Open **Settings → Devices & services → openHop Repeater → Configure** to change:

1. Connect to the repeater API
2. Sign in as `admin`
3. Create a dedicated API token for Home Assistant
4. Save that token in the config entry
5. Discard the admin password after the setup flow finishes
6. Start polling repeater data automatically
- Integration polling interval, defaulting to 15 seconds
- Data-size display unit
- Uptime display unit

Changing an option reloads the integration automatically.

## Dashboard template

A native Lovelace dashboard template is included at:
A comprehensive native Lovelace view is included at:

[`dashboards/openhop_repeater_dashboard.yaml`](dashboards/openhop_repeater_dashboard.yaml)

- `dashboards/pymc_repeater_dashboard.yaml`
The template covers radio health, packet flow, LBT diagnostics, routing, neighbor links, controls, advert tuning, MQTT, companions, GPS, external modem readings, updates, and database metrics.

To use it:

1. Open the YAML file from this repo.
2. Replace `REPEATER_SLUG` with your actual entity prefix.
Example: `repeater_name_here`
3. In Home Assistant, create a new dashboard or open an existing one in raw YAML mode.
4. Paste the template YAML.
5. Update the example MQTT broker and companion entity rows in the `Network` view so they match the dynamic entities created in your installation.

The template only uses built-in Home Assistant cards, so it does not require extra frontend dependencies.

## Security notes

- The repeater API is currently accessed over `http://`
- Use this integration only on a trusted network, or place both systems behind a VPN or another secure transport boundary
- If the API token is revoked on the repeater, Home Assistant should trigger reauthentication

## Repository structure

```text
custom_components/pymc_repeater/
__init__.py
api.py
binary_sensor.py
config_flow.py
const.py
coordinator.py
diagnostics.py
manifest.json
sensor.py
translations/en.json
brand/icon.png
brand/icon@2x.png
dashboards/
pymc_repeater_dashboard.yaml
hacs.json
README.md
1. Find one Repeater entity in Home Assistant, such as `sensor.my_repeater_repeater_version`.
2. Copy the entity prefix—in this example, `my_repeater`.
3. Replace every `REPEATER_SLUG` in the template with that prefix.
4. Create or edit a dashboard view and paste the template into the view's YAML editor.
5. Optionally change the view `title` and `path`.
6. Replace the marked example MQTT broker and companion rows with entities from your installation.
7. If your external sensor is not named `modem`, replace `_sensor_modem_` with its actual sensor slug.

The dashboard uses only built-in Home Assistant cards.

## Actions

The integration exposes Home Assistant actions for supported Repeater operations, including:

- Sending adverts and restarting the Repeater service
- Checking for and installing updates
- Reading broker presets and neighbor-link history
- Running manual CAD checks and CAD calibration
- Saving CAD settings
- Reading advert, companion, and contact diagnostics

Open **Developer tools → Actions** and search for `openHop Repeater` or `pymc_repeater` to see the actions and their current fields.

## Authentication and persistent storage

The Home Assistant integration stores an API token, while the Repeater stores the matching token hash in its SQLite database. Both the Repeater JWT secret and SQLite database must persist across Repeater restarts.

For the openHop Home Assistant add-on, use the persistent openHop storage path:

```yaml
storage:
storage_dir: /var/lib/openhop_repeater
```

## Development notes
Using the legacy, unmapped `/var/lib/pymc_repeater` path in the renamed add-on can cause the API-token database to disappear when the add-on restarts. The integration will then report `Authentication failed for /api/stats` and request reauthentication.

Do not publish your admin password, JWT secret, Home Assistant token, or Repeater API token in an issue or diagnostic upload.

- The config flow follows current Home Assistant custom integration patterns with `manifest.json`, `config_flow.py`, and `translations/en.json`
- The integration uses coordinated polling rather than per-entity API calls
- The client implementation matches the current [openHop Repeater](https://github.com/openhop-dev/openhop_repeater) auth flow:
- `POST /auth/login`
- `POST /api/auth/tokens`
- ongoing reads with `X-API-Key`
## Security

- The Repeater API is currently accessed over plain `http://`.
- Keep Home Assistant and the Repeater on a trusted network, behind a VPN, or within another secure transport boundary.
- Revoke unused Home Assistant API tokens from the Repeater.
- If a token is revoked or no longer validates, Home Assistant starts its standard reauthentication flow.

## Community and related projects

- [Join the openHop Discord](https://discord.gg/3s8MMaSTzq)
- [openHop Repeater](https://github.com/openhop-dev/openhop_repeater)
- [openHop Repeater Home Assistant add-on](https://github.com/openhop-dev/openHop-HA-Add-on)
- [Release notes](CHANGELOG.md)
- [Issue tracker](https://github.com/openhop-dev/openHop-HA-Integration/issues)

## Development

The repository includes HACS validation, Hassfest, Python compilation, and contract tests. To run the local checks:

```bash
python3 -m unittest discover -s tests -v
python3 -m compileall -q custom_components/pymc_repeater
```

## Releases
Release versions are defined in `custom_components/pymc_repeater/manifest.json` and documented in [`CHANGELOG.md`](CHANGELOG.md).

- The integration version is defined in `custom_components/pymc_repeater/manifest.json`
- GitHub Actions validate HACS compatibility, Hassfest, and a Python smoke test on every push and pull request
- Dependabot monitors the workflow dependencies automatically
- For the first stable release, create a Git tag and GitHub release for `v1.0.0`
Contributions and focused bug reports are welcome. Please include the Home Assistant version, integration version, Repeater version, and relevant redacted logs when reporting a problem.
Loading