Hello, Here in Oregon, we have 28 repeaters that connect the Southern half of the state. Trying to figure out how to monitor these in the overnight hours when mesh activity is low? Do we run multiple versions of remote term? is there another way to do this or a special update that would allow this?
Hello, Here in Oregon, we have 28 repeaters that connect the Southern half of the state. Trying to figure out how to monitor these in the overnight hours when mesh activity is low? Do we run multiple versions of remote term? is there another way to do this or a special update that would allow this?
<!-- github-sync-id:4309424651 -->
Hey there! I think we've corresponded via email. Nope, no need to run multiple instances of RemoteTerm. The API, actuated by a script, will let you issue whatever commands you want to as many repeaters as you want, whenever you want. From the interactive/GUI side of things, though, the application is capped at eight in order to limit automated traffic being spewed onto the mesh for stability reasons. The API is open so that people can do whatever they want with the interface, but the super-easily-accessible parts via the GUI is more limited to not make it trivial to issue mesh-destabilizing amounts of traffic.
The below script provides the bones of a basic script for fetching repeater telemetry; with some minor adjustments or LLM assistance that should be trivial to adapt to provide whatever pattern or volume of repeater tracking you need.
#!/usr/bin/env python3"""Poll a RemoteTerm repeater for status + sensor telemetry and log to CSV.
pip install requests
python fetch_telemetry_on_interval.py
"""importcsvimporttimefrompathlibimportPathimportrequests# ── Configure these ──────────────────────────────────────────────────────────BASE_URL="http://localhost:8000"REPEATER_PUBKEY="put_your_64char_hex_public_key_here"PASSWORD=""# empty string for guest loginPOLL_INTERVAL=60# seconds between samplesCSV_PATH=Path("repeater_log.csv")# ─────────────────────────────────────────────────────────────────────────────deflogin():r=requests.post(f"{BASE_URL}/api/contacts/{REPEATER_PUBKEY}/repeater/login",json={"password":PASSWORD},timeout=30,)r.raise_for_status()deffetch_status():r=requests.post(f"{BASE_URL}/api/contacts/{REPEATER_PUBKEY}/repeater/status",timeout=30,)r.raise_for_status()returnr.json()deffetch_lpp():r=requests.post(f"{BASE_URL}/api/contacts/{REPEATER_PUBKEY}/repeater/lpp-telemetry",timeout=30,)r.raise_for_status()returnr.json()["sensors"]defcollect_sample():status=fetch_status()row={"timestamp":time.strftime("%Y-%m-%dT%H:%M:%S")}# Status telemetryforfieldin["battery_volts","noise_floor_dbm","last_rssi_dbm","last_snr_db","uptime_seconds","packets_received","packets_sent","airtime_seconds","sent_flood","sent_direct","recv_flood","recv_direct",]:row[field]=status.get(field)# LPP sensors (best-effort — not all repeaters have these)try:forsensorinfetch_lpp():ifnotisinstance(sensor.get("value"),dict):row[f"lpp_{sensor['type_name']}"]=sensor["value"]exceptException:passreturnrowdefmain():print(f"Logging in to repeater {REPEATER_PUBKEY[:12]}...")login()print("OK\n")first=collect_sample()columns=list(first.keys())file_exists=CSV_PATH.exists()csv_file=open(CSV_PATH,"a",newline="")writer=csv.DictWriter(csv_file,fieldnames=columns,extrasaction="ignore")ifnotfile_exists:writer.writeheader()print(f"Writing to {CSV_PATH} (Ctrl-C to stop)\n")# Write first sample, then looprow=firstwhileTrue:parts=[f"{k}={v}"fork,vinrow.items()ifk!="timestamp"]print(f"[{row['timestamp']}] {' '.join(parts)}")writer.writerow(row)csv_file.flush()time.sleep(POLL_INTERVAL)try:row=collect_sample()exceptExceptionase:print(f"[{time.strftime('%H:%M:%S')}] Error: {e}")if__name__=="__main__":try:main()exceptKeyboardInterrupt:print("\nStopped.")
Hey there! I think we've corresponded via email. Nope, no need to run multiple instances of RemoteTerm. The API, actuated by a script, will let you issue whatever commands you want to as many repeaters as you want, whenever you want. From the interactive/GUI side of things, though, the application is capped at eight in order to limit automated traffic being spewed onto the mesh for stability reasons. The API is open so that people can do whatever they want with the interface, but the super-easily-accessible parts via the GUI is more limited to not make it trivial to issue mesh-destabilizing amounts of traffic.
~~https://github.com/jkingsman/Remote-Terminal-for-MeshCore/issues/32#issuecomment-3985636666~~ (that was out of date)
The below script provides the bones of a basic script for fetching repeater telemetry; with some minor adjustments or LLM assistance that should be trivial to adapt to provide whatever pattern or volume of repeater tracking you need.
```python
#!/usr/bin/env python3
"""Poll a RemoteTerm repeater for status + sensor telemetry and log to CSV.
pip install requests
python fetch_telemetry_on_interval.py
"""
import csv
import time
from pathlib import Path
import requests
# ── Configure these ──────────────────────────────────────────────────────────
BASE_URL = "http://localhost:8000"
REPEATER_PUBKEY = "put_your_64char_hex_public_key_here"
PASSWORD = "" # empty string for guest login
POLL_INTERVAL = 60 # seconds between samples
CSV_PATH = Path("repeater_log.csv")
# ─────────────────────────────────────────────────────────────────────────────
def login():
r = requests.post(
f"{BASE_URL}/api/contacts/{REPEATER_PUBKEY}/repeater/login",
json={"password": PASSWORD},
timeout=30,
)
r.raise_for_status()
def fetch_status():
r = requests.post(
f"{BASE_URL}/api/contacts/{REPEATER_PUBKEY}/repeater/status",
timeout=30,
)
r.raise_for_status()
return r.json()
def fetch_lpp():
r = requests.post(
f"{BASE_URL}/api/contacts/{REPEATER_PUBKEY}/repeater/lpp-telemetry",
timeout=30,
)
r.raise_for_status()
return r.json()["sensors"]
def collect_sample():
status = fetch_status()
row = {"timestamp": time.strftime("%Y-%m-%dT%H:%M:%S")}
# Status telemetry
for field in [
"battery_volts",
"noise_floor_dbm",
"last_rssi_dbm",
"last_snr_db",
"uptime_seconds",
"packets_received",
"packets_sent",
"airtime_seconds",
"sent_flood",
"sent_direct",
"recv_flood",
"recv_direct",
]:
row[field] = status.get(field)
# LPP sensors (best-effort — not all repeaters have these)
try:
for sensor in fetch_lpp():
if not isinstance(sensor.get("value"), dict):
row[f"lpp_{sensor['type_name']}"] = sensor["value"]
except Exception:
pass
return row
def main():
print(f"Logging in to repeater {REPEATER_PUBKEY[:12]}...")
login()
print("OK\n")
first = collect_sample()
columns = list(first.keys())
file_exists = CSV_PATH.exists()
csv_file = open(CSV_PATH, "a", newline="")
writer = csv.DictWriter(csv_file, fieldnames=columns, extrasaction="ignore")
if not file_exists:
writer.writeheader()
print(f"Writing to {CSV_PATH} (Ctrl-C to stop)\n")
# Write first sample, then loop
row = first
while True:
parts = [f"{k}={v}" for k, v in row.items() if k != "timestamp"]
print(f"[{row['timestamp']}] {' '.join(parts)}")
writer.writerow(row)
csv_file.flush()
time.sleep(POLL_INTERVAL)
try:
row = collect_sample()
except Exception as e:
print(f"[{time.strftime('%H:%M:%S')}] Error: {e}")
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
print("\nStopped.")
```
<!-- github-comment-id:4300684757 -->
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Hello, Here in Oregon, we have 28 repeaters that connect the Southern half of the state. Trying to figure out how to monitor these in the overnight hours when mesh activity is low? Do we run multiple versions of remote term? is there another way to do this or a special update that would allow this?
Hey there! I think we've corresponded via email. Nope, no need to run multiple instances of RemoteTerm. The API, actuated by a script, will let you issue whatever commands you want to as many repeaters as you want, whenever you want. From the interactive/GUI side of things, though, the application is capped at eight in order to limit automated traffic being spewed onto the mesh for stability reasons. The API is open so that people can do whatever they want with the interface, but the super-easily-accessible parts via the GUI is more limited to not make it trivial to issue mesh-destabilizing amounts of traffic.
https://github.com/jkingsman/Remote-Terminal-for-MeshCore/issues/32#issuecomment-3985636666(that was out of date)The below script provides the bones of a basic script for fetching repeater telemetry; with some minor adjustments or LLM assistance that should be trivial to adapt to provide whatever pattern or volume of repeater tracking you need.