From 85240402dad947b61ef9090f79078d1c66de8f54 Mon Sep 17 00:00:00 2001 From: Terry Fu Date: Sat, 11 May 2024 17:51:40 -0400 Subject: [PATCH] Autostart Works Partially on Raspberry Pi (#158) * Set the service environment variable `XAUTHORITY` to the value of the outer environment variable when creating the service. (https://github.com/ProjectNeura/LEADS/issues/156#issuecomment-2105995160) * Removed XWS configuring. (#156) * Supported more precise display manager dependencies. (#156) * Code reformatted. * Converted `leads_vec` to a user service `leads-vec`. (https://github.com/ProjectNeura/LEADS/issues/156#issuecomment-2106001543) * Using auto restart to replace delaying. (#156) * Docs. (#156) * Docs. * Bug fixed: mkdir: no such file or directory. (#156) * Code reformatted. --- README.md | 20 ++++++++++++---- leads_vec/__main__.py | 4 ++-- ...ds_vec.service.sh => leads-vec.service.sh} | 7 +----- leads_vec/_bootloader/systemd.py | 24 +++++++++---------- leads_vec_rc/cli.py | 6 ++--- scripts/frp-config.sh | 14 +++++------ scripts/frp-install.sh | 2 +- setup.py | 2 +- 8 files changed, 43 insertions(+), 36 deletions(-) rename leads_vec/_bootloader/{leads_vec.service.sh => leads-vec.service.sh} (59%) diff --git a/README.md b/README.md index d5669430..82ee6ba2 100644 --- a/README.md +++ b/README.md @@ -149,13 +149,25 @@ This will generate a default "config.json" file under the current directory. python -m leads_vec -r systemd run ``` -This will register a system service to start the program. +This will register a user systemd service to start the program. To enable auto-start at boot, run the following. ```shell -systemctl daemon-reload -systemctl enable leads_vec +systemctl --user daemon-reload +systemctl --user enable leads-vec +``` + +You will have to stop the service by this command otherwise it will automatically restart when it exits. + +```shell +systemctl --user stop leads-vec +``` + +Use the following to disable the service. + +```shell +systemctl --user disable leads-vec ``` ##### Use Reverse Proxy @@ -331,7 +343,7 @@ Note that a purely empty file could cause an error. |---------------------|---------|-----------------------------------------------------------|--------------|---------------| | `w_debug_level` | `str` | `"DEBUG"`, `"INFO"`, `"WARN"`, `"ERROR"` | Main, Remote | `"DEBUG"` | | `data_seq_size` | `int` | Buffer size of history data | Main | `100` | -| `data_dir` | `str` | The directory for the data recording system | Remote | `"data"` | +| `data_dir` | `str` | The directory for the data recording system | Main, Remote | `"data"` | | `width` | `int` | Window width | Main | `720` | | `height` | `int` | Window height | Main | `480` | | `fullscreen` | `bool` | `True`: auto maximize; `False`: window mode | Main | `False` | diff --git a/leads_vec/__main__.py b/leads_vec/__main__.py index aa2296ce..d5172e4c 100644 --- a/leads_vec/__main__.py +++ b/leads_vec/__main__.py @@ -57,11 +57,11 @@ sep="\n") _exit() if args.register == "systemd": - from ._bootloader import create_service as _create_service + from ._bootloader import register_leads_vec as _create_service _create_service() _L.info("Service registered") - _L.info(f"Service script is located at \"{_MODULE_PATH}/_bootloader/leads_vec.service.sh\"") + _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() diff --git a/leads_vec/_bootloader/leads_vec.service.sh b/leads_vec/_bootloader/leads-vec.service.sh similarity index 59% rename from leads_vec/_bootloader/leads_vec.service.sh rename to leads_vec/_bootloader/leads-vec.service.sh index f7c1c2cc..1c1853ed 100644 --- a/leads_vec/_bootloader/leads_vec.service.sh +++ b/leads_vec/_bootloader/leads-vec.service.sh @@ -1,14 +1,9 @@ #!/bin/bash -if [ ! -r "/usr/local/leads/config.json" ] +if test ! -r "/usr/local/leads/config.json" then echo "Error: Config file does not exist" exit 1 fi -while ! xhost >& /dev/null -do sleep 1 -done -# configure xws -/usr/bin/xhost +SI:localuser:"$USERNAME" # change the interpreter or adjust the arguments according to your needs python-leads -m leads_vec -c /usr/local/leads/config.json run \ No newline at end of file diff --git a/leads_vec/_bootloader/systemd.py b/leads_vec/_bootloader/systemd.py index 11609e32..dae360ea 100644 --- a/leads_vec/_bootloader/systemd.py +++ b/leads_vec/_bootloader/systemd.py @@ -1,4 +1,4 @@ -from os import chmod as _chmod, getlogin as _get_login, mkdir as _mkdir +from os import chmod as _chmod, getlogin as _get_login, makedirs as _mkdirs from os.path import abspath as _abspath, exists as _exists from leads import L as _L @@ -6,30 +6,30 @@ from leads_gui.system import get_system_kernel as _get_system_kernel -def create_service() -> None: +def register_leads_vec() -> 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\"...") if not _exists("/usr/local/leads"): - _mkdir("/usr/local/leads") + _mkdirs("/usr/local/leads") with open("/usr/local/leads/config.json", "w") as f: f.write(str(_Config({}))) _chmod("/usr/local/leads/config.json", 0x644) - _chmod(script := f"{_abspath(__file__)[:-10]}leads_vec.service.sh", 0o755) - with open("/etc/systemd/system/leads_vec.service", "w") as f: + _chmod(script := f"{_abspath(__file__)[:-10]}leads-vec.service.sh", 0o755) + if not _exists(user_systemd := f"/home/{_get_login()}/.config/systemd/user"): + _L.debug(f"User systemd not found. Creating \"{user_systemd}\"...") + _mkdirs(user_systemd) + with open(f"{user_systemd}/leads-vec.service", "w") as f: f.write( "[Unit]\n" "Description=LEADS VeC\n" - "After=display-manager.service\n" - "Requires=display-manager.service\n" + "After=graphical-session.target\n" "[Service]\n" "Type=simple\n" - f"User={(user := _get_login())}\n" - f"Environment=\"USERNAME={user}\"\n" - "Environment=\"DISPLAY=:0\"\n" - f"Environment=\"XAUTHORITY=/home/{user}/.Xauthority\"\n" f"ExecStart=/bin/bash {script}\n" + f"Restart=always\n" + f"RestartSec=1s\n" "[Install]\n" - "WantedBy=graphical.target" + "WantedBy=default.target" ) diff --git a/leads_vec_rc/cli.py b/leads_vec_rc/cli.py index 98198503..1d368e4d 100644 --- a/leads_vec_rc/cli.py +++ b/leads_vec_rc/cli.py @@ -1,7 +1,7 @@ from atexit import register from datetime import datetime from json import loads, JSONDecodeError -from os import mkdir +from os import makedirs from os.path import abspath, exists from time import sleep from typing import Any @@ -15,8 +15,8 @@ config = require_config() if not exists(config.data_dir): - mkdir(config.data_dir) - L.info(f"Data dir \"{abspath(config.data_dir)}\" created") + L.debug(f"Data directory not found. Creating \"{abspath(config.data_dir)}\"...") + makedirs(config.data_dir) data_record: DataPersistence[DataContainer] = DataPersistence(1, compressor=lambda o, s: o[-s:]) time_stamp_record: DataPersistence[int] = DataPersistence(2000) diff --git a/scripts/frp-config.sh b/scripts/frp-config.sh index 80437a37..a8c05e00 100644 --- a/scripts/frp-config.sh +++ b/scripts/frp-config.sh @@ -8,7 +8,7 @@ abort() { if [ "${EUID:-$(id -u)}" -ne 0 ] then abort "Error: This script requires root permission" fi -if ! test -d "/usr/local/frp" +if test ! -d "/usr/local/frp" then abort "Error: /usr/local/frp not found" fi @@ -23,16 +23,16 @@ execute_root() { } require_argument() { - if [ -n "$1" ] - then echo "$1" - else abort "Required argument $2 does not exist" + if test -z "$1" + then abort "Required argument $2 does not exist" + else echo "$1" fi } argument_exists_or() { - if [ -n "$1" ] - then echo "$1" - else echo "$2" + if test -z "$1" + then echo "$2" + else echo "$1" fi } diff --git a/scripts/frp-install.sh b/scripts/frp-install.sh index 24ad807c..f02ec12b 100644 --- a/scripts/frp-install.sh +++ b/scripts/frp-install.sh @@ -29,7 +29,7 @@ then execute_root "apt" "install" "-y" "curl" fi latest_release=$(curl -s "https://api.github.com/repos/fatedier/frp/releases/latest" | grep -o '"tag_name": "[^"]*' | grep -o '[^"]*$' | cut -c 2-) -if [ -z "$latest_release" ] +if test -z "$latest_release" then abort "Failed to retrieve the latest release" fi filename="frp_${latest_release}_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m)" diff --git a/setup.py b/setup.py index 182278a0..04848f36 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ package_data={ "leads_audio": ["assets/*"], "leads_gui": ["assets/*", "assets/icons/*"], - "leads_vec": ["_bootloader/leads_vec.service.sh"] + "leads_vec": ["_bootloader/leads-vec.service.sh"] }, include_package_data=True, install_requires=["numpy", "pandas"]