Skip to content
Open
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
14 changes: 14 additions & 0 deletions .github/instructions/snyk_rules.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
alwaysApply: true
always_on: true
trigger: always_on
applyTo: "**"
description: Snyk Security At Inception
---

# Project security best practices

- Always run snyk_code_scan tool for new first party code that is generated in a Snyk-supported language.
- If any security issues are found based on newly introduced or modified code or dependencies, attempt to fix the issues using the results context from Snyk.
- Rescan the code after fixing the issues to ensure that the issues were fixed and that there are no newly introduced issues.
- Repeat this process until no new issues are found.
8 changes: 8 additions & 0 deletions manage.sh
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ is_running() {
systemctl is-active "$SERVICE_NAME" >/dev/null 2>&1
}

# Function to check if service is enabled
is_enabled() {
systemctl is-enabled "$SERVICE_NAME" >/dev/null 2>&1
}

# Function to get current version
get_version() {
# Try to read from _version.py first (generated by setuptools_scm)
Expand Down Expand Up @@ -638,6 +643,9 @@ manage_service() {

case $action in
"start")
if ! is_enabled; then
systemctl enable "$SERVICE_NAME"
fi
systemctl start "$SERVICE_NAME"
if is_running; then
show_info "Service Started" "\n✓ pyMC Repeater service has been started successfully."
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ keywords = ["mesh", "networking", "lora", "repeater", "daemon", "iot"]


dependencies = [
"pymc_core[hardware] @ git+https://github.com/rightup/pyMC_core.git@dev",
"pymc_core[hardware] @ git+https://github.com/theshaun/pyMC_core.git@dev",
"pyyaml>=6.0.0",
"cherrypy>=18.0.0",
"paho-mqtt>=1.6.0",
Expand Down
152 changes: 151 additions & 1 deletion radio-presets.json
Original file line number Diff line number Diff line change
@@ -1 +1,151 @@
{"config":{"connect_screen":{"info_message":"The default pin for devices without a screen is 123456. Trouble pairing? Forget the bluetooth device in system settings."},"remote_management":{"repeaters":{"guest_login_enabled":true,"guest_login_disabled_message":"Guest login has been temporarily disabled. Please try again later.","guest_login_passwords":[""],"flood_routed_guest_login_enabled":true,"flood_routed_guest_login_disabled_message":"To avoid overwhelming the mesh with flood packets, please set a path to log in to a repeater as a guest."}},"suggested_radio_settings":{"info_message":"These radio settings have been suggested by the community.","entries":[{"title":"Australia","description":"915.800MHz / SF10 / BW250 / CR5","frequency":"915.800","spreading_factor":"10","bandwidth":"250","coding_rate":"5"},{"title":"Australia: Victoria","description":"916.575MHz / SF7 / BW62.5 / CR8","frequency":"916.575","spreading_factor":"7","bandwidth":"62.5","coding_rate":"8"},{"title":"EU/UK (Narrow)","description":"869.618MHz / SF8 / BW62.5 / CR8","frequency":"869.618","spreading_factor":"8","bandwidth":"62.5","coding_rate":"8"},{"title":"EU/UK (Long Range)","description":"869.525MHz / SF11 / BW250 / CR5","frequency":"869.525","spreading_factor":"11","bandwidth":"250","coding_rate":"5"},{"title":"EU/UK (Medium Range)","description":"869.525MHz / SF10 / BW250 / CR5","frequency":"869.525","spreading_factor":"10","bandwidth":"250","coding_rate":"5"},{"title":"Czech Republic (Narrow)","description":"869.525MHz / SF7 / BW62.5 / CR5","frequency":"869.525","spreading_factor":"7","bandwidth":"62.5","coding_rate":"5"},{"title":"EU 433MHz (Long Range)","description":"433.650MHz / SF11 / BW250 / CR5","frequency":"433.650","spreading_factor":"11","bandwidth":"250","coding_rate":"5"},{"title":"New Zealand","description":"917.375MHz / SF11 / BW250 / CR5","frequency":"917.375","spreading_factor":"11","bandwidth":"250","coding_rate":"5"},{"title":"New Zealand (Narrow)","description":"917.375MHz / SF7 / BW62.5 / CR5","frequency":"917.375","spreading_factor":"7","bandwidth":"62.5","coding_rate":"5"},{"title":"Portugal 433","description":"433.375MHz / SF9 / BW62.5 / CR6","frequency":"433.375","spreading_factor":"9","bandwidth":"62.5","coding_rate":"6"},{"title":"Portugal 868","description":"869.618MHz / SF7 / BW62.5 / CR6","frequency":"869.618","spreading_factor":"7","bandwidth":"62.5","coding_rate":"6"},{"title":"Switzerland","description":"869.618MHz / SF8 / BW62.5 / CR8","frequency":"869.618","spreading_factor":"8","bandwidth":"62.5","coding_rate":"8"},{"title":"USA/Canada (Recommended)","description":"910.525MHz / SF7 / BW62.5 / CR5","frequency":"910.525","spreading_factor":"7","bandwidth":"62.5","coding_rate":"5"},{"title":"USA/Canada (Alternate)","description":"910.525MHz / SF11 / BW250 / CR5","frequency":"910.525","spreading_factor":"11","bandwidth":"250","coding_rate":"5"},{"title":"Vietnam","description":"920.250MHz / SF11 / BW250 / CR5","frequency":"920.250","spreading_factor":"11","bandwidth":"250","coding_rate":"5"}]}}}
{
"config": {
"connect_screen": {
"info_message": "The default pin for devices without a screen is 123456. Trouble pairing? Forget the bluetooth device in system settings."
},
"remote_management": {
"repeaters": {
"guest_login_enabled": true,
"guest_login_disabled_message": "Guest login has been temporarily disabled. Please try again later.",
"guest_login_passwords": [
""
],
"flood_routed_guest_login_enabled": true,
"flood_routed_guest_login_disabled_message": "To avoid overwhelming the mesh with flood packets, please set a path to log in to a repeater as a guest."
}
},
"suggested_radio_settings": {
"info_message": "These radio settings have been suggested by the community.",
"entries": [
{
"title": "Australia",
"description": "915.800MHz / SF10 / BW250 / CR5",
"frequency": "915.800",
"spreading_factor": "10",
"bandwidth": "250",
"coding_rate": "5"
},
{
"title": "Australia (Narrow)",
"description": "916.575MHz / SF7 / BW62.5 / CR8",
"frequency": "916.575",
"spreading_factor": "7",
"bandwidth": "62.5",
"coding_rate": "8"
},
{
"title": "Australia: SA, WA, QLD",
"description": "923.125MHz / SF8 / BW62.5 / CR8",
"frequency": "923.125",
"spreading_factor": "8",
"bandwidth": "62.5",
"coding_rate": "8"
},
{
"title": "EU/UK (Narrow)",
"description": "869.618MHz / SF8 / BW62.5 / CR8",
"frequency": "869.618",
"spreading_factor": "8",
"bandwidth": "62.5",
"coding_rate": "8"
},
{
"title": "EU/UK (Long Range)",
"description": "869.525MHz / SF11 / BW250 / CR5",
"frequency": "869.525",
"spreading_factor": "11",
"bandwidth": "250",
"coding_rate": "5"
},
{
"title": "EU/UK (Medium Range)",
"description": "869.525MHz / SF10 / BW250 / CR5",
"frequency": "869.525",
"spreading_factor": "10",
"bandwidth": "250",
"coding_rate": "5"
},
{
"title": "Czech Republic (Narrow)",
"description": "869.525MHz / SF7 / BW62.5 / CR5",
"frequency": "869.525",
"spreading_factor": "7",
"bandwidth": "62.5",
"coding_rate": "5"
},
{
"title": "EU 433MHz (Long Range)",
"description": "433.650MHz / SF11 / BW250 / CR5",
"frequency": "433.650",
"spreading_factor": "11",
"bandwidth": "250",
"coding_rate": "5"
},
{
"title": "New Zealand",
"description": "917.375MHz / SF11 / BW250 / CR5",
"frequency": "917.375",
"spreading_factor": "11",
"bandwidth": "250",
"coding_rate": "5"
},
{
"title": "New Zealand (Narrow)",
"description": "917.375MHz / SF7 / BW62.5 / CR5",
"frequency": "917.375",
"spreading_factor": "7",
"bandwidth": "62.5",
"coding_rate": "5"
},
{
"title": "Portugal 433",
"description": "433.375MHz / SF9 / BW62.5 / CR6",
"frequency": "433.375",
"spreading_factor": "9",
"bandwidth": "62.5",
"coding_rate": "6"
},
{
"title": "Portugal 868",
"description": "869.618MHz / SF7 / BW62.5 / CR6",
"frequency": "869.618",
"spreading_factor": "7",
"bandwidth": "62.5",
"coding_rate": "6"
},
{
"title": "Switzerland",
"description": "869.618MHz / SF8 / BW62.5 / CR8",
"frequency": "869.618",
"spreading_factor": "8",
"bandwidth": "62.5",
"coding_rate": "8"
},
{
"title": "USA/Canada (Recommended)",
"description": "910.525MHz / SF7 / BW62.5 / CR5",
"frequency": "910.525",
"spreading_factor": "7",
"bandwidth": "62.5",
"coding_rate": "5"
},
{
"title": "USA/Canada (Alternate)",
"description": "910.525MHz / SF11 / BW250 / CR5",
"frequency": "910.525",
"spreading_factor": "11",
"bandwidth": "250",
"coding_rate": "5"
},
{
"title": "Vietnam",
"description": "920.250MHz / SF11 / BW250 / CR5",
"frequency": "920.250",
"spreading_factor": "11",
"bandwidth": "250",
"coding_rate": "5"
}
]
}
}
}
18 changes: 18 additions & 0 deletions radio-settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,24 @@
"use_dio3_tcxo": true,
"use_dio2_rf": true,
"preamble_length": 17
},
"femtofox-1W-SX": {
"name": "FemtoFox SX1262 (1W)",
"bus_id": 0,
"cs_id": 0,
"cs_pin": 16,
"gpio_chip": 1,
"use_gpiod_backend": true,
"reset_pin": 25,
"busy_pin": 22,
"irq_pin": 23,
"txen_pin": -1,
"rxen_pin": 24,
"txled_pin": -1,
"rxled_pin": -1,
"tx_power": 30,
"use_dio3_tcxo": true,
"preamble_length": 17
}
}
}
6 changes: 3 additions & 3 deletions repeater/airtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,17 @@ def calculate_airtime(
Airtime in milliseconds
"""
sf = spreading_factor or self.spreading_factor
bw_khz = (bandwidth_hz or self.bandwidth) / 1000
bw_hz = (bandwidth_hz or self.bandwidth)
cr = coding_rate or self.coding_rate
preamble_len = preamble_len or self.preamble_length
crc = 1 if crc_enabled else 0
h = 0 if explicit_header else 1 # H=0 for explicit, H=1 for implicit

# Low data rate optimization: required for SF11/SF12 at 125kHz
de = 1 if (sf >= 11 and bandwidth_hz <= 125000) else 0
de = 1 if (sf >= 11 and bw_hz <= 125000) else 0

# Symbol time in milliseconds: T_sym = 2^SF / BW_kHz
t_sym = (2 ** sf) / bw_khz
t_sym = (2 ** sf) / (bw_hz / 1000)

# Preamble time: T_preamble = (n_preamble + 4.25) * T_sym
t_preamble = (preamble_len + 4.25) * t_sym
Expand Down
2 changes: 2 additions & 0 deletions repeater/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ def get_radio_for_board(board_config: dict):
"bus_id": spi_config["bus_id"],
"cs_id": spi_config["cs_id"],
"cs_pin": spi_config["cs_pin"],
"gpio_chip": spi_config.get("gpio_chip", 0),
"use_gpiod_backend": spi_config.get("use_gpiod_backend", False),
"reset_pin": spi_config["reset_pin"],
"busy_pin": spi_config["busy_pin"],
"irq_pin": spi_config["irq_pin"],
Expand Down
8 changes: 7 additions & 1 deletion repeater/data_acquisition/letsmesh_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,17 @@
import paho.mqtt.client as mqtt
import threading

from datetime import datetime, timedelta, UTC
from datetime import datetime, timedelta
from nacl.signing import SigningKey
from typing import Callable, Optional, List, Dict
from .. import __version__

# Try to import datetime.UTC (Python 3.11+) otherwise fallback to timezone.utc
try:
from datetime import UTC
except Exception:
from datetime import timezone
UTC = timezone.utc

# Try to import paho-mqtt error code mappings
try:
Expand Down