Skip to content

Commit

Permalink
Support for 1.3 (2.0)
Browse files Browse the repository at this point in the history
  • Loading branch information
berticus2016 committed Oct 31, 2022
1 parent 8e3cd56 commit 74114f1
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 102 deletions.
25 changes: 17 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ The following plugins can be used in the `pipelines` section of `config.yaml`:
| ----------------- | -------------------------------------------------------------------- |
| `debugger` | Log the packet to the system console |
| `message_filter` | Filters out packets from the bridge that match a specific criteria |
| `distance_filter` | Filters out packets that originate too far from a specified `device` |
| `location_filter` | Filters out packets that originate too far from a specified `device` |
| `webhook` | Send HTTP requests with custom payloads using packet information |
| `mqtt_plugin` | Send packets to a MQTT server |
| `encrypt_filter` | Encrypt a packet for a desired MQTT recipient |
Expand All @@ -131,28 +131,37 @@ Useful for troubleshooting.
- **app** Name of meshtastic application to allow or disallow
- **from** The packet `fromId` values to allow or disallow
- **to** The packet `toId` values to allow or disallow
- **message** The packet `message` values to allow or disallow. Supports Regex.

For example:

```
message_filter:
app:
from:
allow:
- !bd5ba0ec
- !f85bc0bc
disallow:
- !c15ba2ec
message:
disallow:
- Good night
```

### distance_filter - Allow or block packets based on distance from origin to radio
### location_filter - Filter packets by location from current node (default) or specific location

- **log_level** `debug` or `info`. Default `info`
- **max_distance_km** Number of kilometers
- **max_distance_km** Filter packets more than a certain distance
- **comparison** `within` or `outside`. Default `within`
- **compare_latitude** Set the latitude to compare against
- **compare_longitude** Set the longitude to compare against
- **latitude** Set the latitude
- **longitude** Set the longitude

For example:
For example

```
distance_filter:
location_filter:
max_distance_km: 1000
```

Expand Down Expand Up @@ -225,7 +234,7 @@ decrypt_filter:
key: '/home/user/keys/key.pem'
```

### send_plugin - Send a packet to a radio
### radio_message_plugin - Send a packet to a radio

- **log_level** `debug` or `info`. Default `info`
- **active** Plugin is active. Values: `true` or `false`. Default `true`.
Expand All @@ -242,7 +251,7 @@ For example:
Broadcasts all packets to the "remote" radio network that are destined to the node `12354345`.

```
send_plugin:
radio_message_plugin:
device: remote
node_mapping:
12354345: ^all
Expand Down
159 changes: 95 additions & 64 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import logging
from re import I
import meshtastic
import meshtastic.serial_interface
import meshtastic.tcp_interface
Expand All @@ -20,7 +21,15 @@
logger.setLevel(logging.DEBUG)


class CustomTCPInterface(meshtastic.tcp_interface.TCPInterface):
def __init__(self, hostname, device_name):
self.device_name = device_name
self.hostname = hostname
super(CustomTCPInterface, self).__init__(hostname)


def onReceive(packet, interface): # called when a packet arrives
nodeInfo = interface.getMyNodeInfo()

for pipeline, pipeline_plugins in bridge_config["pipelines"].items():
logger.debug(f"Pipeline {pipeline} initiated")
Expand All @@ -29,6 +38,9 @@ def onReceive(packet, interface): # called when a packet arrives
pipeline_packet = p.do_action(packet)

for plugin in pipeline_plugins:
if not pipeline_packet:
continue

for plugin_key, plugin_config in plugin.items():

logger.debug(f"Processing plugin: {pipeline}/{plugin_key}")
Expand Down Expand Up @@ -57,8 +69,17 @@ def onConnection(
)


def onLost(interface):
logger.debug(f"Connecting to {interface.hostname} ...")
devices[interface.device_name] = CustomTCPInterface(
hostname=interface.hostname, device_name=interface.device_name
)
logger.debug(f"Connected to {interface.hostname}")


pub.subscribe(onReceive, "meshtastic.receive")
pub.subscribe(onConnection, "meshtastic.connection.established")
pub.subscribe(onLost, "meshtastic.connection.lost")

with open("config.yaml") as f:
bridge_config = yaml.load(f, Loader=SafeLoader)
Expand All @@ -75,99 +96,109 @@ def onConnection(
devPath=device["serial"]
)
elif "tcp" in device:
devices[device["name"]] = meshtastic.tcp_interface.TCPInterface(
hostname=device["tcp"]
logger.debug(f"Connecting to {device['tcp']} ...")
devices[device["name"]] = CustomTCPInterface(
hostname=device["tcp"], device_name=device["name"]
)
logger.debug(f"Connected to {device['tcp']}")
else:
devices[device["name"]] = meshtastic.serial_interface.SerialInterface()

for config in bridge_config["mqtt_servers"]:
required_options = [
"name",
"server",
"port",
]
if "mqtt_servers" in bridge_config:
for config in bridge_config["mqtt_servers"]:
required_options = [
"name",
"server",
"port",
]

for option in required_options:
if option not in config:
logger.warning("Missing config: {option}")
for option in required_options:
if option not in config:
logger.warning("Missing config: {option}")

client_id = config["client_id"] if "client_id" in config else None
username = config["username"] if "username" in config else None
password = config["password"] if "password" in config else None
client_id = config["client_id"] if "client_id" in config else None
username = config["username"] if "username" in config else None
password = config["password"] if "password" in config else None

if client_id:
mqttc = mqtt.Client(client_id)
else:
mqttc = mqtt.Client()
if client_id:
mqttc = mqtt.Client(client_id)
else:
mqttc = mqtt.Client()

if username and password:
mqttc.username_pw_set(username, password)
if username and password:
mqttc.username_pw_set(username, password)

mqtt_servers[config["name"]] = mqttc
mqtt_servers[config["name"]] = mqttc

def on_connect(mqttc, obj, flags, rc):
logger.debug(f"Connected to MQTT {config['name']}")
def on_connect(mqttc, obj, flags, rc):
logger.debug(f"Connected to MQTT {config['name']}")

def on_message(mqttc, obj, msg):
packet = msg.payload.decode()
def on_message(mqttc, obj, msg):
orig_packet = msg.payload.decode()

logger.debug(f"MQTT {config['name']}: on_message")
logger.debug(f"MQTT {config['name']}: on_message")

if "pipelines" not in config:
logger.warning(f"MQTT {config['name']}: no pipeline")
return
if "pipelines" not in config:
logger.warning(f"MQTT {config['name']}: no pipeline")
return

for pipeline, pipeline_plugins in config["pipelines"].items():
for pipeline, pipeline_plugins in config["pipelines"].items():

logger.debug(f"MQTT {config['name']} pipeline {pipeline} started")
if not packet:
continue
packet = orig_packet

for plugin in pipeline_plugins:
for plugin_key, plugin_config in plugin.items():
if plugin_key not in plugins:
logger.error(f"No such plugin: {plugin_key}. Skipping")
logger.debug(f"MQTT {config['name']} pipeline {pipeline} started")
if not packet:
continue

for plugin in pipeline_plugins:
if not packet:
continue

p = plugins[plugin_key]
p.configure(devices, mqtt_servers, plugin_config)
for plugin_key, plugin_config in plugin.items():
if plugin_key not in plugins:
logger.error(f"No such plugin: {plugin_key}. Skipping")
continue

p = plugins[plugin_key]
p.configure(devices, mqtt_servers, plugin_config)

try:
packet = p.do_action(packet)
except Exception as e:
logger.error(f"Hit an error: {e}", exc_info=True)
logger.debug(f"MQTT {config['name']} pipeline {pipeline} finished")
try:
packet = p.do_action(packet)
except Exception as e:
logger.error(f"Hit an error: {e}", exc_info=True)
logger.debug(f"MQTT {config['name']} pipeline {pipeline} finished")

def on_publish(mqttc, obj, mid):
logger.debug(f"MQTT {config['name']}: on_publish: {mid}")
def on_publish(mqttc, obj, mid):
logger.debug(f"MQTT {config['name']}: on_publish: {mid}")

def on_subscribe(mqttc, obj, mid, granted_qos):
logger.debug(f"MQTT {config['name']}: on_subscribe: {mid}")
def on_subscribe(mqttc, obj, mid, granted_qos):
logger.debug(f"MQTT {config['name']}: on_subscribe: {mid}")

mqttc.on_message = on_message
mqttc.on_connect = on_connect
mqttc.on_publish = on_publish
mqttc.on_subscribe = on_subscribe
mqttc.on_message = on_message
mqttc.on_connect = on_connect
mqttc.on_publish = on_publish
mqttc.on_subscribe = on_subscribe

import ssl
import ssl

if "insecure" in config and config["insecure"]:
mqttc.tls_set(cert_reqs=ssl.CERT_NONE)
mqttc.tls_insecure_set(True)
if "insecure" in config and config["insecure"]:
mqttc.tls_set(cert_reqs=ssl.CERT_NONE)
mqttc.tls_insecure_set(True)

mqttc.connect(config["server"], config["port"], 60)
mqttc.connect(config["server"], config["port"], 60)

if "topic" in config:
mqttc.subscribe(config["topic"], 0)
if "topic" in config:
mqttc.subscribe(config["topic"], 0)

mqttc.loop_start()
mqttc.loop_start()

while True:
time.sleep(1000)

for device, instance in devices.items():
instance.close()
if devices:
for device, instance in devices.items():
instance.close()

for server, instance in mqtt_servers.items():
instance.disconnect()
if mqtt_servers:
for server, instance in mqtt_servers.items():
instance.disconnect()
Loading

0 comments on commit 74114f1

Please sign in to comment.