Skip to content

Commit 74114f1

Browse files
committed
Support for 1.3 (2.0)
1 parent 8e3cd56 commit 74114f1

File tree

4 files changed

+188
-102
lines changed

4 files changed

+188
-102
lines changed

README.md

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ The following plugins can be used in the `pipelines` section of `config.yaml`:
105105
| ----------------- | -------------------------------------------------------------------- |
106106
| `debugger` | Log the packet to the system console |
107107
| `message_filter` | Filters out packets from the bridge that match a specific criteria |
108-
| `distance_filter` | Filters out packets that originate too far from a specified `device` |
108+
| `location_filter` | Filters out packets that originate too far from a specified `device` |
109109
| `webhook` | Send HTTP requests with custom payloads using packet information |
110110
| `mqtt_plugin` | Send packets to a MQTT server |
111111
| `encrypt_filter` | Encrypt a packet for a desired MQTT recipient |
@@ -131,28 +131,37 @@ Useful for troubleshooting.
131131
- **app** Name of meshtastic application to allow or disallow
132132
- **from** The packet `fromId` values to allow or disallow
133133
- **to** The packet `toId` values to allow or disallow
134+
- **message** The packet `message` values to allow or disallow. Supports Regex.
134135

135136
For example:
136137

137138
```
138139
message_filter:
139-
app:
140+
from:
140141
allow:
141142
- !bd5ba0ec
142143
- !f85bc0bc
143144
disallow:
144145
- !c15ba2ec
146+
message:
147+
disallow:
148+
- Good night
145149
```
146150

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

149153
- **log_level** `debug` or `info`. Default `info`
150-
- **max_distance_km** Number of kilometers
154+
- **max_distance_km** Filter packets more than a certain distance
155+
- **comparison** `within` or `outside`. Default `within`
156+
- **compare_latitude** Set the latitude to compare against
157+
- **compare_longitude** Set the longitude to compare against
158+
- **latitude** Set the latitude
159+
- **longitude** Set the longitude
151160

152-
For example:
161+
For example
153162

154163
```
155-
distance_filter:
164+
location_filter:
156165
max_distance_km: 1000
157166
```
158167

@@ -225,7 +234,7 @@ decrypt_filter:
225234
key: '/home/user/keys/key.pem'
226235
```
227236

228-
### send_plugin - Send a packet to a radio
237+
### radio_message_plugin - Send a packet to a radio
229238

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

244253
```
245-
send_plugin:
254+
radio_message_plugin:
246255
device: remote
247256
node_mapping:
248257
12354345: ^all

main.py

Lines changed: 95 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import json
22
import logging
3+
from re import I
34
import meshtastic
45
import meshtastic.serial_interface
56
import meshtastic.tcp_interface
@@ -20,7 +21,15 @@
2021
logger.setLevel(logging.DEBUG)
2122

2223

24+
class CustomTCPInterface(meshtastic.tcp_interface.TCPInterface):
25+
def __init__(self, hostname, device_name):
26+
self.device_name = device_name
27+
self.hostname = hostname
28+
super(CustomTCPInterface, self).__init__(hostname)
29+
30+
2331
def onReceive(packet, interface): # called when a packet arrives
32+
nodeInfo = interface.getMyNodeInfo()
2433

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

3140
for plugin in pipeline_plugins:
41+
if not pipeline_packet:
42+
continue
43+
3244
for plugin_key, plugin_config in plugin.items():
3345

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

5971

72+
def onLost(interface):
73+
logger.debug(f"Connecting to {interface.hostname} ...")
74+
devices[interface.device_name] = CustomTCPInterface(
75+
hostname=interface.hostname, device_name=interface.device_name
76+
)
77+
logger.debug(f"Connected to {interface.hostname}")
78+
79+
6080
pub.subscribe(onReceive, "meshtastic.receive")
6181
pub.subscribe(onConnection, "meshtastic.connection.established")
82+
pub.subscribe(onLost, "meshtastic.connection.lost")
6283

6384
with open("config.yaml") as f:
6485
bridge_config = yaml.load(f, Loader=SafeLoader)
@@ -75,99 +96,109 @@ def onConnection(
7596
devPath=device["serial"]
7697
)
7798
elif "tcp" in device:
78-
devices[device["name"]] = meshtastic.tcp_interface.TCPInterface(
79-
hostname=device["tcp"]
99+
logger.debug(f"Connecting to {device['tcp']} ...")
100+
devices[device["name"]] = CustomTCPInterface(
101+
hostname=device["tcp"], device_name=device["name"]
80102
)
103+
logger.debug(f"Connected to {device['tcp']}")
81104
else:
82105
devices[device["name"]] = meshtastic.serial_interface.SerialInterface()
83106

84-
for config in bridge_config["mqtt_servers"]:
85-
required_options = [
86-
"name",
87-
"server",
88-
"port",
89-
]
107+
if "mqtt_servers" in bridge_config:
108+
for config in bridge_config["mqtt_servers"]:
109+
required_options = [
110+
"name",
111+
"server",
112+
"port",
113+
]
90114

91-
for option in required_options:
92-
if option not in config:
93-
logger.warning("Missing config: {option}")
115+
for option in required_options:
116+
if option not in config:
117+
logger.warning("Missing config: {option}")
94118

95-
client_id = config["client_id"] if "client_id" in config else None
96-
username = config["username"] if "username" in config else None
97-
password = config["password"] if "password" in config else None
119+
client_id = config["client_id"] if "client_id" in config else None
120+
username = config["username"] if "username" in config else None
121+
password = config["password"] if "password" in config else None
98122

99-
if client_id:
100-
mqttc = mqtt.Client(client_id)
101-
else:
102-
mqttc = mqtt.Client()
123+
if client_id:
124+
mqttc = mqtt.Client(client_id)
125+
else:
126+
mqttc = mqtt.Client()
103127

104-
if username and password:
105-
mqttc.username_pw_set(username, password)
128+
if username and password:
129+
mqttc.username_pw_set(username, password)
106130

107-
mqtt_servers[config["name"]] = mqttc
131+
mqtt_servers[config["name"]] = mqttc
108132

109-
def on_connect(mqttc, obj, flags, rc):
110-
logger.debug(f"Connected to MQTT {config['name']}")
133+
def on_connect(mqttc, obj, flags, rc):
134+
logger.debug(f"Connected to MQTT {config['name']}")
111135

112-
def on_message(mqttc, obj, msg):
113-
packet = msg.payload.decode()
136+
def on_message(mqttc, obj, msg):
137+
orig_packet = msg.payload.decode()
114138

115-
logger.debug(f"MQTT {config['name']}: on_message")
139+
logger.debug(f"MQTT {config['name']}: on_message")
116140

117-
if "pipelines" not in config:
118-
logger.warning(f"MQTT {config['name']}: no pipeline")
119-
return
141+
if "pipelines" not in config:
142+
logger.warning(f"MQTT {config['name']}: no pipeline")
143+
return
120144

121-
for pipeline, pipeline_plugins in config["pipelines"].items():
145+
for pipeline, pipeline_plugins in config["pipelines"].items():
122146

123-
logger.debug(f"MQTT {config['name']} pipeline {pipeline} started")
124-
if not packet:
125-
continue
147+
packet = orig_packet
126148

127-
for plugin in pipeline_plugins:
128-
for plugin_key, plugin_config in plugin.items():
129-
if plugin_key not in plugins:
130-
logger.error(f"No such plugin: {plugin_key}. Skipping")
149+
logger.debug(f"MQTT {config['name']} pipeline {pipeline} started")
150+
if not packet:
151+
continue
152+
153+
for plugin in pipeline_plugins:
154+
if not packet:
131155
continue
132156

133-
p = plugins[plugin_key]
134-
p.configure(devices, mqtt_servers, plugin_config)
157+
for plugin_key, plugin_config in plugin.items():
158+
if plugin_key not in plugins:
159+
logger.error(f"No such plugin: {plugin_key}. Skipping")
160+
continue
161+
162+
p = plugins[plugin_key]
163+
p.configure(devices, mqtt_servers, plugin_config)
135164

136-
try:
137-
packet = p.do_action(packet)
138-
except Exception as e:
139-
logger.error(f"Hit an error: {e}", exc_info=True)
140-
logger.debug(f"MQTT {config['name']} pipeline {pipeline} finished")
165+
try:
166+
packet = p.do_action(packet)
167+
except Exception as e:
168+
logger.error(f"Hit an error: {e}", exc_info=True)
169+
logger.debug(f"MQTT {config['name']} pipeline {pipeline} finished")
141170

142-
def on_publish(mqttc, obj, mid):
143-
logger.debug(f"MQTT {config['name']}: on_publish: {mid}")
171+
def on_publish(mqttc, obj, mid):
172+
logger.debug(f"MQTT {config['name']}: on_publish: {mid}")
144173

145-
def on_subscribe(mqttc, obj, mid, granted_qos):
146-
logger.debug(f"MQTT {config['name']}: on_subscribe: {mid}")
174+
def on_subscribe(mqttc, obj, mid, granted_qos):
175+
logger.debug(f"MQTT {config['name']}: on_subscribe: {mid}")
147176

148-
mqttc.on_message = on_message
149-
mqttc.on_connect = on_connect
150-
mqttc.on_publish = on_publish
151-
mqttc.on_subscribe = on_subscribe
177+
mqttc.on_message = on_message
178+
mqttc.on_connect = on_connect
179+
mqttc.on_publish = on_publish
180+
mqttc.on_subscribe = on_subscribe
152181

153-
import ssl
182+
import ssl
154183

155-
if "insecure" in config and config["insecure"]:
156-
mqttc.tls_set(cert_reqs=ssl.CERT_NONE)
157-
mqttc.tls_insecure_set(True)
184+
if "insecure" in config and config["insecure"]:
185+
mqttc.tls_set(cert_reqs=ssl.CERT_NONE)
186+
mqttc.tls_insecure_set(True)
158187

159-
mqttc.connect(config["server"], config["port"], 60)
188+
mqttc.connect(config["server"], config["port"], 60)
160189

161-
if "topic" in config:
162-
mqttc.subscribe(config["topic"], 0)
190+
if "topic" in config:
191+
mqttc.subscribe(config["topic"], 0)
163192

164-
mqttc.loop_start()
193+
mqttc.loop_start()
165194

166195
while True:
167196
time.sleep(1000)
168197

169-
for device, instance in devices.items():
170-
instance.close()
198+
if devices:
199+
for device, instance in devices.items():
200+
instance.close()
171201

172-
for server, instance in mqtt_servers.items():
173-
instance.disconnect()
202+
if mqtt_servers:
203+
for server, instance in mqtt_servers.items():
204+
instance.disconnect()

0 commit comments

Comments
 (0)