diff --git a/LinuxMint/create_local_venv.sh b/LinuxMint/create_local_venv.sh index daba959..b9399ac 100644 --- a/LinuxMint/create_local_venv.sh +++ b/LinuxMint/create_local_venv.sh @@ -1,21 +1,72 @@ -#!/bin/bash -set -e +#!/usr/bin/env bash +set -euo pipefail # create_local_venv.sh -# Dev helper: create a local venv for running meshtastic_client.py -# directly from the project folder (e.g. in VS Code). +# Dev helper: create a *local* venv for running meshtastic_client.py directly +# from the project folder (e.g. in VS Code). +# +# Key goals: +# - Make the project directory the current directory. +# - Keep it movable: no hard-coded absolute paths required. +# - Ensure Tkinter is installed at *system level* (it is not a pip package). -PROJECT_DIR="/home/knud/Desktop/Meshtastic/Meshtastic_client" -VENV_DIR="${PROJECT_DIR}/.venv" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +DEFAULT_PROJECT_DIR="$SCRIPT_DIR" + +# Tip: +# If you run this script *from inside* the project folder, you can set: +# MESHTASTIC_CLIENT_DIR="." ./create_local_venv.sh +# But the safest movable default is the folder where this script lives. + +# You can override the project location when you move the folder: +# MESHTASTIC_CLIENT_DIR=/path/to/Meshtastic_client ./create_local_venv.sh +# Or (only if you launch it from inside the repo): +# MESHTASTIC_CLIENT_DIR="." ./create_local_venv.sh +PROJECT_DIR="${MESHTASTIC_CLIENT_DIR:-$DEFAULT_PROJECT_DIR}" + +# Normalize to an absolute path (handles "." etc.) +PROJECT_DIR="$(realpath -m "$PROJECT_DIR")" + +# Basic sanity checks +if [[ ! -d "$PROJECT_DIR" ]]; then + echo "ERROR: Project dir not found: $PROJECT_DIR" >&2 + exit 1 +fi + +# If the script is inside the repo, this helps catch mis-pointing. +if [[ ! -f "$PROJECT_DIR/meshtastic_client.py" ]]; then + echo "WARNING: meshtastic_client.py not found in: $PROJECT_DIR" >&2 + echo " If you moved the repo, set MESHTASTIC_CLIENT_DIR to the new path." >&2 +fi + +VENV_DIR="$PROJECT_DIR/.venv" echo "Project dir : $PROJECT_DIR" echo "Local venv : $VENV_DIR" -cd "$PROJECT_DIR" || exit 1 -if [ -d "$VENV_DIR" ]; then - echo "Local venv already exists at $VENV_DIR" +# Make PROJECT_DIR the current directory +cd "$PROJECT_DIR" + +# --- Tkinter (system level) ------------------------------------------------- +# Tkinter is provided by distro packages (Debian/Ubuntu/Mint: python3-tk). +# It cannot be installed reliably with pip inside a venv. + +if ! python3 -c 'import tkinter' >/dev/null 2>&1; then + echo + echo "Tkinter is missing for system python3." >&2 + echo "Install it system-wide (Linux Mint / Ubuntu / Debian):" >&2 + echo " sudo apt update" >&2 + echo " sudo apt install -y python3-tk" >&2 + echo + echo "After installing, re-run this script." >&2 + exit 2 +fi + +# --- venv ------------------------------------------------------------------- +if [[ -d "$VENV_DIR" ]]; then + echo "Local venv already exists at: $VENV_DIR" echo "If you want a fresh one, delete it first:" - echo " rm -rf "$VENV_DIR"" + echo " rm -rf \"$VENV_DIR\"" exit 0 fi @@ -26,16 +77,21 @@ echo "Upgrading pip inside venv..." "$VENV_DIR/bin/pip" install --upgrade pip echo "Installing dev dependencies into local venv..." -"$VENV_DIR/bin/pip" install meshtastic pyserial pypubsub protobuf bleak +"$VENV_DIR/bin/pip" install \ + meshtastic \ + pyserial \ + pypubsub \ + protobuf \ + bleak echo "Writing requirements.txt (for reference)..." -cat > "$PROJECT_DIR/requirements.txt" << EOF +cat > "$PROJECT_DIR/requirements.txt" <<'REQ' meshtastic pyserial pypubsub protobuf bleak -EOF +REQ echo echo "====================================================" @@ -46,6 +102,6 @@ echo " In VS Code, select this interpreter:" echo " $VENV_DIR/bin/python" echo echo " To run locally from terminal:" -echo " source "$VENV_DIR/bin/activate"" +echo " source \"$VENV_DIR/bin/activate\"" echo " python meshtastic_client.py" echo "====================================================" diff --git a/LinuxMint/meshtastic-client_1.0.202512121818_amd64.deb b/LinuxMint/meshtastic-client_1.0.202512121818_amd64.deb new file mode 100644 index 0000000..4fcf468 Binary files /dev/null and b/LinuxMint/meshtastic-client_1.0.202512121818_amd64.deb differ diff --git a/LinuxMint/rebuilddeb.sh b/LinuxMint/rebuilddeb.sh index abbc83f..bb0ffcd 100644 --- a/LinuxMint/rebuilddeb.sh +++ b/LinuxMint/rebuilddeb.sh @@ -1,91 +1,123 @@ -#!/bin/bash -set -e +#!/usr/bin/env bash +set -euo pipefail -### CONFIG ############################################################ +# rebuilddeb.sh +# Build a .deb from the *current directory* (PROJECT_DIR=".") +# and declare Tkinter as a system requirement (python3-tk). +# +# Usage: +# cd /path/to/Meshtastic_client +# ./rebuilddeb.sh APP_NAME="meshtastic-client" -APP_VERSION=$(date +"1.0.%Y%m%d%H%M") -PROJECT_DIR="/home/knud/Desktop/Meshtastic/Meshtastic_client" -BUILD_DIR="$PROJECT_DIR/build" +APP_VERSION="$(date +"1.0.%Y%m%d%H%M")" +PROJECT_DIR="." # <-- always build from current directory ICON_NAME="meshtastic.png" APP_INSTALL_DIR="/opt/${APP_NAME}" -# Logging +# --- helpers --------------------------------------------------------------- + +die() { echo "ERROR: $*" >&2; exit 1; } + +ensure_dir() { + local d="${1:-}" + [[ -n "$d" ]] || die "ensure_dir() got an empty path (this caused: mkdir: cannot create directory '' ...)" + mkdir -p "$d" +} + +# --- normalize paths -------------------------------------------------------- + +cd "$PROJECT_DIR" || die "Cannot cd to PROJECT_DIR=$PROJECT_DIR" +PROJECT_DIR="$(pwd -P)" + +BUILD_DIR="$PROJECT_DIR/build" LOG_DIR="$PROJECT_DIR/build_logs" -mkdir -p "$LOG_DIR" -LOG_FILE="$LOG_DIR/rebuild_$(date +\"%Y%m%d_%H%M%S\").log" +LOG_FILE="$LOG_DIR/rebuild_$(date +"%Y%m%d_%H%M%S").log" + +ensure_dir "$LOG_DIR" # Send all stdout/stderr to both terminal and log exec > >(tee -a "$LOG_FILE") 2>&1 -echo "Logging to: $LOG_FILE" +echo "=== Building ${APP_NAME} version ${APP_VERSION} ===" +echo "Project dir : ${PROJECT_DIR}" +echo "Build dir : ${BUILD_DIR}" +echo "Log file : ${LOG_FILE}" -###################################################################### +# --- system requirement: Tkinter ------------------------------------------- -echo "=== Building $APP_NAME version $APP_VERSION ===" -cd "$PROJECT_DIR" || exit 1 - -### CLEAN OLD BUILD OUTPUT ########################################### - -echo "[1/5] Cleaning old build dir..." -rm -rf "$BUILD_DIR" -mkdir -p "$BUILD_DIR" - -### CREATE FILE LAYOUT ################################################ -# We do **NOT** bundle a pre-built venv in the .deb anymore. -# Instead we install the app code + a small launcher that creates -# a per-user venv on first run under ~/.local/share/${APP_NAME}/venv. - -echo "[2/5] Creating directory structure in build tree..." - -# App code location on target system (read-only, root-owned) -mkdir -p "$BUILD_DIR${APP_INSTALL_DIR}" - -# Launcher + desktop file + icon -mkdir -p "$BUILD_DIR/usr/local/bin" -mkdir -p "$BUILD_DIR/usr/share/applications" -mkdir -p "$BUILD_DIR/usr/share/icons/hicolor/48x48/apps" - -### COPY APPLICATION CODE ############################################ - -echo "[3/5] Copying application code..." - -cp "$PROJECT_DIR/meshtastic_client.py" "$BUILD_DIR${APP_INSTALL_DIR}/meshtastic_client.py" - -if [ -f "$PROJECT_DIR/$ICON_NAME" ]; then - cp "$PROJECT_DIR/$ICON_NAME" "$BUILD_DIR/usr/share/icons/hicolor/48x48/apps/${APP_NAME}.png" -else - echo " (Warning: $ICON_NAME not found, skipping icon copy)" +# Tkinter must exist system-wide (Debian/Ubuntu/Mint package: python3-tk). +# It cannot be installed with pip inside a venv reliably. +if ! python3 -c 'import tkinter' >/dev/null 2>&1; then + echo "ERROR: Tkinter is missing for system python3." >&2 + echo "Install it:" >&2 + echo " sudo apt update && sudo apt install -y python3-tk" >&2 + exit 2 fi -### CREATE LAUNCHER SCRIPT ########################################### +# --- clean old build output ------------------------------------------------- -echo "[4/5] Generating launcher script /usr/local/bin/${APP_NAME}..." +echo "[1/6] Cleaning old build dir..." +rm -rf "$BUILD_DIR" +ensure_dir "$BUILD_DIR" -LAUNCHER="$BUILD_DIR/usr/local/bin/${APP_NAME}" +# --- create file layout ----------------------------------------------------- -cat > "$LAUNCHER" << 'EOF' -#!/bin/bash -set -e +echo "[2/6] Creating directory structure in build tree..." +ensure_dir "$BUILD_DIR$APP_INSTALL_DIR" +ensure_dir "$BUILD_DIR/usr/local/bin" +ensure_dir "$BUILD_DIR/usr/share/applications" +ensure_dir "$BUILD_DIR/usr/share/icons/hicolor/256x256/apps" + +# --- copy app code ---------------------------------------------------------- + +echo "[3/6] Copying application code..." +# Copy only what we need; ignore missing optional files. +for f in meshtastic_client.py README.md requirements.txt; do + [[ -f "$PROJECT_DIR/$f" ]] && cp -a "$PROJECT_DIR/$f" "$BUILD_DIR$APP_INSTALL_DIR/" +done + +if [[ -f "$PROJECT_DIR/$ICON_NAME" ]]; then + cp -a "$PROJECT_DIR/$ICON_NAME" "$BUILD_DIR/usr/share/icons/hicolor/256x256/apps/${APP_NAME}.png" +else + echo "WARNING: Icon $ICON_NAME not found in project dir." +fi + +# --- create launcher -------------------------------------------------------- + +echo "[4/6] Generating launcher script /usr/local/bin/$APP_NAME..." +LAUNCHER="$BUILD_DIR/usr/local/bin/$APP_NAME" + +cat > "$LAUNCHER" <<'EOF' +#!/usr/bin/env bash +set -euo pipefail APP_NAME="meshtastic-client" APP_DIR="/opt/${APP_NAME}" +DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/${APP_NAME}" +VENV_DIR="${DATA_DIR}/venv" +PY_BIN="$(command -v python3 || true)" -# Per-user venv location (no root needed) -USER_DATA_ROOT="${XDG_DATA_HOME:-$HOME/.local/share}" -USER_APP_DIR="${USER_DATA_ROOT}/${APP_NAME}" -VENV_DIR="${USER_APP_DIR}/venv" +if [[ -z "$PY_BIN" ]]; then + echo "[${APP_NAME}] ERROR: python3 not found." >&2 + exit 1 +fi -PY_BIN="${VENV_DIR}/bin/python" -PIP_BIN="${VENV_DIR}/bin/pip" +# Tkinter must be available at system level +if ! "$PY_BIN" -c 'import tkinter' >/dev/null 2>&1; then + echo "[${APP_NAME}] ERROR: Tkinter is missing (install python3-tk)." >&2 + echo " sudo apt update && sudo apt install -y python3-tk" >&2 + exit 2 +fi -# Create venv + install deps on first start -if [ ! -x "$PY_BIN" ]; then - mkdir -p "$USER_APP_DIR" - echo "[${APP_NAME}] Creating virtualenv in $VENV_DIR ..." - python3 -m venv "$VENV_DIR" +mkdir -p "$DATA_DIR" +if [[ ! -d "$VENV_DIR" ]]; then + echo "[${APP_NAME}] Creating per-user venv at: $VENV_DIR" + "$PY_BIN" -m venv "$VENV_DIR" + + PIP_BIN="$VENV_DIR/bin/pip" echo "[${APP_NAME}] Upgrading pip..." "$PIP_BIN" install --upgrade pip @@ -100,41 +132,43 @@ if [ ! -x "$PY_BIN" ]; then echo "[${APP_NAME}] Virtualenv ready." fi -exec "$PY_BIN" "${APP_DIR}/meshtastic_client.py" "$@" +exec "$VENV_DIR/bin/python" "${APP_DIR}/meshtastic_client.py" "$@" EOF chmod +x "$LAUNCHER" -### CREATE .DESKTOP FILE ############################################# - -echo "[5/5] Creating .desktop file..." +# --- desktop file ----------------------------------------------------------- +echo "[5/6] Creating .desktop file..." DESKTOP_FILE="$BUILD_DIR/usr/share/applications/${APP_NAME}.desktop" -cat > "$DESKTOP_FILE" << EOF +cat > "$DESKTOP_FILE" </dev/null 2>&1 || die "fpm not found. Install it first (e.g. gem install --user-install fpm, or your preferred method)." -echo "[9/9] Building .deb using fpm..." fpm -s dir -t deb -n "$APP_NAME" -v "$APP_VERSION" \ --description "Meshtastic Desktop Client" \ -d python3 \ -d python3-venv \ -d python3-pip \ + -d python3-tk \ -C "$BUILD_DIR" \ . echo "======================================================" echo " Build finished!" -echo " Created package: ${APP_NAME}_${APP_VERSION}_amd64.deb" +echo " Created package (in current dir): ${APP_NAME}_${APP_VERSION}_amd64.deb" echo " Log file: $LOG_FILE" echo "======================================================" diff --git a/LinuxMint/requirements.txt b/LinuxMint/requirements.txt index d5ee007..81fd945 100644 --- a/LinuxMint/requirements.txt +++ b/LinuxMint/requirements.txt @@ -3,5 +3,3 @@ pyserial pypubsub protobuf bleak -google protobuf - diff --git a/LinuxMint/run-client.sh b/LinuxMint/run-client.sh new file mode 100644 index 0000000..0d63a31 --- /dev/null +++ b/LinuxMint/run-client.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Run from the *current directory* (.) so the project can be moved. +PROJECT_DIR="." +cd "$PROJECT_DIR" + +# Load env vars from .envrc (if present) +if [[ -f ".envrc" ]]; then + set -a + # shellcheck disable=SC1091 + source ".envrc" + set +a +fi + +exec python3 meshtastic_client.py