diff options
Diffstat (limited to 'openhop/repeater')
| -rw-r--r-- | openhop/repeater/defaults/main.yaml | 38 | ||||
| -rw-r--r-- | openhop/repeater/handlers/main.yaml | 8 | ||||
| -rw-r--r-- | openhop/repeater/tasks/main.yaml | 102 | ||||
| -rw-r--r-- | openhop/repeater/templates/config.yaml.j2 | 53 | ||||
| -rw-r--r-- | openhop/repeater/templates/openhop-repeater.service.j2 | 18 | ||||
| -rw-r--r-- | openhop/repeater/vars/boards/rak6421-slot1.yaml | 15 | ||||
| -rw-r--r-- | openhop/repeater/vars/boards/rak6421-slot2.yaml | 15 | ||||
| -rw-r--r-- | openhop/repeater/vars/rf/eu.yaml | 12 | ||||
| -rw-r--r-- | openhop/repeater/vars/rf/us.yaml | 11 |
9 files changed, 272 insertions, 0 deletions
diff --git a/openhop/repeater/defaults/main.yaml b/openhop/repeater/defaults/main.yaml new file mode 100644 index 0000000..d26e73e --- /dev/null +++ b/openhop/repeater/defaults/main.yaml @@ -0,0 +1,38 @@ +--- + +repeater_version: "1.1.1" +# https://github.com/openhop-dev/openhop_repeater/tags +# openhop_repeater is NOT on PyPI, so it installs from this git tag. +# Its dependency openhop_core[hardware] resolves from PyPI automatically. +repeater_repo: "https://github.com/openhop-dev/openhop_repeater" + +# Service layout — mirrors upstream's own systemd unit and docs. +repeater_user: "repeater" +repeater_venv_dir: "/opt/openhop_repeater/venv" +repeater_config_dir: "/etc/openhop_repeater" +repeater_data_dir: "/var/lib/openhop_repeater" + +# --- Node identity --- +repeater_node_name: "{{inventory_hostname}}" +repeater_latitude: 0.0 +repeater_longitude: 0.0 +repeater_owner_info: "" +# Path to the node's identity file (its MeshCore public/private keypair). The +# daemon generates one here on first boot and reuses it thereafter, so pointing +# this at persistent storage keeps a stable identity across reinstalls. Null +# lets the daemon generate an ephemeral identity each run. +repeater_identity_file: null + +# --- Hardware + RF presets (loaded by name from the role's vars/ dir) --- +# WARNING: the RAK13302 has a 1W SKY66122 PA. NEVER power the HAT without the +# antenna connected, or you risk destroying the radio front-end. +# +# repeater_board -> loads the pin map from vars/boards/<name>.yaml +# available: rak6421-slot1, rak6421-slot2 +# (add a new board by dropping another file in vars/boards/) +repeater_board: "rak6421-slot1" +# +# repeater_rf_preset -> loads the RF params from vars/rf/<name>.yaml +# available: us, eu +# (every node on a mesh must share the same RF preset) +repeater_rf_preset: "us" diff --git a/openhop/repeater/handlers/main.yaml b/openhop/repeater/handlers/main.yaml new file mode 100644 index 0000000..583691b --- /dev/null +++ b/openhop/repeater/handlers/main.yaml @@ -0,0 +1,8 @@ +--- + +- name: restart openhop-repeater + become: yes + systemd: + name: "openhop-repeater.service" + state: "restarted" + daemon_reload: "yes" diff --git a/openhop/repeater/tasks/main.yaml b/openhop/repeater/tasks/main.yaml new file mode 100644 index 0000000..b24044c --- /dev/null +++ b/openhop/repeater/tasks/main.yaml @@ -0,0 +1,102 @@ +--- + +- name: load board pin preset + include_vars: "boards/{{repeater_board}}.yaml" + +- name: load RF region preset + include_vars: "rf/{{repeater_rf_preset}}.yaml" + +- name: enable SPI for the LoRa HAT + become: yes + lineinfile: + path: "/boot/firmware/config.txt" + line: "dtparam=spi=on" + regexp: "^#?dtparam=spi=" + register: spi_result + +- name: remind to reboot for SPI to take effect + debug: + msg: "config.txt updated — reboot {{inventory_hostname}} for dtparam=spi=on to take effect" + when: spi_result.changed + +- name: apt install openhop repeater dependencies + become: yes + apt: + name: + - "git" + - "python3-venv" + - "python3-dev" + - "build-essential" + +- name: add openhop repeater user + become: yes + user: + name: "{{repeater_user}}" + system: "yes" + shell: "/bin/false" + home: "{{repeater_data_dir}}" + create_home: "no" + groups: "spi,gpio" + append: "yes" + +- name: create openhop repeater directories + become: yes + file: + path: "{{item.path}}" + state: "directory" + owner: "{{item.owner}}" + group: "{{item.owner}}" + mode: "{{item.mode}}" + loop: + - { path: "/opt/openhop_repeater", owner: "root", mode: "0755" } + - { path: "{{repeater_config_dir}}", owner: "root", mode: "0755" } + - { path: "{{repeater_data_dir}}", owner: "{{repeater_user}}", mode: "0750" } + +- name: check installed openhop_repeater version + become: yes + stat: + path: "{{repeater_venv_dir}}/.installed-{{repeater_version}}" + register: repeater_installed + +- name: install openhop_repeater into venv + become: yes + pip: + name: "git+{{repeater_repo}}@{{repeater_version}}" + virtualenv: "{{repeater_venv_dir}}" + virtualenv_command: "python3 -m venv" + when: not repeater_installed.stat.exists + notify: restart openhop-repeater + +- name: stamp installed openhop_repeater version + become: yes + copy: + dest: "{{repeater_venv_dir}}/.installed-{{repeater_version}}" + content: "{{repeater_version}}\n" + mode: "0644" + when: not repeater_installed.stat.exists + +- name: configure openhop repeater + become: yes + template: + src: "config.yaml.j2" + dest: "{{repeater_config_dir}}/config.yaml" + owner: "root" + group: "{{repeater_user}}" + mode: "0640" + notify: restart openhop-repeater + +- name: install openhop-repeater systemd service + become: yes + template: + src: "openhop-repeater.service.j2" + dest: "/lib/systemd/system/openhop-repeater.service" + mode: "0644" + notify: restart openhop-repeater + +- name: ensure openhop-repeater service is started + become: yes + systemd: + name: "openhop-repeater.service" + enabled: "yes" + state: "started" + daemon_reload: "yes" diff --git a/openhop/repeater/templates/config.yaml.j2 b/openhop/repeater/templates/config.yaml.j2 new file mode 100644 index 0000000..ddd2772 --- /dev/null +++ b/openhop/repeater/templates/config.yaml.j2 @@ -0,0 +1,53 @@ +# Managed by Ansible (openhop/repeater role) — do not edit by hand. + +repeater: + node_name: "{{ repeater_node_name }}" + latitude: {{ repeater_latitude }} + longitude: {{ repeater_longitude }} + identity_file: {{ ('"' + repeater_identity_file + '"') if repeater_identity_file else 'null' }} + owner_info: "{{ repeater_owner_info }}" + cache_ttl: 3600 + max_flood_hops: 64 + use_score_for_tx: false + score_threshold: 0.3 + send_advert_interval_hours: 10 + allow_discovery: true + +radio_type: sx1262 + +sx1262: + bus_id: {{ repeater_sx1262_bus_id }} + cs_id: {{ repeater_sx1262_cs_id }} + cs_pin: {{ repeater_sx1262_cs_pin }} + reset_pin: {{ repeater_sx1262_reset_pin }} + busy_pin: {{ repeater_sx1262_busy_pin }} + irq_pin: {{ repeater_sx1262_irq_pin }} + txen_pin: {{ repeater_sx1262_txen_pin }} + rxen_pin: {{ repeater_sx1262_rxen_pin }} + en_pin: -1 + txled_pin: -1 + rxled_pin: -1 + use_dio3_tcxo: {{ repeater_sx1262_use_dio3_tcxo | string | lower }} + dio3_tcxo_voltage: {{ repeater_sx1262_dio3_tcxo_voltage }} + use_dio2_rf: {{ repeater_sx1262_use_dio2_rf | string | lower }} + is_waveshare: {{ repeater_sx1262_is_waveshare | string | lower }} + +radio: + frequency: {{ repeater_frequency_hz }} + tx_power: {{ repeater_tx_power_dbm }} + bandwidth: {{ repeater_bandwidth_hz }} + spreading_factor: {{ repeater_spreading_factor }} + coding_rate: {{ repeater_coding_rate }} + preamble_length: {{ repeater_preamble_length }} + implicit_header: false + +# Observer/telemetry disabled — repeater-only deployment. +mqtt_brokers: + iata_code: "Test" + status_interval: 300 + brokers: [] + +glass: + enabled: false + base_url: "http://localhost:8080" + inform_interval_seconds: 30 diff --git a/openhop/repeater/templates/openhop-repeater.service.j2 b/openhop/repeater/templates/openhop-repeater.service.j2 new file mode 100644 index 0000000..53aa737 --- /dev/null +++ b/openhop/repeater/templates/openhop-repeater.service.j2 @@ -0,0 +1,18 @@ +[Unit] +Description=openHop MeshCore Repeater +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +User={{repeater_user}} +Group={{repeater_user}} +WorkingDirectory={{repeater_data_dir}} +ExecStart={{repeater_venv_dir}}/bin/python -m repeater.main --config {{repeater_config_dir}}/config.yaml +Restart=always +RestartSec=5 +StandardOutput=journal +StandardError=journal + +[Install] +WantedBy=multi-user.target diff --git a/openhop/repeater/vars/boards/rak6421-slot1.yaml b/openhop/repeater/vars/boards/rak6421-slot1.yaml new file mode 100644 index 0000000..464a194 --- /dev/null +++ b/openhop/repeater/vars/boards/rak6421-slot1.yaml @@ -0,0 +1,15 @@ +--- +# RAK6421 WisMesh Pi HAT — RAK13302 (SX1262 + 1W SKY66122 FEM) in SLOT 1. +# Source: meshtastic/firmware bin/config.d/lora-RAK6421-13302-slot1.yaml +repeater_sx1262_bus_id: 0 # spidev0.0 +repeater_sx1262_cs_id: 0 # CE0 (BCM 8) +repeater_sx1262_cs_pin: 8 +repeater_sx1262_reset_pin: 16 +repeater_sx1262_busy_pin: 24 +repeater_sx1262_irq_pin: 22 # DIO1 +repeater_sx1262_use_dio3_tcxo: true +repeater_sx1262_dio3_tcxo_voltage: 1.8 +repeater_sx1262_use_dio2_rf: true +repeater_sx1262_txen_pin: 12 # SKY66122 FEM enable (verify TX vs RX) +repeater_sx1262_rxen_pin: 13 # SKY66122 FEM enable (verify TX vs RX) +repeater_sx1262_is_waveshare: false diff --git a/openhop/repeater/vars/boards/rak6421-slot2.yaml b/openhop/repeater/vars/boards/rak6421-slot2.yaml new file mode 100644 index 0000000..71a5fb9 --- /dev/null +++ b/openhop/repeater/vars/boards/rak6421-slot2.yaml @@ -0,0 +1,15 @@ +--- +# RAK6421 WisMesh Pi HAT — RAK13302 (SX1262 + 1W SKY66122 FEM) in SLOT 2. +# Source: meshtastic/firmware bin/config.d/lora-RAK6421-13302-slot2.yaml +repeater_sx1262_bus_id: 0 # spidev0.1 +repeater_sx1262_cs_id: 1 # CE1 (BCM 7) +repeater_sx1262_cs_pin: 7 +repeater_sx1262_reset_pin: 24 +repeater_sx1262_busy_pin: 19 +repeater_sx1262_irq_pin: 18 # DIO1 +repeater_sx1262_use_dio3_tcxo: true +repeater_sx1262_dio3_tcxo_voltage: 1.8 +repeater_sx1262_use_dio2_rf: true +repeater_sx1262_txen_pin: 26 # SKY66122 FEM enable (verify TX vs RX) +repeater_sx1262_rxen_pin: 23 # SKY66122 FEM enable (verify TX vs RX) +repeater_sx1262_is_waveshare: false diff --git a/openhop/repeater/vars/rf/eu.yaml b/openhop/repeater/vars/rf/eu.yaml new file mode 100644 index 0000000..11fca12 --- /dev/null +++ b/openhop/repeater/vars/rf/eu.yaml @@ -0,0 +1,12 @@ +--- +# MeshCore EU 863-870 MHz preset. +# WARNING: every node on your mesh MUST share identical frequency / bandwidth / +# spreading_factor / coding_rate. Confirm these against your local +# MeshCore EU community settings, and respect the sub-band duty-cycle / +# power limits before deploying. +repeater_frequency_hz: 869525000 # 869.525 MHz +repeater_bandwidth_hz: 250000 +repeater_spreading_factor: 11 # 7-12 +repeater_coding_rate: 5 # 5-8 +repeater_preamble_length: 32 +repeater_tx_power_dbm: 14 # keep within the chosen EU sub-band limit diff --git a/openhop/repeater/vars/rf/us.yaml b/openhop/repeater/vars/rf/us.yaml new file mode 100644 index 0000000..e20b1c6 --- /dev/null +++ b/openhop/repeater/vars/rf/us.yaml @@ -0,0 +1,11 @@ +--- +# MeshCore US 902-928 MHz preset. +# WARNING: every node on your mesh MUST share identical frequency / bandwidth / +# spreading_factor / coding_rate. Confirm these against your local +# MeshCore US community settings before deploying. +repeater_frequency_hz: 910525000 # 910.525 MHz +repeater_bandwidth_hz: 250000 +repeater_spreading_factor: 11 # 7-12 +repeater_coding_rate: 5 # 5-8 +repeater_preamble_length: 32 +repeater_tx_power_dbm: 22 # SX1262 register max; SKY66122 boosts to ~1W |
