mmrelay 1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mmrelay might be problematic. Click here for more details.

mmrelay/setup_utils.py ADDED
@@ -0,0 +1,263 @@
1
+ """
2
+ Setup utilities for MMRelay.
3
+
4
+ This module provides simple functions for managing the systemd user service
5
+ and generating configuration files.
6
+ """
7
+
8
+ # Import version from package
9
+ import os
10
+ import shutil
11
+ import subprocess
12
+ import sys
13
+ from pathlib import Path
14
+
15
+
16
+ def get_executable_path():
17
+ """Get the full path to the mmrelay executable."""
18
+ return shutil.which("mmrelay") or sys.executable
19
+
20
+
21
+ def get_user_service_path():
22
+ """Get the path to the user service file."""
23
+ service_dir = Path.home() / ".config" / "systemd" / "user"
24
+ return service_dir / "mmrelay.service"
25
+
26
+
27
+ def service_exists():
28
+ """Check if the service file exists."""
29
+ return get_user_service_path().exists()
30
+
31
+
32
+ def print_service_commands():
33
+ """Print the commands for controlling the systemd user service."""
34
+ print("\nUse these commands to control the mmrelay service:")
35
+ print(" systemctl --user start mmrelay.service # Start the service")
36
+ print(" systemctl --user stop mmrelay.service # Stop the service")
37
+ print(" systemctl --user restart mmrelay.service # Restart the service")
38
+ print(" systemctl --user status mmrelay.service # Check service status")
39
+
40
+
41
+ def wait_for_service_start():
42
+ """Wait for the service to start with a loading animation."""
43
+ import sys
44
+ import time
45
+
46
+ print("\nStarting mmrelay service", end="")
47
+ sys.stdout.flush()
48
+
49
+ # Animation characters
50
+ chars = ["-", "\\", "|", "/"]
51
+
52
+ # Wait for 10 seconds with animation
53
+ for i in range(40): # 40 * 0.25s = 10s
54
+ time.sleep(0.25)
55
+ print(f"\rStarting mmrelay service {chars[i % len(chars)]}", end="")
56
+ sys.stdout.flush()
57
+
58
+ print("\rStarting mmrelay service... done!")
59
+ sys.stdout.flush()
60
+
61
+
62
+ def read_service_file():
63
+ """Read the content of the service file if it exists."""
64
+ service_path = get_user_service_path()
65
+ if service_path.exists():
66
+ return service_path.read_text()
67
+ return None
68
+
69
+
70
+ def create_service_file():
71
+ """Create the systemd user service file."""
72
+ executable_path = get_executable_path()
73
+ if not executable_path:
74
+ print("Error: Could not find mmrelay executable in PATH")
75
+ return False
76
+
77
+ # Create service directory if it doesn't exist
78
+ service_dir = get_user_service_path().parent
79
+ service_dir.mkdir(parents=True, exist_ok=True)
80
+
81
+ # Create logs directory if it doesn't exist
82
+ logs_dir = Path.home() / ".mmrelay" / "logs"
83
+ logs_dir.mkdir(parents=True, exist_ok=True)
84
+
85
+ # Try to find the service template file
86
+ # First, check in the package directory
87
+ package_dir = os.path.dirname(__file__)
88
+ template_path = os.path.join(
89
+ os.path.dirname(os.path.dirname(package_dir)), "tools", "mmrelay.service"
90
+ )
91
+
92
+ # If not found, try the repository root
93
+ if not os.path.exists(template_path):
94
+ repo_root = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
95
+ template_path = os.path.join(repo_root, "tools", "mmrelay.service")
96
+
97
+ # If still not found, try the current directory
98
+ if not os.path.exists(template_path):
99
+ template_path = os.path.join(os.getcwd(), "tools", "mmrelay.service")
100
+
101
+ if not os.path.exists(template_path):
102
+ print(f"Error: Could not find service template at {template_path}")
103
+ return False
104
+
105
+ # Read the template
106
+ with open(template_path, "r") as f:
107
+ service_template = f.read()
108
+
109
+ # Replace placeholders with actual values
110
+ service_content = (
111
+ service_template.replace(
112
+ "WorkingDirectory=%h/meshtastic-matrix-relay",
113
+ "# WorkingDirectory is not needed for installed package",
114
+ )
115
+ .replace(
116
+ "%h/meshtastic-matrix-relay/.pyenv/bin/python %h/meshtastic-matrix-relay/main.py",
117
+ executable_path,
118
+ )
119
+ .replace(
120
+ "--config %h/.mmrelay/config/config.yaml",
121
+ "--config %h/.mmrelay/config.yaml",
122
+ )
123
+ )
124
+
125
+ # Write service file
126
+ try:
127
+ get_user_service_path().write_text(service_content)
128
+ print(f"Service file created at {get_user_service_path()}")
129
+ return True
130
+ except (IOError, OSError) as e:
131
+ print(f"Error creating service file: {e}")
132
+ return False
133
+
134
+
135
+ def reload_daemon():
136
+ """Reload the systemd user daemon."""
137
+ try:
138
+ # Using absolute path for security
139
+ subprocess.run(["/usr/bin/systemctl", "--user", "daemon-reload"], check=True)
140
+ print("Systemd user daemon reloaded")
141
+ return True
142
+ except subprocess.CalledProcessError as e:
143
+ print(f"Error reloading systemd daemon: {e}")
144
+ return False
145
+ except OSError as e:
146
+ print(f"Error: {e}")
147
+ return False
148
+
149
+
150
+ def install_service():
151
+ """Install or update the MMRelay user service."""
152
+ # Check if service already exists
153
+ existing_service = read_service_file()
154
+
155
+ if existing_service:
156
+ print(f"A service file already exists at {get_user_service_path()}")
157
+ if (
158
+ not input("Do you want to reinstall/update the service? (y/n): ")
159
+ .lower()
160
+ .startswith("y")
161
+ ):
162
+ print("Service installation cancelled.")
163
+ print_service_commands()
164
+ return True
165
+
166
+ # Create or update service file
167
+ if not create_service_file():
168
+ return False
169
+
170
+ # Reload daemon
171
+ if not reload_daemon():
172
+ return False
173
+
174
+ if existing_service:
175
+ print("Service updated successfully")
176
+ else:
177
+ print("Service installed successfully")
178
+
179
+ # Check if config is valid before starting the service
180
+ from mmrelay.cli import check_config
181
+
182
+ if not check_config():
183
+ print(
184
+ "\nWarning: Configuration is not valid. Service is installed but not started."
185
+ )
186
+ print("Please fix your configuration and then start the service manually.")
187
+ print_service_commands()
188
+ return True
189
+
190
+ # Ask if user wants to enable and start the service
191
+ if (
192
+ input("Do you want to enable the service to start at boot? (y/n): ")
193
+ .lower()
194
+ .startswith("y")
195
+ ):
196
+ try:
197
+ subprocess.run(
198
+ ["/usr/bin/systemctl", "--user", "enable", "mmrelay.service"],
199
+ check=True,
200
+ )
201
+ print("Service enabled successfully")
202
+ except subprocess.CalledProcessError as e:
203
+ print(f"Error enabling service: {e}")
204
+ except OSError as e:
205
+ print(f"Error: {e}")
206
+
207
+ if input("Do you want to start the service now? (y/n): ").lower().startswith("y"):
208
+ if start_service():
209
+ # Wait for the service to start
210
+ wait_for_service_start()
211
+
212
+ # Show service status
213
+ show_service_status()
214
+ print("Service started successfully")
215
+ else:
216
+ print("\nWarning: Failed to start the service. Please check the logs.")
217
+
218
+ print_service_commands()
219
+
220
+ return True
221
+
222
+
223
+ def start_service():
224
+ """Start the systemd user service.
225
+
226
+ Returns:
227
+ bool: True if successful, False otherwise.
228
+ """
229
+ try:
230
+ subprocess.run(
231
+ ["/usr/bin/systemctl", "--user", "start", "mmrelay.service"], check=True
232
+ )
233
+ return True
234
+ except subprocess.CalledProcessError as e:
235
+ print(f"Error starting service: {e}")
236
+ return False
237
+ except OSError as e:
238
+ print(f"Error: {e}")
239
+ return False
240
+
241
+
242
+ def show_service_status():
243
+ """Show the status of the systemd user service.
244
+
245
+ Returns:
246
+ bool: True if successful, False otherwise.
247
+ """
248
+ try:
249
+ result = subprocess.run(
250
+ ["/usr/bin/systemctl", "--user", "status", "mmrelay.service"],
251
+ check=True,
252
+ capture_output=True,
253
+ text=True,
254
+ )
255
+ print("\nService Status:")
256
+ print(result.stdout)
257
+ return True
258
+ except subprocess.CalledProcessError as e:
259
+ print(f"Could not get service status: {e}")
260
+ return False
261
+ except OSError as e:
262
+ print(f"Error: {e}")
263
+ return False
@@ -0,0 +1,160 @@
1
+ Metadata-Version: 2.4
2
+ Name: mmrelay
3
+ Version: 1.0
4
+ Summary: Bridge between Meshtastic mesh networks and Matrix chat rooms
5
+ Home-page: https://github.com/geoffwhittington/meshtastic-matrix-relay
6
+ Author: Geoff Whittington, Jeremiah K., and contributors
7
+ Author-email: jeremiahk@gmx.com
8
+ Project-URL: Bug Tracker, https://github.com/geoffwhittington/meshtastic-matrix-relay/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Topic :: Communications
14
+ Requires-Python: >=3.8
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: meshtastic
18
+ Requires-Dist: Pillow==11.1.0
19
+ Requires-Dist: matrix-nio==0.25.2
20
+ Requires-Dist: matplotlib==3.10.1
21
+ Requires-Dist: requests==2.32.3
22
+ Requires-Dist: markdown==3.7
23
+ Requires-Dist: haversine==2.9.0
24
+ Requires-Dist: schedule==1.2.2
25
+ Requires-Dist: platformdirs==4.2.0
26
+ Requires-Dist: py-staticmaps>=0.4.0
27
+ Dynamic: license-file
28
+
29
+ # M<>M Relay
30
+
31
+ ## (Meshtastic <=> Matrix Relay)
32
+
33
+ A powerful and easy-to-use relay between Meshtastic devices and Matrix chat rooms, allowing seamless communication across platforms. This opens the door for bridging Meshtastic devices to [many other platforms](https://matrix.org/bridges/).
34
+
35
+ ---
36
+
37
+ ## Getting Started
38
+
39
+ MMRelay runs on Linux, macOS, and Windows.
40
+
41
+ ### Quick Installation
42
+
43
+ ```bash
44
+ # Install using pip
45
+ pip install mmrelay
46
+
47
+ # Or use pipx for isolated installation (recommended)
48
+ pipx install mmrelay
49
+ ```
50
+
51
+ ### Resources
52
+
53
+ - **New Users**: See [INSTRUCTIONS.md](INSTRUCTIONS.md) for setup and configuration
54
+ - **Existing Users**: Check [UPGRADE_TO_V1.md](UPGRADE_TO_V1.md) for migration guidance
55
+ - **Configuration**: Review [sample_config.yaml](sample_config.yaml) for examples
56
+
57
+ ### Command-Line Options
58
+
59
+ ```bash
60
+ usage: mmrelay [-h] [--config CONFIG] [--data-dir DATA_DIR] [--log-level {error,warning,info,debug}] [--logfile LOGFILE] [--version] [--generate-config] [--install-service] [--check-config]
61
+
62
+ Options:
63
+ -h, --help Show this help message and exit
64
+ --config CONFIG Path to config file
65
+ --data-dir DATA_DIR Base directory for all data (logs, database, plugins)
66
+ --log-level {error,warning,info,debug}
67
+ Set logging level
68
+ --logfile LOGFILE Path to log file (can be overridden by --data-dir)
69
+ --version Show version and exit
70
+ --generate-config Generate a sample config.yaml file
71
+ --install-service Install or update the systemd user service
72
+ --check-config Check if the configuration file is valid
73
+ ```
74
+
75
+ ---
76
+
77
+ ## Features
78
+
79
+ - Bidirectional message relay between Meshtastic devices and Matrix chat rooms, capable of supporting multiple meshnets
80
+ - Supports serial, network, and **_BLE (now too!)_** connections for Meshtastic devices
81
+ - Custom fields are embedded in Matrix messages for relaying messages between multiple meshnets
82
+ - Truncates long messages to fit within Meshtastic's payload size
83
+ - SQLite database to store node information for improved functionality
84
+ - Customizable logging level for easy debugging
85
+ - Configurable through a simple YAML file
86
+ - Supports mapping multiple rooms and channels 1:1
87
+ - Relays messages to/from an MQTT broker, if configured in the Meshtastic firmware
88
+ - ✨️ _Cross-platform reactions support_ ✨️ **NEW!!**
89
+
90
+ _We would love to support [Matrix E2EE rooms](https://github.com/geoffwhittington/meshtastic-matrix-relay/issues/33), but this is currently not implemented._
91
+
92
+ ---
93
+
94
+ ## Windows Installer
95
+
96
+ ![Windows Installer Screenshot](https://user-images.githubusercontent.com/1770544/235249050-8c79107a-50cc-4803-b989-39e58100342d.png)
97
+
98
+ The latest installer is available [here](https://github.com/geoffwhittington/meshtastic-matrix-relay/releases).
99
+
100
+ ---
101
+
102
+ ## Plugins
103
+
104
+ M<>M Relay supports plugins for extending its functionality, enabling customization and enhancement of the relay to suit specific needs.
105
+
106
+ ### Core Plugins
107
+
108
+ Generate a map of your nodes:
109
+
110
+ ![Map Plugin Screenshot](https://user-images.githubusercontent.com/1770544/235247915-47750b4f-d505-4792-a458-54a5f24c1523.png)
111
+
112
+ Produce high-level details about your mesh:
113
+
114
+ ![Mesh Details Screenshot](https://user-images.githubusercontent.com/1770544/235245873-1ddc773b-a4cd-4c67-b0a5-b55a29504b73.png)
115
+
116
+ See the full list of core plugins [here](https://github.com/geoffwhittington/meshtastic-matrix-relay/wiki/Core-Plugins).
117
+
118
+ ### Community & Custom Plugins
119
+
120
+ It is possible to create custom plugins and share them with the community. Check [example_plugins/README.md](https://github.com/geoffwhittington/meshtastic-matrix-relay/tree/main/example_plugins) and the [Community Plugins Development Guide](https://github.com/geoffwhittington/meshtastic-matrix-relay/wiki/Community-Plugin-Development-Guide).
121
+
122
+ ✨️ Visit the [Community Plugins List](https://github.com/geoffwhittington/meshtastic-matrix-relay/wiki/Community-Plugin-List)!
123
+
124
+ #### Install a Community Plugin
125
+
126
+ Add the repository under the `community-plugins` section in `config.yaml`:
127
+
128
+ ```yaml
129
+ community-plugins:
130
+ example-plugin:
131
+ active: true
132
+ repository: https://github.com/jeremiah-k/mmr-plugin-template.git
133
+ tag: main
134
+ ```
135
+
136
+ ### Plugin System
137
+
138
+ MMRelay features a powerful plugin system with standardized locations:
139
+
140
+ - **Core Plugins**: Pre-installed with the package
141
+ - **Custom Plugins**: Your own plugins in `~/.mmrelay/plugins/custom/`
142
+ - **Community Plugins**: Third-party plugins in `~/.mmrelay/plugins/community/`
143
+
144
+ Plugins make it easy to extend functionality without modifying the core code.
145
+
146
+ ---
147
+
148
+ ## Getting Started with Matrix
149
+
150
+ See our Wiki page [Getting Started With Matrix & MM Relay](https://github.com/geoffwhittington/meshtastic-matrix-relay/wiki/Getting-Started-With-Matrix-&-MM-Relay).
151
+
152
+ ---
153
+
154
+ ## Already on Matrix?
155
+
156
+ Join us!
157
+
158
+ - Our project's room: [#mmrelay:meshnet.club](https://matrix.to/#/#mmrelay:meshnet.club)
159
+ - Part of the Meshtastic Community Matrix space: [#meshtastic-community:meshnet.club](https://matrix.to/#/#meshtastic-community:meshnet.club)
160
+ - Public Relay Room: [#relay-room:meshnet.club](https://matrix.to/#/#relay-room:meshnet.club) - Where we bridge multiple meshnets. Feel free to join us, with or without a relay!
@@ -0,0 +1,29 @@
1
+ mmrelay/__init__.py,sha256=tY9iMcQ9e8IhGjiSjukqcNujnqqf7_OTORo7JvRDWvU,278
2
+ mmrelay/cli.py,sha256=H-h-hvrFiOr9gTY5o21snBNiHJCDJx_HLR8JxTs1M-o,12273
3
+ mmrelay/config.py,sha256=epH-xOOIMblG5w_fk86r8JgJK-70bLbX5CfMTWOfPmo,7064
4
+ mmrelay/config_checker.py,sha256=UnoHVTXzfdTfFkbmXv9r_Si76v-sxXLb5FOaQSOM45E,4909
5
+ mmrelay/db_utils.py,sha256=DP2YuKBZtV771wo9X-Z7Ww5txfaIR0inWh1K_oVZ7cA,11430
6
+ mmrelay/log_utils.py,sha256=-ItwMnxa-t2ZKBIp6wzCkq19dk7A0MofsvjS_ilTSlQ,3808
7
+ mmrelay/main.py,sha256=a_ZLDiGcBtrZgTlJq8gqGSW8YCduDgAOEDxzwy4AiXE,10097
8
+ mmrelay/matrix_utils.py,sha256=GkIVj2bbPHtx1emFMwhEhc1SWHcv4UvkuyZYdb-Wnwo,30511
9
+ mmrelay/meshtastic_utils.py,sha256=7Q6mQ2gLLc_yjlGCmakPgGRoBB9znRWOCGMW0MgoZ-w,21414
10
+ mmrelay/plugin_loader.py,sha256=QfSXu4nxxBL_pGttLJGzGki8kRtWbFdtSoD_Qnx2iqU,12758
11
+ mmrelay/setup_utils.py,sha256=iFHEGnrop3Lv2j-MDmOGT4oQYuAm_5YHAc16O2rpkew,8022
12
+ mmrelay/plugins/__init__.py,sha256=KVMQIXRhe0wlGj4O3IZ0vOIQRKFkfPYejHXhJL17qrc,51
13
+ mmrelay/plugins/base_plugin.py,sha256=7tBIARWp9Qc4iAEMcsKiUJh1cbqXHcXAk4dlu1b8SBg,7524
14
+ mmrelay/plugins/debug_plugin.py,sha256=Jziht9Nj_bRO6Rmy7TjfBXaYo5eM3XsenbWFxPpyUs4,443
15
+ mmrelay/plugins/drop_plugin.py,sha256=ACchX6GfEldqTyvsZVg-5jwbe2-CjENQVVZFnw8SaEM,4618
16
+ mmrelay/plugins/health_plugin.py,sha256=svV_GfpAVL0QhiVzi3PVZ1mNpsOL1NHSmkRF-Mn_ExE,2250
17
+ mmrelay/plugins/help_plugin.py,sha256=-C4M1PPi1m-fPRvNAlcMyHDNiEEIF6013z2vzrepa1Q,1453
18
+ mmrelay/plugins/map_plugin.py,sha256=tWzNvErSoIjqpWtdR-uhbnqdX1SQZl1XQn3Qrp195Kk,10024
19
+ mmrelay/plugins/mesh_relay_plugin.py,sha256=E04JU4uKr7KTScahS0VKBJ1xwvq1ULJaeFVYEtceMvA,4273
20
+ mmrelay/plugins/nodes_plugin.py,sha256=RDabzyG5hKG5aYWecsRUcLSjMCCv6Pngmq2Qpld1A1U,2903
21
+ mmrelay/plugins/ping_plugin.py,sha256=RTRdgDQUSO33lreDTmWsTlI0L1C3FJrXE0KYqfEWYO0,4017
22
+ mmrelay/plugins/telemetry_plugin.py,sha256=8SxWv4BLXMUTbiVaD3MjlMMdQyS7S_1OfLlVNAUMSO0,6306
23
+ mmrelay/plugins/weather_plugin.py,sha256=yoKA_HdFqFEhgYdXqLhvXatLphCyLJFuGUKCR7fILv0,8546
24
+ mmrelay-1.0.dist-info/licenses/LICENSE,sha256=yceWauM1c0-FHxVplsD7W1-AbSeRaUNlmqT4UO1msBU,1073
25
+ mmrelay-1.0.dist-info/METADATA,sha256=NCTfzxMnJjPpgBtOP0oGD7ZPYQBHA6CiUkvarmYzrGk,6219
26
+ mmrelay-1.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
27
+ mmrelay-1.0.dist-info/entry_points.txt,sha256=SJZwGUOEpQ-qx4H8UL4xKFnKeInGUaZNW1I0ddjK7Ws,45
28
+ mmrelay-1.0.dist-info/top_level.txt,sha256=B_ZLCRm7NYAmI3PipRUyHGymP-C-q16LSeMGzmqJfo4,8
29
+ mmrelay-1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (78.1.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ mmrelay = mmrelay.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 geoffwhittington
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ mmrelay