diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..276815c --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +meshtastic-client_*.deb +meshtastic-client_*.rpm +/tmp/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..99bd185 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,12 @@ +# AGENT Instructions for Meshtastic Linux Client + +## Required Checks +- Run `flake8` for style and syntax errors. +- Execute `bandit -r . -n 5` for basic security scanning. +- Validate markdown docs with `mdl README.md docs/README.md`. +- Build packaging artifacts using: + - `fpm -s dir -t deb -n meshtastic-client -v 1.0 --prefix=/opt/meshtastic-linux-client .` + - `fpm -s dir -t rpm -n meshtastic-client -v 1.0 --prefix=/opt/meshtastic-linux-client .` + +## Pull Request Notes +Summarize significant changes and include the test results output. If package or test commands fail due to missing dependencies or network limits, mention that in the Testing section. diff --git a/README.md b/README.md index 11df3e4..19977e6 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ A full-featured Linux desktop client for Meshtastic radios. Built with ❤️ by [KAUNIX]. ## Features + - Bluetooth scan and connect - Chat messaging with timestamps - Per-channel and per-message AES encryption @@ -15,22 +16,36 @@ Built with ❤️ by [KAUNIX]. - Chat export ## Installation + ```bash sudo apt install python3-pip pip3 install -r requirements.txt python3 main.py +``` + +## Screenshots - # Screenshots +### Main Chat Window -## Main Chat Window ![Main Chat](screenshots/main_chat_window.png) -## Mesh Map +### Mesh Map + ![Mesh Map](screenshots/mesh_map.png) -## Settings Panel +### Settings Panel + ![Settings](screenshots/settings_panel.png) -## Node Info Window +### Node Info Window + ![Node Info](screenshots/node_info_window.png) +## Packaging + +Run `./build_packages.sh` to create `.deb` and `.rpm` packages for release. + +## Contributing + +See [AGENTS.md](AGENTS.md) for required tests and packaging steps +before submitting pull requests. diff --git a/backend/bluetooth_handler.py b/backend/bluetooth_handler.py index d82bdc8..93787be 100644 --- a/backend/bluetooth_handler.py +++ b/backend/bluetooth_handler.py @@ -4,10 +4,12 @@ Handles Bluetooth scanning and connecting to Meshtastic devices. """ + import asyncio import bleak import meshtastic.ble_interface + class BluetoothHandler: """Handles scanning for Bluetooth devices and connecting.""" @@ -44,4 +46,3 @@ def disconnect(self): if self.interface: asyncio.run(self.interface.close()) self.interface = None - diff --git a/backend/message_handler.py b/backend/message_handler.py index d244209..85a7721 100644 --- a/backend/message_handler.py +++ b/backend/message_handler.py @@ -4,9 +4,11 @@ Handles sending and receiving chat messages through Meshtastic. """ + import asyncio from threading import Thread + class MessageHandler: """Handles sending and receiving text messages.""" @@ -49,4 +51,3 @@ def _run_forever(self): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop.run_forever() - diff --git a/build_packages.sh b/build_packages.sh new file mode 100755 index 0000000..83f0cd4 --- /dev/null +++ b/build_packages.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e +VERSION=${1:-1.0} +PREFIX=/opt/meshtastic-linux-client + +fpm -s dir -t deb -n meshtastic-client -v "$VERSION" --prefix="$PREFIX" . +fpm -s dir -t rpm -n meshtastic-client -v "$VERSION" --prefix="$PREFIX" . diff --git a/docs/README.md b/docs/README.md index 0ff3e92..dc43b9d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,18 +9,21 @@ Built for Linux Mint, Ubuntu, Debian — Secure, Off-Grid Communications. ## 🚀 Quick Start 1. Clone the repository: + ```bash git clone https://github.com/YOUR_USERNAME/meshtastic-linux-client.git cd meshtastic-linux-client ``` -2. Install dependencies: +1. Install dependencies: + ```bash sudo apt install python3-pip pip3 install -r requirements.txt ``` -3. Run the app: +1. Run the app: + ```bash python3 main.py ``` @@ -53,10 +56,10 @@ Built for Linux Mint, Ubuntu, Debian — Secure, Off-Grid Communications. | Issue | Fix | |:---|:---| -| App won't launch | Make sure all Python dependencies are installed (`pip3 install -r requirements.txt`) | -| Bluetooth not finding nodes | Ensure your device is advertising over BLE and that Linux Bluetooth services are active | +| App won't launch | Install deps with `pip3 install -r requirements.txt` | +| Bluetooth not finding nodes | Enable BLE ads and check the Bluetooth service | | Mesh map empty | Check that multiple nodes are powered and linked | -| Message decryption fails | Verify you have the correct encryption key for that channel | +| Message decryption fails | Verify the correct key is set for that channel | --- @@ -72,4 +75,3 @@ Pull Requests welcome! Open an Issue to report bugs, suggest features, or just say hi! --- - diff --git a/main.py b/main.py index e561833..b1aa3be 100644 --- a/main.py +++ b/main.py @@ -4,10 +4,12 @@ Launches the main PyQt6-based Meshtastic Linux Client GUI. """ + import sys from PyQt6 import QtWidgets from ui.main_window import MainWindow + def main(): """Main entry point.""" app = QtWidgets.QApplication(sys.argv) @@ -16,6 +18,6 @@ def main(): window.show() sys.exit(app.exec()) + if __name__ == "__main__": main() - diff --git a/ui/advanced_settings_window.py b/ui/advanced_settings_window.py index fd791a8..604baa3 100644 --- a/ui/advanced_settings_window.py +++ b/ui/advanced_settings_window.py @@ -4,8 +4,10 @@ Provides access to radio transmission settings (power, interval, modem config). """ + from PyQt6 import QtWidgets + class AdvancedSettingsWindow(QtWidgets.QWidget): """Window for advanced radio settings.""" @@ -25,4 +27,3 @@ def setup_ui(self): layout.addRow("TX Power (dBm):", self.tx_power) layout.addRow("Broadcast Interval (s):", self.broadcast_interval) self.setLayout(layout) - diff --git a/ui/firmware_update_window.py b/ui/firmware_update_window.py index 9c353c1..780e29c 100644 --- a/ui/firmware_update_window.py +++ b/ui/firmware_update_window.py @@ -4,8 +4,10 @@ Allows users to upload and flash new firmware to Meshtastic devices. """ + from PyQt6 import QtWidgets + class FirmwareUpdateWindow(QtWidgets.QWidget): """Window for firmware updates.""" @@ -23,4 +25,3 @@ def setup_ui(self): layout.addWidget(self.choose_file_button) layout.addWidget(self.flash_button) self.setLayout(layout) - diff --git a/ui/main_window.py b/ui/main_window.py index b8368b3..7192467 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -1,10 +1,12 @@ """ Main Window -Defines the main application window, containing sidebar buttons, chat display, device list, and chat input. +Defines the main application window, containing sidebar buttons, chat display, +device list, and chat input. """ -from PyQt6 import QtWidgets, QtCore, QtGui +from PyQt6 import QtWidgets + class MainWindow(QtWidgets.QMainWindow): """Main window for the Meshtastic Linux Client.""" @@ -13,5 +15,15 @@ def __init__(self): super().__init__() self.setWindowTitle("Meshtastic Linux Client") self.resize(1000, 700) - self.setup + self.setup_ui() + + def setup_ui(self): + """Configure top-level widgets.""" + central = QtWidgets.QWidget() + layout = QtWidgets.QVBoxLayout(central) + self.chat_display = QtWidgets.QTextEdit() + self.device_list = QtWidgets.QListWidget() + layout.addWidget(self.chat_display) + layout.addWidget(self.device_list) + self.setCentralWidget(central) diff --git a/ui/mesh_map_window.py b/ui/mesh_map_window.py index b3539fb..df7deb5 100644 --- a/ui/mesh_map_window.py +++ b/ui/mesh_map_window.py @@ -4,8 +4,10 @@ Visualizes the connected Meshtastic mesh network topology. """ + from PyQt6 import QtWidgets + class MeshMapWindow(QtWidgets.QWidget): """Window displaying mesh network map.""" @@ -21,4 +23,3 @@ def setup_ui(self): self.map_canvas = QtWidgets.QLabel("Mesh Map Visualization Here (WIP)") layout.addWidget(self.map_canvas) self.setLayout(layout) - diff --git a/ui/node_info_window.py b/ui/node_info_window.py index 818a334..cede8aa 100644 --- a/ui/node_info_window.py +++ b/ui/node_info_window.py @@ -4,8 +4,10 @@ Displays information about the connected Meshtastic device. """ + from PyQt6 import QtWidgets + class NodeInfoWindow(QtWidgets.QWidget): """Window showing node firmware, hardware info.""" @@ -23,4 +25,3 @@ def setup_ui(self): layout.addRow("Firmware Version:", self.firmware_label) layout.addRow("Hardware Model:", self.hardware_label) self.setLayout(layout) - diff --git a/ui/settings_window.py b/ui/settings_window.py index c5052a1..d9b8d3c 100644 --- a/ui/settings_window.py +++ b/ui/settings_window.py @@ -4,8 +4,10 @@ Provides an interface for user-configurable settings. """ + from PyQt6 import QtWidgets + class SettingsWindow(QtWidgets.QWidget): """Window for application settings.""" @@ -21,4 +23,3 @@ def setup_ui(self): self.dark_mode_toggle = QtWidgets.QCheckBox("Enable Dark Mode") layout.addWidget(self.dark_mode_toggle) self.setLayout(layout) -