diff --git a/README.md b/README.md index 23d1344d..7de6d6d1 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,8 @@ dedicated circuit board, but generic development kits such as Raspberry Pi and A high-level system running on a host computer, the software framework has the ability to adapt to any type of hardware component if you are willing to write some codes. -This document will guide you through LEADS VeC. You will find a detailed -version [here](https://leads-docs.projectneura.org/en/latest/vec). +This document will guide you through LEADS VeC. You will find a detailed version +[here](https://leads-docs.projectneura.org/en/latest/vec). LEADS VeC Demo @@ -76,7 +76,8 @@ pip install Pillow PySDL2 customtkinter gpiozero lgpio pynmea2 pynput pysdl2-dll `numpy` and `pandas` will be automatically installed with `leads`. -`Pillow`, `PySDL2`, `customtkinter`, `gpiozero`, `lgpio`, `pynmea2`, `pynput`, `pysdl2-dll`, and `pyserial` are optional. +`Pillow`, `PySDL2`, `customtkinter`, `gpiozero`, `lgpio`, `pynmea2`, `pynput`, `pysdl2-dll`, and `pyserial` are +optional. If you only want the framework, run the following. @@ -232,9 +233,6 @@ If not specified, all configurations will be default values. To learn about the configuration file, read [Configurations](#configurations). -If you install Python using the scripts, you will not find `python ...`, `python3 ...`, `pip ...`, or `pip3 ...` working -because you have to specify the Python version such that `python3.12 ...` and `python3.12 -m pip ...`. - ## Environment Setup This section helps you set up the identical environment we have for the VeC project. A more detailed guide of @@ -243,18 +241,43 @@ Ubuntu 22.04 LTS on a Raspberry Pi 4 Model B 8GB. After the OS is set up, just r You may also choose to clone the repository or download the scripts from [releases](https://github.com/ProjectNeura/LEADS/releases) (only stable releases provide scripts). -These scripts currently only support Ubuntu. +These scripts currently only support `apt` as the package manager. + +If you install Python using the scripts, you will not find `python ...`, `python3 ...`, `pip ...`, or `pip3 ...` working +because you have to specify the Python environment such that `/usr/local/leads/venv/bin/python ...` and +`/usr/local/leads/venv/bin/pip ...`. -### Python and LEADS +### LEADS -You can simply run "[setup.sh](scripts/setup.sh)" and it will install everything including all the optional dependencies -of LEADS for you. +You can simply run "[setup.sh](scripts/setup.sh)" and it will install everything including Python 3.12 all the optional +dependencies of LEADS for you. ```shell /bin/sh "setup.sh$(wget -O setup.sh https://raw.githubusercontent.com/ProjectNeura/LEADS/master/scripts/setup.sh)" && rm setup.sh || rm setup.sh ``` -### Python Only +To save your time from typing `/usr/local/leads/venv/bin/python -m leads_vec -c /usr/local/leads/config.json run` a +thousand times, we provide a boot script "[leads.sh](scripts/leads.sh)". + +Download it to wherever you feel convenient. + +```shell +wget -O leads.sh https://raw.githubusercontent.com/ProjectNeura/LEADS/master/scripts/leads.sh +``` + +Run it like this. + +```shell +/bin/sh leads.sh {arg1} {arg2} {arg3} ... +``` + +It specifies to use this configuration file: "usr/local/leads/config.json". If the file does not exist an error will be +raised. You must [create](#configurations) or [generate](#generate-a-configuration-file) a configuration file with the +exact same path. + +You can always pass other optional arguments additionally to that. + +### Python [python-install.sh](scripts/python-install.sh) will only install Python 3.12 and Tcl/Tk. @@ -280,7 +303,7 @@ To configure frp, use "[frp-config.sh](scripts/frp-config.sh)". There are 4 arguments for this script, of which the first 2 are required. ```shell -/bin/sh "frp-config.sh$(...)" ${frp server IP} ${frp token} ${frp port} ${LEADS comm port} && rm frp-config.sh || rm frp-config.sh +/bin/sh "frp-config.sh$(...)" {frp_server_ip} {frp_token} {frp_port} {comm_port} && rm frp-config.sh || rm frp-config.sh ``` ### OBS Studio diff --git a/leads_vec/__main__.py b/leads_vec/__main__.py index 8f71b645..b336233c 100644 --- a/leads_vec/__main__.py +++ b/leads_vec/__main__.py @@ -1,10 +1,9 @@ from argparse import ArgumentParser as _ArgumentParser, BooleanOptionalAction as _BooleanOptionalAction from importlib.metadata import version as _package_version, PackageNotFoundError as _PackageNotFoundError from importlib.util import spec_from_file_location as _spec_from_file_location, module_from_spec as _module_from_spec -from os import mkdir as _mkdir, chmod as _chmod +from os import getlogin as _get_login from os.path import abspath as _abspath from os.path import exists as _exists -from subprocess import run as _run from sys import exit as _exit, version as _version from warnings import filterwarnings as _filterwarnings @@ -22,7 +21,7 @@ parser = _ArgumentParser(prog="LEADS VeC", description="Lightweight Embedded Assisted Driving System VeC", - epilog="ProjectNeura: https://projectneura.org" + epilog="ProjectNeura: https://projectneura.org\n" "GitHub: https://github.com/ProjectNeura/LEADS") parser.add_argument("action", choices=("info", "replay", "run")) parser.add_argument("-c", "--config", default=None, help="specify a configuration file") @@ -51,6 +50,7 @@ _L.info(f"LEADS VeC", f"System Kernel: {_get_system_kernel().upper()}", f"Python Version: {_version}", + f"User: {_get_login()}", f"`frpc` Available: {_frpc_exists()}", f"Module Path: {_MODULE_PATH}", f"LEADS Version: {leads_version}", @@ -58,19 +58,11 @@ sep="\n") _exit() if args.register == "systemd": - if _get_system_kernel() != "linux": - _exit("Error: Unsupported operating system") - if not _exists("/usr/local/leads/config.json"): - _L.info("Config file not found. Creating \"/usr/local/leads/config.json\"...") - _mkdir("/usr/local/leads") - with open("/usr/local/leads/config.json", "w") as f: - f.write(str(_Config({}))) - _L.info("Using \"/usr/local/leads/config.json\"") - _chmod("/usr/local/leads/config.json", 777) from ._bootloader import create_service as _create_service _create_service() _L.info("Service registered") + _L.info(f"Service script is located at \"{_MODULE_PATH}/_bootloader/leads_vec.service.sh\"") elif args.register == "config": if _exists("config.json"): r = input("\"config.json\" already exists. Overwrite? (y/N) >>>").lower() @@ -94,13 +86,10 @@ config.auto_magnify_font_sizes() _register_config(config) if args.xws: - if _get_system_kernel() != "linux": - _exit("Error: Unsupported operating system") - from os import getuid as _getuid - from pwd import getpwuid as _getpwuid + from ._bootloader import configure_xws as _configure_xws - _L.info("Configuring X Window System...") - _run(("/usr/bin/xhost", f"+SI:localuser:{_getpwuid(_getuid()).pw_name}")) + _configure_xws() + _L.info("X Window System configured") from leads_vec.cli import main diff --git a/leads_vec/_bootloader/__init__.py b/leads_vec/_bootloader/__init__.py index 752916d7..46cea2c4 100644 --- a/leads_vec/_bootloader/__init__.py +++ b/leads_vec/_bootloader/__init__.py @@ -1,2 +1,3 @@ from leads_vec._bootloader.frp import * from leads_vec._bootloader.systemd import * +from leads_vec._bootloader.xws import * diff --git a/leads_vec/_bootloader/leads_vec.service.sh b/leads_vec/_bootloader/leads_vec.service.sh index 307c85f0..4c2c26be 100644 --- a/leads_vec/_bootloader/leads_vec.service.sh +++ b/leads_vec/_bootloader/leads_vec.service.sh @@ -3,4 +3,7 @@ then echo "Error: Config file does not exist" exit 1 fi -python3.12 -m leads_vec -c /usr/local/leads/config.json --xws run \ No newline at end of file + +# change the interpreter or adjust the arguments according to your needs +# but do not remove `--xws` +/usr/local/leads/venv/bin/python -m leads_vec -c /usr/local/leads/config.json --xws run \ No newline at end of file diff --git a/leads_vec/_bootloader/systemd.py b/leads_vec/_bootloader/systemd.py index 7ccdb3a9..689f2ed4 100644 --- a/leads_vec/_bootloader/systemd.py +++ b/leads_vec/_bootloader/systemd.py @@ -1,8 +1,20 @@ -from os import chmod as _chmod, getlogin as _get_login -from os.path import abspath as _abspath +from os import chmod as _chmod, getlogin as _get_login, mkdir as _mkdir +from os.path import abspath as _abspath, exists as _exists + +from leads import L as _L +from leads_gui import Config as _Config +from leads_gui.system import get_system_kernel as _get_system_kernel def create_service() -> None: + if _get_system_kernel() != "linux": + raise SystemError("Unsupported operating system") + if not _exists("/usr/local/leads/config.json"): + _L.debug("Config file not found. Creating \"/usr/local/leads/config.json\"...") + _mkdir("/usr/local/leads") + with open("/usr/local/leads/config.json", "w") as f: + f.write(str(_Config({}))) + _chmod("/usr/local/leads/config.json", 777) _chmod(f"{(script := _abspath(__file__)[:-10])}leads_vec.service.sh", 777) with open("/etc/systemd/system/leads_vec.service", "w") as f: f.write( diff --git a/leads_vec/_bootloader/xws.py b/leads_vec/_bootloader/xws.py new file mode 100644 index 00000000..1c663511 --- /dev/null +++ b/leads_vec/_bootloader/xws.py @@ -0,0 +1,10 @@ +from os import getlogin as _get_login +from subprocess import run as _run + +from leads_gui.system import get_system_kernel as _get_system_kernel + + +def configure_xws() -> None: + if _get_system_kernel() != "linux": + raise SystemError("Unsupported operating system") + _run(("/usr/bin/xhost", f"+SI:localuser:{_get_login()}")) diff --git a/readthedocs b/readthedocs index 0ee167af..a1e60182 160000 --- a/readthedocs +++ b/readthedocs @@ -1 +1 @@ -Subproject commit 0ee167af6a80df47747d13b6f362c9d7fe7b9cc6 +Subproject commit a1e60182e53ab6f564bca83744dc99e8eed627e3 diff --git a/scripts/frp-config.sh b/scripts/frp-config.sh index 21ccebce..9b7cc12e 100644 --- a/scripts/frp-config.sh +++ b/scripts/frp-config.sh @@ -8,6 +8,9 @@ abort() { if [ "${EUID:-$(id -u)}" -ne 0 ]; then abort "Error: This script requires root permission" fi +if ! test -d "/usr/local/frp"; +then abort "Error: /usr/local/frp not found" +fi execute() { if ! "$@"; @@ -32,15 +35,13 @@ argument_exists_or() { else echo "$2" fi } -if ! test -d "/usr/local/frp"; -then abort "frp not found" -fi + echo "Configuring client..." -echo "serverAddr = \"$(require_argument "$1" "frp server IP")\"" > "/usr/local/frp/frpc.toml" +echo "serverAddr = \"$(require_argument "$1" "frp_server_ip")\"" > "/usr/local/frp/frpc.toml" { echo "serverPort = $(argument_exists_or "$3" "7000")" echo "auth.method = \"token\"" - echo "auth.token = \"$(require_argument "$2" "frp token")\"" + echo "auth.token = \"$(require_argument "$2" "frp_token")\"" echo "[[proxies]]" echo "name = \"leads-vec-comm\"" echo "type = \"tcp\"" @@ -52,7 +53,7 @@ echo "Configuring server..." echo "bindPort = $(argument_exists_or "$3" "7000")" > "/usr/local/frp/frps.toml" { echo "auth.method = \"token\"" - echo "auth.token = \"$(require_argument "$2" "frp token")\"" + echo "auth.token = \"$(require_argument "$2" "frp_token")\"" echo "vhostHTTPPort = 80" echo "vhostHTTPSPort = 443" } >> "/usr/local/frp/frps.toml" \ No newline at end of file diff --git a/scripts/frp-install.sh b/scripts/frp-install.sh index 0d6602e5..68e030d6 100644 --- a/scripts/frp-install.sh +++ b/scripts/frp-install.sh @@ -9,6 +9,10 @@ if [ "${EUID:-$(id -u)}" -ne 0 ]; then abort "Error: This script requires root permission" fi +if test -d "/usr/local/frp"; +then abort "Error: /usr/local/frp already exists" +fi + execute() { if ! "$@"; then abort "$(printf "Failed: %s" "$@")" @@ -19,9 +23,6 @@ execute_root() { execute "sudo" "$@" } -if test -d "/usr/local/frp"; -then abort "/usr/local/frp already exists" -fi if ! command -v curl > /dev/null; then echo "cURL is not available, installing..." diff --git a/scripts/leads.sh b/scripts/leads.sh new file mode 100644 index 00000000..5869dd89 --- /dev/null +++ b/scripts/leads.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +abort() { + printf "%s\n" "$@" >&2 + exit 1 +} + +execute() { + if ! "$@"; + then abort "$(printf "Failed: %s" "$@")" + fi +} + +execute "/usr/local/leads/venv/bin/python" "-m" "leads_vec" "-c" "/usr/local/leads/config.json" "$@" "run" \ No newline at end of file diff --git a/scripts/python-install.sh b/scripts/python-install.sh index 90d4fbac..f1b820b6 100644 --- a/scripts/python-install.sh +++ b/scripts/python-install.sh @@ -24,10 +24,7 @@ execute_root "add-apt-repository" "ppa:deadsnakes/ppa" execute_root "apt" "update" echo "Installing Python 3.12..." execute_root "apt" "install" "-y" "gcc" "python3.12" "python3.12-dev" -echo "Fixing Pip..." -execute_root "wget" "-O" "get-pip.py" "https://bootstrap.pypa.io/get-pip.py" -execute_root "python3.12" "get-pip.py" -echo "Cleaning up..." -execute_root "rm" "get-pip.py" echo "Installing Tcl/Tk..." -execute_root "apt" "install" "-y" "python3.12-tk" \ No newline at end of file +execute_root "apt" "install" "-y" "python3.12-tk" +echo "Creating Virtual Environment..." +execute_root "python3.12" "-m" "venv" "/usr/local/leads/venv" \ No newline at end of file diff --git a/scripts/setup.sh b/scripts/setup.sh index 958edf0b..242f28bc 100644 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -25,5 +25,5 @@ execute_root "/bin/sh" "python-install.sh" echo "Cleaning up..." execute_root "rm" "python-install.sh" echo "Installing dependencies..." -execute "python3.12" "-m" "pip" "install" "Pillow" "PySDL2" "customtkinter" "gpiozero" "lgpio" "pynmea2" "pynput" "pysdl2-dll" "pyserial" "leads" -execute "python3.12" "-m" "leads_vec" "info" \ No newline at end of file +execute "/usr/local/leads/venv/bin/pip" "install" "Pillow" "PySDL2" "customtkinter" "gpiozero" "lgpio" "pynmea2" "pynput" "pysdl2-dll" "pyserial" "leads" +execute "/usr/local/leads/venv/bin/python" "-m" "leads_vec" "info" \ No newline at end of file