WIP
This commit is contained in:
commit
18c00de38a
4 changed files with 134 additions and 0 deletions
1
.gitingnore
Normal file
1
.gitingnore
Normal file
|
|
@ -0,0 +1 @@
|
|||
venv/
|
||||
27
config.yaml
Normal file
27
config.yaml
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
prometheus:
|
||||
pushgateway_address: "localhost:9091"
|
||||
job: "meshcore_repeater_telemetry"
|
||||
serial_device_path: "/dev/ttyACM0"
|
||||
radio_settings:
|
||||
freq: 869.618
|
||||
bw: 62.5
|
||||
sf: 8
|
||||
cr: 8
|
||||
retries: 2
|
||||
timeout: 20
|
||||
repeaters:
|
||||
# stay_hydrated_01
|
||||
- contact_data: "11004a629a62e51f0ec770afc47bb22010df0ac1c47475499b6b5e47b3487a4f71e680440669d4d9bdfacc88e82e441a86026082f74a53e962c7cf3981cdc2bcaa4a820ce77bf71ad2eddf196524e1b5397e9d105eacbfd866e211957a80c5eda788eb84fb01925916320377689600737461795f68796472617465645f3031"
|
||||
password: ""
|
||||
path: []
|
||||
# 25469 - hansemesh.de
|
||||
- contact_data: "11014aa73518d39789c74af4ad460e31833cd824a5bc0f3df5482ecdf96eec2e30989cb53f0669defe3a07e35089ba86a739544dee340fc489d18379d2b6682eacf4b75b3e9a77f3fcae93bc7e26377977e0a74f0a84deb0cead20e98f62533e78f98a68de600b92484532035d0896003235343639202d2068616e73656d6573682e6465"
|
||||
password: ""
|
||||
path:
|
||||
- "4a"
|
||||
# CCCHH
|
||||
- contact_data: "1102a74accc426cdf274e5b90dff50cc1081ab7195fb8166285a29b39b106fe31e80be6b19a0f768651168d5be7bce6ba4145a473045564e5ac83c014aa764dc94e31e22aee35460c86c39d8c4acd27647340264b0e7c5d82919e4eacc7ae796f92b071a6d09130592f43b310320bb97004343434848"
|
||||
password: ""
|
||||
path:
|
||||
- "4a"
|
||||
- "f4"
|
||||
99
main.py
Executable file
99
main.py
Executable file
|
|
@ -0,0 +1,99 @@
|
|||
#!/usr/bin/env python3
|
||||
import asyncio
|
||||
import json
|
||||
import yaml
|
||||
import time
|
||||
from meshcore import MeshCore, EventType, packets
|
||||
from prometheus_client import CollectorRegistry, Gauge, push_to_gateway
|
||||
|
||||
def parse_public_key_from_contact_data(contact_data):
|
||||
public_key_length = 64
|
||||
packet_type_length = len(str(packets.PacketType.CONTACT_URI.value))
|
||||
packet_path_specifier_length = 2
|
||||
if contact_data and contact_data.startswith(str(packets.PacketType.CONTACT_URI.value)):
|
||||
path_length = int(contact_data[packet_type_length:packet_type_length+packet_path_specifier_length])
|
||||
offset = packet_type_length + packet_path_specifier_length + path_length * 2
|
||||
return contact_data[offset:offset+public_key_length]
|
||||
return False
|
||||
|
||||
async def setup(meshcore, config):
|
||||
await meshcore.commands.set_time(int(time.time()))
|
||||
result = await meshcore.commands.set_radio(config["radio_settings"]["freq"], config["radio_settings"]["bw"], config["radio_settings"]["sf"], config["radio_settings"]["cr"])
|
||||
if result.type is EventType.ERROR:
|
||||
print("Failed to setup radio")
|
||||
exit(1)
|
||||
await meshcore.commands.set_manual_add_contacts(False)
|
||||
for repeater in config["repeaters"]:
|
||||
public_key = parse_public_key_from_contact_data(repeater["contact_data"])
|
||||
if not public_key:
|
||||
print("Failed to parse public key from contact data: %s" % repeater["contact_data"])
|
||||
continue
|
||||
repeater["public_key"] = public_key
|
||||
try:
|
||||
result = await meshcore.commands.import_contact(bytes.fromhex(repeater["contact_data"]))
|
||||
if result.type is EventType.ERROR:
|
||||
raise Exception("Failed to import contact")
|
||||
except:
|
||||
print("Failed add contact from contact data: %s\nAborting." % repeater["contact_data"])
|
||||
exit(1)
|
||||
await meshcore.commands.set_manual_add_contacts(True)
|
||||
await meshcore.ensure_contacts()
|
||||
|
||||
async def main():
|
||||
with open("config.yaml", "r") as file:
|
||||
config = yaml.safe_load(file)
|
||||
|
||||
meshcore = await MeshCore.create_serial(config["serial_device_path"])
|
||||
await setup(meshcore, config)
|
||||
|
||||
for repeater in config["repeaters"]:
|
||||
contact = meshcore.get_contact_by_key_prefix(repeater["public_key"])
|
||||
await meshcore.commands.change_contact_path(contact, "".join(repeater["path"]))
|
||||
print(contact)
|
||||
|
||||
tries = 0
|
||||
while(tries <= config["retries"]):
|
||||
tries += 1
|
||||
|
||||
await meshcore.commands.send_login(contact, repeater["password"])
|
||||
result = await meshcore.wait_for_event(EventType.LOGIN_SUCCESS, timeout=config["timeout"])
|
||||
if result is None:
|
||||
print("Timeout waiting on login for %s" % repeater["public_key"])
|
||||
else:
|
||||
break
|
||||
|
||||
if tries == config["retries"] + 1:
|
||||
print("Maximum login retries exceeded for %s" % repeater["public_key"])
|
||||
break
|
||||
|
||||
result = None
|
||||
tries = 0
|
||||
while(tries <= config["retries"]):
|
||||
tries += 1
|
||||
|
||||
result = await meshcore.commands.send_telemetry_req(repeater["public_key"])
|
||||
if result.type == EventType.ERROR:
|
||||
print("Error sending telemetry request for %s" % repeater["public_key"])
|
||||
continue
|
||||
|
||||
result = await meshcore.wait_for_event(EventType.TELEMETRY_RESPONSE, timeout=config["timeout"])
|
||||
if result is None:
|
||||
print("Timeout waiting on telemetry for %s" % repeater["public_key"])
|
||||
continue
|
||||
else:
|
||||
break
|
||||
|
||||
if tries == config["retries"] + 1:
|
||||
print("Maximum telemetry request retries exceeded for %s" % repeater["public_key"])
|
||||
else:
|
||||
telemetry_data_list = result.payload["lpp"]
|
||||
|
||||
registry = CollectorRegistry()
|
||||
for telemetry_data in telemetry_data_list:
|
||||
if telemetry_data["type"] == "voltage":
|
||||
gauge = Gauge("voltage", "Battery Voltage", registry=registry)
|
||||
gauge.set(telemetry_data["value"])
|
||||
push_to_gateway(config["prometheus"]["pushgateway_address"], job=config["prometheus"]["job"], grouping_key={"instance": contact["adv_name"]}, registry=registry)
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
7
requirements.txt
Normal file
7
requirements.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
bleak==1.1.1
|
||||
dbus-fast==2.44.5
|
||||
meshcore==2.1.12
|
||||
prometheus_client==0.23.1
|
||||
pycayennelpp==2.4.0
|
||||
pyserial==3.5
|
||||
pyserial-asyncio==0.6
|
||||
Loading…
Add table
Add a link
Reference in a new issue