diff --git a/docs/changelog.md b/docs/changelog.md index 6d1a9db..2381537 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,6 +2,12 @@ This document covers possible important changes to KIAUH. +### 2023-02-03 +The installer for MJPG-Streamer got replaced by crowsnest. It is an improved webcam service, utilizing ustreamer. +Please have a look here for additional info about crowsnest and how to configure it: https://github.com/mainsail-crew/crowsnest \ +It's unsure if the previous MJPG-Streamer installer will be updated and make its way back into KIAUH. +A big thanks to [KwadFan](https://github.com/KwadFan) for writing the crowsnest implementation. + ### 2022-10-31 Some functions got updated, though not all of them. diff --git a/scripts/crowsnest.sh b/scripts/crowsnest.sh new file mode 100644 index 0000000..f8ed048 --- /dev/null +++ b/scripts/crowsnest.sh @@ -0,0 +1,241 @@ +#!/usr/bin/env bash + +#=======================================================================# +# Copyright (C) 2020 - 2022 Dominik Willner # +# # +# This file is part of KIAUH - Klipper Installation And Update Helper # +# https://github.com/th33xitus/kiauh # +# # +# This file may be distributed under the terms of the GNU GPLv3 license # +#=======================================================================# + +#=======================================================================# +# Crowsnest Installer brought to you by KwadFan # +# Copyright (C) 2022 KwadFan # +# https://github.com/KwadFan/crowsnest # +#=======================================================================# + +# Error Handling +set -e + +# Helper messages + +function multi_instance_message(){ + echo -e "Crowsnest is NOT designed to support multi instances." + echo -e "A workaround for this is to choose the most used instance as a 'master'" + echo -e "Use this instance to set up your 'crowsnest.conf' and steering it's service.\n" + echo -e "Found the following instances:\n" + for i in ${1}; do + select_msg "${i}" + done + echo -e "\nLaunching crowsnest's configuration tool ..." + continue_config +} + +# Helper funcs +function clone_crowsnest(){ + $(command -v git) clone "${CROWSNEST_REPO}" -b master "${CROWSNEST_DIR}" +} + +function check_multi_instance(){ + local -a instances + readarray -t instances < <(find "${HOME}" -regex "${HOME}/[a-zA-Z0-9_]+_data/*" -printf "%P\n" 2> /dev/null | sort) + if [[ "${#instances[@]}" -gt 1 ]]; then + status_msg "Multi instance install detected ..." + multi_instance_message "${instances[*]}" + if [[ -d "${HOME}/crowsnest" ]]; then + pushd "${HOME}/crowsnest" &> /dev/null || exit 1 + if ! make config ;then + error_msg "Something went wrong! Please try again..." + if [[ -f "tools/.config" ]]; then + rm -f tools/.config + fi + exit 1 + fi + if [[ ! -f "tools/.config" ]]; then + log_error "failure while generating .config" + error_msg "Generating .config failed, installation aborted" + exit 1 + fi + popd &> /dev/null || exit 1 + fi + fi +} + +function continue_config() { + local reply + while true; do + read -erp "${cyan}###### Continue with configuration? (y/N):${white} " reply + case "${reply}" in + Y|y|Yes|yes) + select_msg "Yes" + break;; + N|n|No|no|"") + select_msg "No" + warn_msg "Installation aborted by user ... Exiting!" + exit 1;; + *) + error_msg "Invalid Input!\n";; + esac + done + return 0 +} + +# Install func +function install_crowsnest(){ + + # Step 1: jump to home directory + pushd "${HOME}" &> /dev/null || exit 1 + + # Step 2: Clone crowsnest repo + status_msg "Cloning 'crowsnest' repository ..." + if [[ ! -d "${HOME}/crowsnest" && -z "$(ls -A "${HOME}/crowsnest" 2> /dev/null)" ]]; then + clone_crowsnest + else + ok_msg "crowsnest repository already exists ..." + fi + + # Step 3: Install dependencies + dependency_check git make + + # Step 4: Check for Multi Instance + check_multi_instance + + # Step 5: Launch crowsnest installer + pushd "${HOME}/crowsnest" &> /dev/null || exit 1 + title_msg "Installer will prompt you for sudo password!" + status_msg "Launching crowsnest installer ..." + if ! sudo make install; then + error_msg "Something went wrong! Please try again..." + exit 1 + fi + + # Step 5: Leave directory (twice due two pushd) + popd &> /dev/null || exit 1 + popd &> /dev/null || exit 1 +} + +# Remove func +function remove_crowsnest(){ + pushd "${HOME}/crowsnest" &> /dev/null || exit 1 + title_msg "Uninstaller will prompt you for sudo password!" + status_msg "Launching crowsnest uninstaller ..." + if ! make uninstall; then + error_msg "Something went wrong! Please try again..." + exit 1 + fi + if [[ -e "${CROWSNEST_DIR}" ]]; then + status_msg "Removing crowsnest directory ..." + rm -rf "${CROWSNEST_DIR}" + ok_msg "Directory removed!" + fi +} + +# Status funcs +get_crowsnest_status(){ + local -a files + files=( + "${CROWSNEST_DIR}" + "/usr/local/bin/crowsnest" + "/etc/logrotate.d/crowsnest" + "/etc/systemd/system/crowsnest.service" + "$(find "${HOME}" -name 'crowsnest.env' 2> /dev/null || + echo "${HOME}/printer_data/systemd/crowsnest.env")" + ) + # Contains ugly hackaround for multi instance... :( + local count + count=0 + + for file in "${files[@]}"; do + [[ -e "${file}" ]] && count=$(( count +1 )) + done + if [[ "${count}" -eq "${#files[*]}" ]]; then + echo "Installed" + elif [[ "${count}" -gt 0 ]]; then + echo "Incomplete!" + else + echo "Not installed!" + fi +} + +# Update funcs +# Shameless stolen from KlipperScreen.sh +function get_local_crowsnest_commit() { + [[ ! -d ${CROWSNEST_DIR} || ! -d "${CROWSNEST_DIR}/.git" ]] && return + + local commit + cd "${CROWSNEST_DIR}" + commit="$(git describe HEAD --always --tags | cut -d "-" -f 1,2)" + echo "${commit}" +} + +function get_remote_crowsnest_commit() { + [[ ! -d ${CROWSNEST_DIR} || ! -d "${CROWSNEST_DIR}/.git" ]] && return + + local commit + cd "${CROWSNEST_DIR}" && git fetch origin -q + commit=$(git describe origin/master --always --tags | cut -d "-" -f 1,2) + echo "${commit}" +} + +function compare_crowsnest_versions() { + local versions local_ver remote_ver + local_ver="$(get_local_crowsnest_commit)" + remote_ver="$(get_remote_crowsnest_commit)" + + if [[ ${local_ver} != "${remote_ver}" ]]; then + versions="${yellow}$(printf " %-14s" "${local_ver}")${white}" + versions+="|${green}$(printf " %-13s" "${remote_ver}")${white}" + # add moonraker to application_updates_available in kiauh.ini + add_to_application_updates "crowsnest" + else + versions="${green}$(printf " %-14s" "${local_ver}")${white}" + versions+="|${green}$(printf " %-13s" "${remote_ver}")${white}" + fi + + echo "${versions}" +} + +function install_crowsnest_dependencies() { + local packages + local install_script="${CROWSNEST_DIR}/tools/install.sh" + + ### read PKGLIST from official install-script + status_msg "Reading dependencies..." + # shellcheck disable=SC2016 + packages="$(grep "PKGLIST=" "${install_script}" | cut -d'"' -f2 | sed 's/\${PKGLIST}//g' | tr -d '\n')" + + echo "${cyan}${packages}${white}" | tr '[:space:]' '\n' + read -r -a packages <<< "${packages}" + + ### Update system package info + status_msg "Updating package lists..." + if ! sudo apt-get update --allow-releaseinfo-change; then + log_error "failure while updating package lists" + error_msg "Updating package lists failed!" + exit 1 + fi + + ### Install required packages + status_msg "Installing required packages..." + if ! sudo apt-get install --yes "${packages[@]}"; then + log_error "failure while installing required crowsnest packages" + error_msg "Installing required packages failed!" + exit 1 + fi +} + +function update_crowsnest() { + do_action_service "stop" "crowsnest" + + if [[ ! -d ${CROWSNEST_DIR} ]]; then + clone_crowsnest + else + status_msg "Updating Crowsnest ..." + cd "${CROWSNEST_DIR}" && git pull + ### read PKGLIST and install possible new dependencies + install_crowsnest_dependencies + fi + ok_msg "Update complete!" + do_action_service "restart" "crowsnest" +} diff --git a/scripts/globals.sh b/scripts/globals.sh index 5ff9e0c..81629d6 100644 --- a/scripts/globals.sh +++ b/scripts/globals.sh @@ -68,4 +68,9 @@ function set_globals() { #=============== MOONRAKER-OBICO ================# MOONRAKER_OBICO_DIR="${HOME}/moonraker-obico" MOONRAKER_OBICO_REPO="https://github.com/TheSpaghettiDetective/moonraker-obico.git" + + #=============== Crowsnest ================# + CROWSNEST_DIR="${HOME}/crowsnest" + CROWSNEST_REPO="https://github.com/mainsail-crew/crowsnest.git" + } diff --git a/scripts/ui/install_menu.sh b/scripts/ui/install_menu.sh index 3b31689..c17942f 100755 --- a/scripts/ui/install_menu.sh +++ b/scripts/ui/install_menu.sh @@ -27,10 +27,8 @@ function install_ui() { echo -e "| 3) [Mainsail] | 8) [Telegram Bot] |" echo -e "| 4) [Fluidd] | 9) $(obico_install_title) |" echo -e "| | |" - echo -e "| Touchscreen GUI: | |" - echo -e "| 5) [KlipperScreen] | |" -# echo -e "| Touchscreen GUI: | Webcam Streamer: |" -# echo -e "| 5) [KlipperScreen] | 10) [MJPG-Streamer] |" + echo -e "| Touchscreen GUI: | Webcam Streamer: |" + echo -e "| 5) [KlipperScreen] | 10) [Crowsnest] |" back_footer } @@ -66,11 +64,8 @@ function install_menu() { do_action "telegram_bot_setup_dialog" "install_ui";; 9) do_action "moonraker_obico_setup_dialog" "install_ui";; -# 10) -# do_action "install_mjpg-streamer" "install_ui";; -# clear && print_header -# print_error "Function currently disabled! Sorry!" -# install_ui;; + 10) + do_action "install_crowsnest" "install_ui";; B|b) clear; main_menu; break;; *) diff --git a/scripts/ui/main_menu.sh b/scripts/ui/main_menu.sh index 263ba24..42e9a06 100755 --- a/scripts/ui/main_menu.sh +++ b/scripts/ui/main_menu.sh @@ -29,6 +29,7 @@ function main_ui() { echo -e "| | Fluidd: $(print_status "fluidd")|" echo -e "| | KlipperScreen: $(print_status "klipperscreen")|" echo -e "| 6) [Settings] | Telegram Bot: $(print_status "telegram_bot")|" + echo -e "| | Crowsnest: $(print_status "crowsnest")|" echo -e "| | Obico: $(print_status "moonraker_obico")|" echo -e "| | |" echo -e "| $(print_kiauh_version)| Octoprint: $(print_status "octoprint")|" @@ -107,6 +108,9 @@ function main_menu() { "start octoprint") do_action_service "start" "octoprint"; main_ui;; "stop octoprint") do_action_service "stop" "octoprint"; main_ui;; "restart octoprint") do_action_service "restart" "octoprint"; main_ui;; + "start crowsnest") do_action_service "start" "crowsnest"; main_ui;; + "stop crowsnest") do_action_service "stop" "crowsnest"; main_ui;; + "restart crowsnest") do_action_service "restart" "crowsnest"; main_ui;; update) do_action "update_kiauh" "main_ui";; 0)clear && print_header #upload_selection diff --git a/scripts/ui/remove_menu.sh b/scripts/ui/remove_menu.sh index 4cf743d..2cae157 100755 --- a/scripts/ui/remove_menu.sh +++ b/scripts/ui/remove_menu.sh @@ -21,7 +21,7 @@ function remove_ui() { echo -e "| 1) [Klipper] | 6) [OctoPrint] |" echo -e "| 2) [Moonraker] | |" echo -e "| | Webcam Streamer: |" - echo -e "| Klipper Webinterface: | 7) [MJPG-Streamer] |" + echo -e "| Klipper Webinterface: | 7) [Crowsnest] |" echo -e "| 3) [Mainsail] | |" echo -e "| 4) [Fluidd] | Other: |" echo -e "| | 8) [PrettyGCode] |" @@ -51,7 +51,7 @@ function remove_menu() { 6) do_action "remove_octoprint" "remove_ui";; 7) - do_action "remove_mjpg-streamer" "remove_ui";; + do_action "remove_crowsnest" "remove_ui";; 8) do_action "remove_prettygcode" "remove_ui";; 9) diff --git a/scripts/ui/update_menu.sh b/scripts/ui/update_menu.sh index a4fb2c3..8e7f7a9 100755 --- a/scripts/ui/update_menu.sh +++ b/scripts/ui/update_menu.sh @@ -32,8 +32,9 @@ function update_ui() { echo -e "| 6) [PrettyGCode] |$(compare_prettygcode_versions)|" echo -e "| 7) [Telegram Bot] |$(compare_telegram_bot_versions)|" echo -e "| 8) [Obico for Klipper]|$(compare_moonraker_obico_versions)|" + echo -e "| 9) [Crowsnest] |$(compare_crowsnest_versions)|" echo -e "| |------------------------------|" - echo -e "| 9) [System] | $(check_system_updates) |" + echo -e "| 10)[System] | $(check_system_updates) |" back_footer } @@ -63,6 +64,8 @@ function update_menu() { 8) do_action "update_moonraker_obico" "update_ui";; 9) + do_action "update_crowsnest" "update_ui";; + 10) do_action "update_system" "update_ui";; a) do_action "update_all" "update_ui";;