diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..97238fb2 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,66 @@ +name: Build Image + +on: + repository_dispatch: + push: + schedule: + - cron: '0 0 * * *' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Install Dependencies + run: | + sudo apt update + sudo apt install coreutils p7zip-full qemu-user-static + + - name: Checkout CustomPiOS + uses: actions/checkout@v2 + with: + repository: 'guysoft/CustomPiOS' + path: CustomPiOS + + - name: Checkout Project Repository + uses: actions/checkout@v2 + with: + path: repository + submodules: true + + - name: Download Raspbian Image + run: | + cd repository/src/image + wget -c --trust-server-names 'https://downloads.raspberrypi.org/raspios_lite_armhf_latest' + + - name: Update CustomPiOS Paths + run: | + cd repository/src + ../../CustomPiOS/src/update-custompios-paths + + - name: Force apt mirror to work around intermittent mirror hiccups + run: | + echo "OCTOPI_APTMIRROR=http://mirror.us.leaseweb.net/raspbian/raspbian" > repository/src/config.local + + - name: Build Image + run: | + sudo modprobe loop + cd repository/src + sudo bash -x ./build_dist + + - name: Copy output + id: copy + run: | + source repository/src/config + NOW=$(date +"%Y-%m-%d-%H%M") + IMAGE=$NOW-octopi-$DIST_VERSION + + cp repository/src/workspace/*.img $IMAGE.img + + echo "::set-output name=image::$IMAGE" + + # artifact upload will take care of zipping for us + - uses: actions/upload-artifact@v1 + if: github.event_name == 'schedule' + with: + name: ${{ steps.copy.outputs.image }} + path: ${{ steps.copy.outputs.image }}.img diff --git a/.gitignore b/.gitignore index caa2b02e..1638832a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ src/config.local src/custompios_path src/image/*.zip +src/image-raspios_lite_arm64/*.zip src/image-variants/*.zip **/key.json src/nightly_build_scripts/index.html @@ -10,3 +11,5 @@ src/workspace src/build.log src/vagrant/*.log src/vagrant/.vagrant +.vscode +.idea diff --git a/README.rst b/README.rst index 5e268e98..d3d46c6e 100644 --- a/README.rst +++ b/README.rst @@ -19,7 +19,11 @@ Download the latest stable build via this button: Official mirror is `here `_ -Nightly builds are available `here `_ +Second mirror is `here `_ + +Nightly builds are available `here `_ + +64bit Nightly builds are available `here `_ How to use it? -------------- @@ -41,9 +45,8 @@ OctoPrint is located at `http://octopi.local `_ and also at To install plugins from the commandline instead of OctoPrint's built-in plugin manager, :code:`pip` may be found at :code:`/home/pi/oprint/bin/pip`. Thus, an example install cmd may be: :code:`/home/pi/oprint/bin/pip install ` -If a USB webcam or the Raspberry Pi camera is detected, MJPG-streamer will be started automatically as webcam server. OctoPrint on OctoPi ships with correctly configured stream and snapshot URLs pointing at it. If necessary, you can reach it under `http://octopi.local/webcam/?action=stream `_ and SSL respectively, or directly on its configured port 8080: `http://octopi.local:8080/?action=stream `_. +If a USB webcam or the Raspberry Pi camera is detected, MJPG-streamer will be started automatically as webcam server. OctoPrint on OctoPi ships with correctly configured stream and snapshot URLs pointing at it. If necessary, you can reach it under `http://octopi.local/webcam/?action=stream `_ and SSL respectively, or directly on its configured port 8080: `http://octopi.local:8080/?action=stream `_. -CuraEngine is installed and OctoPrint ships pre-configured with the correct path to utilize it for on-board-slicing. Just import a Cura Slicing Profile in OctoPrint's settings and start slicing directly on your Pi. Features -------- @@ -51,7 +54,6 @@ Features * `OctoPrint `_ host software for 3d printers out of the box * `Raspbian `_ tweaked for maximum performance for printing out of the box * `mjpg-streamer with RaspiCam support `_ for live viewing of prints and timelapse video creation. -* `CuraEngine `_ pre-installed for slicing directly on the Raspberry Pi Developing ---------- @@ -79,7 +81,7 @@ You can build it by issuing the following commands:: git clone https://github.com/guysoft/CustomPiOS.git git clone https://github.com/guysoft/OctoPi.git cd OctoPi/src/image - wget -c --trust-server-names 'https://downloads.raspberrypi.org/raspbian_lite_latest' + wget -c --trust-server-names 'https://downloads.raspberrypi.org/raspios_lite_armhf_latest' cd .. ../../CustomPiOS/src/update-custompios-paths sudo modprobe loop @@ -90,7 +92,11 @@ Building OctoPi Variants OctoPi supports building variants, which are builds with changes from the main release build. An example and other variants are available in `CustomPiOS, folder src/variants/example `_. -To build a variant use:: +docker exec -it mydistro_builder:: + + sudo docker exec -it mydistro_builder build [Variant] + +Or to build a variant inside a container:: sudo bash -x ./build_dist [Variant] diff --git a/media/rpi-imager-OctoPi.png b/media/rpi-imager-OctoPi.png new file mode 100644 index 00000000..ac738869 Binary files /dev/null and b/media/rpi-imager-OctoPi.png differ diff --git a/src/config b/src/config index f4af2f4b..506f300e 100755 --- a/src/config +++ b/src/config @@ -1,4 +1,11 @@ export DIST_NAME=OctoPi -export DIST_VERSION=0.17.0 +export DIST_VERSION=1.0.0 export MODULES="base(raspicam, network, disable-services(octopi), password-for-sudo)" +export RPI_IMAGER_NAME="${DIST_NAME} version ${DIST_VERSION}" +export RPI_IMAGER_DESCRIPTION="A Raspberry Pi distribution for 3D printers. Ships OctoPrint out-of-the-box." +export RPI_IMAGER_ICON="https://raw.githubusercontent.com/guysoft/OctoPi/devel/media/rpi-imager-OctoPi.png" + + +export BASE_IMAGE_ENLARGEROOT=2000 +export BASE_IMAGE_RESIZEROOT=200 diff --git a/src/image-raspios_lite_arm64/README b/src/image-raspios_lite_arm64/README new file mode 100644 index 00000000..e5aa7b03 --- /dev/null +++ b/src/image-raspios_lite_arm64/README @@ -0,0 +1,5 @@ +Place zipped Raspberry Pi OS 64bit image here. + +If not otherwise specified, the build script will always use the most +recent zip file matching the file name pattern "*-raspbian.zip" or "*-rpios.zip" located +here. diff --git a/src/image-rpios_arm64/README b/src/image-rpios_arm64/README new file mode 100644 index 00000000..63a2c46b --- /dev/null +++ b/src/image-rpios_arm64/README @@ -0,0 +1,5 @@ +Place zipped Raspberry Pi OS image here for the arm64 variant. Or any other variant you want to build/ + +If not otherwise specified, the build script will always use the most +recent zip file matching the file name pattern "*-raspbian.zip" or "*-rpios.zip" or "*-rpios.xz" located +here. diff --git a/src/image/README b/src/image/README index 8c07825f..4203497c 100644 --- a/src/image/README +++ b/src/image/README @@ -1,5 +1,5 @@ -Place zipped Rasbian image here. +Place zipped Raspberry Pi OS image here. Or any other variant you want to build/ If not otherwise specified, the build script will always use the most -recent zip file matching the file name pattern "*-raspbian.zip" located +recent zip file matching the file name pattern "*-raspbian.zip" or "*-rpios.zip" or "*-rpios.xz" located here. diff --git a/src/modules/octopi/config b/src/modules/octopi/config index fcca2e09..b39f19a3 100755 --- a/src/modules/octopi/config +++ b/src/modules/octopi/config @@ -2,32 +2,29 @@ # All our config settings must start with OCTOPI_ # OctoPrint archive -[ -n "$OCTOPI_OCTOPRINT_ARCHIVE" ] || OCTOPI_OCTOPRINT_ARCHIVE=$(wget -q -O - https://api.github.com/repos/foosel/OctoPrint/releases/latest | grep "zipball_url" | cut -d : -f 2,3 | tr -d \" | tr -d ,) -[ -n "$OCTOPI_OCTOPRINT_REPO_SHIP" ] || OCTOPI_OCTOPRINT_REPO_SHIP=https://github.com/foosel/OctoPrint.git +[ -n "$OCTOPI_OCTOPRINT_PACKAGE" ] || OCTOPI_OCTOPRINT_PACKAGE="OctoPrint" [ -n "$OCTOPI_INCLUDE_OCTOPRINT" ] || OCTOPI_INCLUDE_OCTOPRINT=yes -# PyBonjour archive -[ -n "$OCTOPI_PYBONJOUR_ARCHIVE" ] || OCTOPI_PYBONJOUR_ARCHIVE=https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/pybonjour/pybonjour-1.1.1.tar.gz - # CuraEngine archive & version [ -n "$OCTOPI_CURAENGINE_VERSION" ] || OCTOPI_CURAENGINE_VERSION=15.04.6 [ -n "$OCTOPI_CURAENGINE_ARCHIVE" ] || OCTOPI_CURAENGINE_ARCHIVE=https://github.com/Ultimaker/CuraEngine/archive/$OCTOPI_CURAENGINE_VERSION.zip -[ -n "$OCTOPI_INCLUDE_CURAENGINE" ] || OCTOPI_INCLUDE_CURAENGINE=yes +[ -n "$OCTOPI_INCLUDE_CURAENGINE" ] || OCTOPI_INCLUDE_CURAENGINE=no # mjpg streamer -[ -n "$OCTOPI_MJPGSTREAMER_REPO_SHIP" ] || OCTOPI_MJPGSTREAMER_REPO_SHIP=https://github.com/jacksonliam/mjpg-streamer.git -[ -n "$OCTOPI_MJPGSTREAMER_REPO_BUILD" ] || OCTOPI_MJPGSTREAMER_REPO_BUILD= -[ -n "$OCTOPI_MJPGSTREAMER_REPO_BRANCH" ] || OCTOPI_MJPGSTREAMER_REPO_BRANCH=master -[ -n "$OCTOPI_MJPGSTREAMER_REPO_DEPTH" ] || OCTOPI_MJPGSTREAMER_REPO_DEPTH=1 +[ -n "$OCTOPI_MJPGSTREAMER_ARCHIVE" ] || OCTOPI_MJPGSTREAMER_ARCHIVE=https://github.com/jacksonliam/mjpg-streamer/archive/master.zip [ -n "$OCTOPI_INCLUDE_MJPGSTREAMER" ] || OCTOPI_INCLUDE_MJPGSTREAMER=yes +# FFMPEG HLS +[ -n "$OCTOPI_INCLUDE_FFMPEG_HLS" ] || OCTOPI_INCLUDE_FFMPEG_HLS=yes + # HAProxy [ -n "$OCTOPI_INCLUDE_HAPROXY" ] || OCTOPI_INCLUDE_HAPROXY=yes -# WiringPi -[ -n "$OCTOPI_INCLUDE_WIRINGPI" ] || OCTOPI_INCLUDE_WIRINGPI=yes - # yq [ -n "$OCTOPI_YQ_DOWNLOAD" ] || OCTOPI_YQ_DOWNLOAD=$(wget -q -O - https://api.github.com/repos/mikefarah/yq/releases/latest | grep "browser_download_url" | grep "yq_linux_arm" | cut -d : -f 2,3 | tr -d \" | tr -d ,) [ -n "$OCTOPI_COMMIT" ] || OCTOPI_COMMIT=`pushd "${DIST_PATH}" > /dev/null ; git rev-parse HEAD ; popd > /dev/null` + +# Fixed apt mirror +[ -n "$OCTOPI_APTMIRROR" ] || OCTOPI_APTMIRROR= + diff --git a/src/modules/octopi/filesystem/boot/octopi.txt b/src/modules/octopi/filesystem/boot/octopi.txt index 12557d9a..24cc430e 100644 --- a/src/modules/octopi/filesystem/boot/octopi.txt +++ b/src/modules/octopi/filesystem/boot/octopi.txt @@ -53,7 +53,10 @@ ### Additional options to supply to MJPG Streamer for the RasPi Cam # -# See https://faq.octoprint.org/mjpg-streamer-config for available options +# See https://faq.octoprint.org/mjpg-streamer-config for available options. +# +# NOTE: Newer raspi cam modules are reporting as usb devices causing these +# options to be ignored. Set `camera="raspi"` to avoid these issues. # # Defaults to 10fps # @@ -72,3 +75,21 @@ # #camera_http_webroot="./www-octopi" #camera_http_options="-n" + +# Configuration of network monitoring +# +# This enables network monitoring for wifi connections with a simple ping test. +# If connection terminates by variable reasons system tries to restart the wifi connection to reestablish a connection. +# The connection test is done every minute. +# By default it is disabled (0 = off / 1 = on) +# destination_host can be an ip address or a hostname (for hostname ensure dns resosultion is working correctly) +enable_network_monitor=0 +destination_host=192.168.1.1 + +### EXPERIMENTAL +# Support for different streamer types. +# +# Available options: +# mjpeg [default] - stable MJPG-streamer +# hls - experimental FFMPEG HLS streamer +#camera_streamer=mjpeg diff --git a/src/modules/octopi/filesystem/home/pi/scripts/safemode b/src/modules/octopi/filesystem/home/pi/scripts/safemode new file mode 100755 index 00000000..1965f0c2 --- /dev/null +++ b/src/modules/octopi/filesystem/home/pi/scripts/safemode @@ -0,0 +1,10 @@ +#!/bin/sh + +if grep -q "startOnceInSafeMode" ~/.octoprint/config.yaml; +then + # If found,replace the existing line + sed -i 's/.*startOnceInSafeMode: false.*/\ \ startOnceInSafeMode: true/' ~/.octoprint/config.yaml +else + # Append otherwise + sed -i '/server:/a \ \ startOnceInSafeMode: true' ~/.octoprint/config.yaml +fi diff --git a/src/modules/octopi/filesystem/home/root/bin/git b/src/modules/octopi/filesystem/home/root/bin/git index 39a0e07b..4e8a986a 100644 --- a/src/modules/octopi/filesystem/home/root/bin/git +++ b/src/modules/octopi/filesystem/home/root/bin/git @@ -3,6 +3,8 @@ if [ "$(id -u)" == "0" ] then echo "Please do not run git as root, your regular user account is enough :)" + echo "The rationale behind this restriction is to prevent cloning the OctoPrint" + echo "repository as root, which will most likely break some functionality." echo echo "If you need to run git with root rights for some other application than" echo "what comes preinstalled on this image you can remove this sanity check:" diff --git a/src/modules/octopi/filesystem/home/root/bin/streamer_select b/src/modules/octopi/filesystem/home/root/bin/streamer_select new file mode 100755 index 00000000..9d965140 --- /dev/null +++ b/src/modules/octopi/filesystem/home/root/bin/streamer_select @@ -0,0 +1,32 @@ +#!/bin/bash + +# Exit on any error. +set -e + +CONFIG_FILE=/boot/octopi.txt +MJPEG_TYPE=mjpeg +HLS_TYPE=hls +MJPEG_SERVICE=webcamd.service +HLS_SERVICE=ffmpeg_hls.service +DEFAULT_TYPE=${MJPEG_TYPE} +FLAG_DIRECTORY=/etc/octopi_streamer + +source ${CONFIG_FILE} + +if [ -z ${camera_streamer+x} ]; then + echo "No streamer type is set. Defaulting to '${DEFAULT_TYPE}'." + camera_streamer=${DEFAULT_TYPE} +fi + +rm -rf ${FLAG_DIRECTORY} +mkdir -p ${FLAG_DIRECTORY} + +echo "Setting streamer type '${camera_streamer}'." +if [ "${camera_streamer}" = "${MJPEG_TYPE}" ]; then + touch ${FLAG_DIRECTORY}/${MJPEG_TYPE} +elif [ "${camera_streamer}" = "${HLS_TYPE}" ]; then + touch ${FLAG_DIRECTORY}/${HLS_TYPE} +else + echo "Streamer type '${camera_streamer}' is not supported." + exit 1 +fi \ No newline at end of file diff --git a/src/modules/octopi/filesystem/home/root/bin/user-fix b/src/modules/octopi/filesystem/home/root/bin/user-fix new file mode 100755 index 00000000..09735c9e --- /dev/null +++ b/src/modules/octopi/filesystem/home/root/bin/user-fix @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +# Written by Gina Häußge originally at https://github.com/OctoPrint/OctoPi-UpToDate/blob/e70ccdaf0cd4ef4adfaa3f9b6b288fb6bfda116a/scripts/files/user-fix + +set -e + +USERID=1000 +FIRSTUSER=`getent passwd $USERID | cut -d: -f1` +FIRSTUSERHOME=`getent passwd $USERID | cut -d: -f6` + +CURRENT=`grep User= /etc/systemd/system/octoprint.service | cut -d= -f2` + +if [ "$CURRENT" = "pi" -a "$FIRSTUSER" != "pi" ]; then + # if we get here it means that the first user was renamed but we haven't yet + # updated all of OctoPi's files that depend on that name, so let's do that now + + # first we need to figure out if we can use the new user name in systemd files + # directly or if we need to use the UID - we do that by checking if the + # escaped name differes from the plain name, if so something is non ASCII + # and the UID is the safer bet + FIRSTUSERESC=`systemd-escape "$FIRSTUSER"` + if [ "$FIRSTUSER" != "$FIRSTUSERESC" ]; then + SERVICEUSER=$USERID + else + SERVICEUSER=$FIRSTUSER + fi + + # fix OctoPrint service file + echo "Fixing service file" + sed -i "s!User=pi!User=$SERVICEUSER!g" /etc/systemd/system/octoprint.service + sed -i "s!ExecStart=/home/pi/!ExecStart=$FIRSTUSERHOME/!g" /etc/systemd/system/octoprint.service + systemctl daemon-reload + + # fix sudoers files + echo "Fixing sudoers" + sed -i "s!^pi!$FIRSTUSER!g" /etc/sudoers.d/octoprint-service + sed -i "s!^pi!$FIRSTUSER!g" /etc/sudoers.d/octoprint-shutdown + + # fix scripts + echo "Fixing scripts" + sed -i "s!/home/pi/!$FIRSTUSERHOME/!g" $FIRSTUSERHOME/scripts/add-octoprint-checkout + sed -i "s!/home/pi/!$FIRSTUSERHOME/!g" $FIRSTUSERHOME/scripts/welcome + sed -i "s!/home/pi/!$FIRSTUSERHOME/!g" $FIRSTUSERHOME/.bashrc + sed -i "s!/home/pi/!$FIRSTUSERHOME/!g" /root/bin/webcamd + + # fix virtualenv + echo "Fixing paths in virtual environment" + cd $FIRSTUSERHOME/oprint + sudo -u $FIRSTUSER $FIRSTUSERHOME/.local/bin/virtualenv-tools --update-path $FIRSTUSERHOME/oprint + + # finally, reboot for all of this to actually take affect + echo "Adjusted scripts to new user, restarting services..." + systemctl reboot +fi \ No newline at end of file diff --git a/src/modules/octopi/filesystem/home/root/bin/webcamd b/src/modules/octopi/filesystem/home/root/bin/webcamd index 668fa51c..89d5d96a 100755 --- a/src/modules/octopi/filesystem/home/root/bin/webcamd +++ b/src/modules/octopi/filesystem/home/root/bin/webcamd @@ -11,11 +11,11 @@ ### computer. ### ######################################################################## -MJPGSTREAMER_HOME=/home/pi/mjpg-streamer +MJPGSTREAMER_HOME=/opt/mjpg-streamer MJPGSTREAMER_INPUT_USB="input_uvc.so" MJPGSTREAMER_INPUT_RASPICAM="input_raspicam.so" -brokenfps_usb_devices=("046d:082b" "1908:2310" "0458:708c" "1e4e:0102" "0471:0311" "038f:6001") +brokenfps_usb_devices=("046d:082b" "1908:2310" "0458:708c" "0458:6006" "1e4e:0102" "0471:0311" "038f:6001" "046d:0804" "046d:0825" "046d:0994" "0ac8:3450") config_dir="/boot/octopi.conf.d" @@ -46,7 +46,7 @@ for cfg_file in ${cfg_files[@]}; do camera_usb_options="-r 640x480 -f 10" camera_raspi_options="-fps 10" camera_http_webroot="./www-octopi" - camera_http_options="-n" + camera_http_options="-n --listen 127.0.0.1" additional_brokenfps_usb_devices=() if [[ -e ${cfg_file} ]]; then @@ -73,7 +73,7 @@ for cfg_file in ${cfg_files[@]}; do echo "raspi options: $camera_raspi_options" echo "http options: -w $camera_http_webroot $camera_http_options" echo "" - echo "Explicitly USB device: $extracted_device" + echo "Explicitly set USB device: $extracted_device" echo "-----------------------------------------------" echo "" @@ -104,6 +104,14 @@ function cleanup() { exit 0 } +# waits for our child processes +function awaitChildren() { + local pids=$(jobs -pr) + for pid in $pids; do + wait $pid + done +} + # says goodbye when the script shuts down function goodbye() { # say goodbye @@ -115,6 +123,37 @@ function goodbye() { # runs MJPG Streamer, using the provided input plugin + configuration function runMjpgStreamer { input=$1 + + # There are problems with 0x000137ab firmware on VL805 (Raspberry Pi 4}). + # Try to autodetect offending firmware and temporarily fix the issue + # by changing power management mode + echo "Checking for VL805 (Raspberry Pi 4)..." + if [[ -f /usr/bin/vl805 ]]; then + VL805_VERSION=$(/usr/bin/vl805) + VL805_VERSION=${VL805_VERSION#*: } + echo " - version 0x${VL805_VERSION} detected" + case "$VL805_VERSION" in + 00013701) + echo " - nothing to be done. It shouldn't cause USB problems." + ;; + 000137ab) + echo -e " - \e[31mThis version is known to cause problems with USB cameras.\e[39m" + echo -e " You may want to downgrade to 0x0013701." + echo -e " - [FIXING] Trying the setpci -s 01:00.0 0xD4.B=0x41 hack to mitigate the" + echo -e " issue. It disables ASPM L1 on the VL805. Your board may (or may not) get" + echo -e " slightly hotter. For details see:" + echo -e " https://www.raspberrypi.org/forums/viewtopic.php?f=28&t=244421" + setpci -s 01:00.0 0xD4.B=0x41 + ;; + *) + echo " - unknown firmware version. Doing nothing." + ;; + esac + else + echo " - It seems that you don't have VL805 (Raspberry Pi 4)." + echo " There should be no problems with USB (a.k.a. select() timeout)" + fi + pushd $MJPGSTREAMER_HOME > /dev/null 2>&1 echo Running ./mjpg_streamer -o "output_http.so -w $camera_http_webroot $camera_http_options" -i "$input" LD_LIBRARY_PATH=. ./mjpg_streamer -o "output_http.so -w $camera_http_webroot $camera_http_options" -i "$input" & @@ -150,19 +189,22 @@ function startUsb { product=`cat $uevent_file | grep PRODUCT | cut -d"=" -f2` vid=`echo $product | cut -d"/" -f1` pid=`echo $product | cut -d"/" -f2` - vidpid=`printf "%04x:%04x" "0x$vid" "0x$pid"` - - # ... then look if it is in our list of known broken-fps-devices and if so remove - # the -f parameter from the options (if it's in there, else that's just a no-op) - for identifier in ${brokenfps_usb_devices[@]}; - do - if [ "$vidpid" = "$identifier" ]; then - echo - echo "Camera model $vidpid is known to not work with -f parameter, stripping it out" - echo - options=`echo $options | sed -e "s/\(\s\+\|^\)-f\s\+[0-9]\+//g"` - fi - done + + if [[ -n "$vid" && -n "$pid" ]]; then + vidpid=`printf "%04x:%04x" "0x$vid" "0x$pid"` + + # ... then look if it is in our list of known broken-fps-devices and if so remove + # the -f parameter from the options (if it's in there, else that's just a no-op) + for identifier in ${brokenfps_usb_devices[@]}; + do + if [ "$vidpid" = "$identifier" ]; then + echo + echo "Camera model $vidpid is known to not work with -f parameter, stripping it out" + echo + options=`echo $options | sed -e "s/\(\s\+\|^\)-f\s\+[0-9]\+//g"` + fi + done + fi fi logger -s "Starting USB webcam" @@ -185,7 +227,9 @@ while true; do video_devices=($(find /dev -regextype sed -regex '\/dev/video[0-9]\+' | sort 2> /dev/null)) # add list of raspi camera into an array - if [ "`vcgencmd get_camera`" = "supported=1 detected=1" ]; then + vcgencmd_regex="supported=1 detected=1.*" + # Example output matching: supported=1 detected=1, libcamera interfaces=0 + if [[ "`vcgencmd get_camera`" =~ $vcgencmd_regex ]]; then video_devices+=( "raspi" ) fi @@ -206,22 +250,24 @@ while true; do camera_http_webroot="${array_camera_http_webroot[${i}]}" camera_http_options="${array_camera_http_options[${i}]}" brokenfps_usb_devices="${array_camera_brokenfps_usb_devices[${i}]}" + if [[ ${camera_usb_device} ]] && { [[ "usb" == ${scan_mode} ]] || [[ "auto" == ${scan_mode} ]]; }; then # usb device is explicitly set in options usb_device_path=`readlink -f ${camera_usb_device}` if containsString "$usb_device_path" "${array_camera_device[@]}"; then if [[ "auto" != ${scan_mode} ]]; then - array_camera_device[${i}]="alredy_in_use" + array_camera_device[${i}]="already_in_use" echo "config file='$camera_config':Video device already in use." continue fi elif containsString "$usb_device_path" "${video_devices[@]}"; then array_camera_device[${i}]="$usb_device_path" # explicitly set usb device was found in video_devices array, start usb with the found device - echo "config file='$camera_config':USB device was set in options and found in devices, start MJPG-streamer with the configured USB video device: $usb_device_path" + echo "config file='$camera_config':USB device was set in options and found in devices, starting MJPG-streamer with the configured USB video device: $usb_device_path" startUsb "$usb_device_path" continue fi + elif [[ -z ${camera_usb_device} ]] && { [[ "usb-auto" == ${scan_mode} ]] || [[ "auto" == ${scan_mode} ]]; }; then for video_device in "${video_devices[@]}"; do if [[ "raspi" != "$video_device" ]]; then @@ -230,7 +276,7 @@ while true; do else array_camera_device[${i}]="$video_device" # device is not set explicitly in options, start usb with first found usb camera as the device - echo "config file='$camera_config':USB device was not set in options, start MJPG-streamer with the first found video device: ${video_device}" + echo "config file='$camera_config':USB device was not set in options, starting MJPG-streamer with the first found video device: ${video_device}" startUsb "${video_device}" break fi @@ -240,16 +286,17 @@ while true; do continue fi fi + if [[ "raspi" == ${scan_mode} ]] || [[ "auto" == ${scan_mode} ]]; then video_device="raspi" if containsString "$video_device" "${array_camera_device[@]}"; then if [[ "auto" != ${scan_mode} ]]; then - array_camera_device[${i}]="alredy_in_use" + array_camera_device[${i}]="already_in_use" echo "config file='$camera_config':RasPiCam device already in use." fi elif containsString "$video_device" "${video_devices[@]}"; then array_camera_device[${i}]="$video_device" - echo "config file='$camera_config':Start MJPG-streamer with video device: ${video_device}" + echo "config file='$camera_config':Starting MJPG-streamer with video device: ${video_device}" startRaspi sleep 30 & sleep_pid=$! @@ -259,14 +306,19 @@ while true; do fi done done + array_assigned_device=( ${array_camera_device[*]} ) if [[ ${#array_camera[@]} -eq ${#array_assigned_device[@]} ]]; then - echo "Done bring up all configured video device" - exit 0 - else - echo "Scan again in two minutes" - sleep 120 & - sleep_pid=$! - wait ${sleep_pid} + echo "Done bringing up all configured video devices" + awaitChildren + + # reset array_camera_device to empty + array_camera_device=() + for cam in ${array_camera[@]}; do + array_camera_device+=("") + done fi + + echo "Scanning again in two minutes" + sleep 120 done diff --git a/src/modules/octopi/filesystem/root/etc/default/octoprint b/src/modules/octopi/filesystem/root/etc/default/octoprint deleted file mode 100644 index 5389e9c5..00000000 --- a/src/modules/octopi/filesystem/root/etc/default/octoprint +++ /dev/null @@ -1,22 +0,0 @@ -# Configuration for /etc/init.d/octoprint - -# The init.d script will only run if this variable non-empty. -OCTOPRINT_USER=pi - -# To what host to bind daemon, default is 127.0.0.1 -HOST=127.0.0.1 - -# On what port to run daemon, default is 5000 -PORT=5000 - -# Path to the OctoPrint executable, use this to override the default setting "/usr/bin/octoprint" -DAEMON=/home/pi/oprint/bin/octoprint - -# What arguments to pass to octoprint, usually no need to touch this -DAEMON_ARGS="--host=$HOST --port=$PORT" - -# Umask of files octoprint generates, Change this to 000 if running octoprint as its own, separate user -UMASK=022 - -# Should we run at startup? -START=yes diff --git a/src/modules/octopi/filesystem/root/etc/default/webcamd b/src/modules/octopi/filesystem/root/etc/default/webcamd deleted file mode 100644 index cdbae578..00000000 --- a/src/modules/octopi/filesystem/root/etc/default/webcamd +++ /dev/null @@ -1,13 +0,0 @@ -# Configuration for /etc/init.d/webcamd - -# Daemon -DAEMON=/root/bin/webcamd - -# Log file to use -LOG=/var/log/webcamd.log - -# User to run under -USER=pi - -# Should we run at startup? -ENABLED=1 diff --git a/src/modules/octopi/filesystem/root/etc/haproxy/errors/503-no-webcam-hls.http b/src/modules/octopi/filesystem/root/etc/haproxy/errors/503-no-webcam-hls.http new file mode 100644 index 00000000..e94373b1 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/haproxy/errors/503-no-webcam-hls.http @@ -0,0 +1,68 @@ +HTTP/1.0 503 Service Unavailable +Cache-Control: no-cache +Connection: close +Content-Type: text/html + + + + HLS Webcam server is currently not running + + + +
+

The HLS webcam server is currently not running

+
+ + + diff --git a/src/modules/octopi/filesystem/root/etc/haproxy/haproxy.cfg b/src/modules/octopi/filesystem/root/etc/haproxy/haproxy.1.x.cfg similarity index 77% rename from src/modules/octopi/filesystem/root/etc/haproxy/haproxy.cfg rename to src/modules/octopi/filesystem/root/etc/haproxy/haproxy.1.x.cfg index e20b80c8..443dd002 100644 --- a/src/modules/octopi/filesystem/root/etc/haproxy/haproxy.cfg +++ b/src/modules/octopi/filesystem/root/etc/haproxy/haproxy.1.x.cfg @@ -2,11 +2,13 @@ global maxconn 4096 user haproxy group haproxy - log 127.0.0.1 local1 debug + log /dev/log local1 debug + tune.ssl.default-dh-param 2048 defaults log global mode http + compression algo gzip option httplog option dontlognull retries 3 @@ -23,6 +25,8 @@ frontend public bind :::443 v4v6 ssl crt /etc/ssl/snakeoil.pem option forwardfor except 127.0.0.1 use_backend webcam if { path_beg /webcam/ } + use_backend webcam_hls if { path_beg /hls/ } + use_backend webcam_hls if { path_beg /jpeg/ } default_backend octoprint backend octoprint @@ -40,3 +44,6 @@ backend webcam server webcam1 127.0.0.1:8080 errorfile 503 /etc/haproxy/errors/503-no-webcam.http +backend webcam_hls + server webcam_hls_1 127.0.0.1:28126 + errorfile 503 /etc/haproxy/errors/503-no-webcam-hls.http diff --git a/src/modules/octopi/filesystem/root/etc/haproxy/haproxy.2.x.cfg b/src/modules/octopi/filesystem/root/etc/haproxy/haproxy.2.x.cfg new file mode 100644 index 00000000..b9c30185 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/haproxy/haproxy.2.x.cfg @@ -0,0 +1,49 @@ +global + maxconn 4096 + user haproxy + group haproxy + log /dev/log local1 debug + tune.ssl.default-dh-param 2048 + +defaults + log global + mode http + compression algo gzip + option httplog + option dontlognull + retries 3 + option redispatch + option http-server-close + option forwardfor + maxconn 2000 + timeout connect 5s + timeout client 15m + timeout server 15m + +frontend public + bind :::80 v4v6 + bind :::443 v4v6 ssl crt /etc/ssl/snakeoil.pem + option forwardfor except 127.0.0.1 + use_backend webcam if { path_beg /webcam/ } + use_backend webcam_hls if { path_beg /hls/ } + use_backend webcam_hls if { path_beg /jpeg/ } + default_backend octoprint + +backend octoprint + acl needs_scheme req.hdr_cnt(X-Scheme) eq 0 + + http-request replace-path ^([^\ :]*)\ /(.*) \1\ /\2 + http-request add-header X-Scheme https if needs_scheme { ssl_fc } + http-request add-header X-Scheme http if needs_scheme !{ ssl_fc } + option forwardfor + server octoprint1 127.0.0.1:5000 + errorfile 503 /etc/haproxy/errors/503-no-octoprint.http + +backend webcam + http-request replace-path /webcam/(.*) /\1 + server webcam1 127.0.0.1:8080 + errorfile 503 /etc/haproxy/errors/503-no-webcam.http + +backend webcam_hls + server webcam_hls_1 127.0.0.1:28126 + errorfile 503 /etc/haproxy/errors/503-no-webcam-hls.http diff --git a/src/modules/octopi/filesystem/root/etc/init.d/octoprint b/src/modules/octopi/filesystem/root/etc/init.d/octoprint deleted file mode 100755 index 3cbecce8..00000000 --- a/src/modules/octopi/filesystem/root/etc/init.d/octoprint +++ /dev/null @@ -1,141 +0,0 @@ -#!/bin/sh - -### BEGIN INIT INFO -# Provides: octoprint -# Required-Start: $local_fs networking -# Required-Stop: -# Should-Start: -# Should-Stop: -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# Short-Description: OctoPrint daemon -# Description: Starts the OctoPrint daemon with the user specified in -# /etc/default/octoprint. -### END INIT INFO - -# Author: Sami Olmari - -PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin -DESC="OctoPrint Daemon" -NAME="OctoPrint" -DAEMON=/usr/bin/octoprint -PIDFILE=/var/run/$NAME.pid -PKGNAME=octoprint -SCRIPTNAME=/etc/init.d/$PKGNAME - -# Read configuration variable file if it is present -[ -r /etc/default/$PKGNAME ] && . /etc/default/$PKGNAME - -# Exit if the octoprint is not installed -[ -x "$DAEMON" ] || exit 0 - -# Load the VERBOSE setting and other rcS variables -[ -f /etc/default/rcS ] && . /etc/default/rcS - -# Define LSB log_* functions. -# Depend on lsb-base (>= 3.0-6) to ensure that this file is present. -. /lib/lsb/init-functions - -if [ -z "$START" -o "$START" != "yes" ] -then - log_warning_msg "Not starting $PKGNAME, edit /etc/default/$PKGNAME to start it." - exit 0 -fi - -if [ -z "$OCTOPRINT_USER" ] -then - log_warning_msg "Not starting $PKGNAME, OCTOPRINT_USER not set in /etc/default/$PKGNAME." - exit 0 -fi - -# -# Function to verify if a pid is alive -# -is_alive() -{ - pid=`cat $1` > /dev/null 2>&1 - kill -0 $pid > /dev/null 2>&1 - return $? -} - -# -# Function that starts the daemon/service -# -do_start() -{ - # Return - # 0 if daemon has been started - # 1 if daemon was already running - # 2 if daemon could not be started - - is_alive $PIDFILE - RETVAL="$?" - - if [ $RETVAL != 0 ]; then - start-stop-daemon --start --background --quiet --pidfile $PIDFILE --make-pidfile \ - --exec $DAEMON --chuid $OCTOPRINT_USER --user $OCTOPRINT_USER --umask $UMASK -- serve $DAEMON_ARGS - RETVAL="$?" - fi -} - -# -# Function that stops the daemon/service -# -do_stop() -{ - # Return - # 0 if daemon has been stopped - # 1 if daemon was already stopped - # 2 if daemon could not be stopped - # other if a failure occurred - - start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --user $OCTOPRINT_USER --pidfile $PIDFILE - RETVAL="$?" - [ "$RETVAL" = "2" ] && return 2 - - rm -f $PIDFILE - - [ "$RETVAL" = "0" ] && return 0 || return 1 -} - -case "$1" in - start) - [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" - do_start - case "$?" in - 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; - 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; - esac - ;; - stop) - [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" - do_stop - case "$?" in - 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; - 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; - esac - ;; - restart) - log_daemon_msg "Restarting $DESC" "$NAME" - do_stop - case "$?" in - 0|1) - do_start - case "$?" in - 0) log_end_msg 0 ;; - 1) log_end_msg 1 ;; # Old process is still running - *) log_end_msg 1 ;; # Failed to start - esac - ;; - *) - # Failed to stop - log_end_msg 1 - ;; - esac - ;; - *) - echo "Usage: $SCRIPTNAME {start|stop|restart}" >&2 - exit 3 - ;; -esac - diff --git a/src/modules/octopi/filesystem/root/etc/logrotate.d/webcamd b/src/modules/octopi/filesystem/root/etc/logrotate.d/webcamd index 5c148ac0..2c5b5c68 100644 --- a/src/modules/octopi/filesystem/root/etc/logrotate.d/webcamd +++ b/src/modules/octopi/filesystem/root/etc/logrotate.d/webcamd @@ -1,4 +1,4 @@ -/var/log/webcam.log +/var/log/webcamd.log { rotate 4 weekly diff --git a/src/modules/octopi/filesystem/root/etc/network/if-up.d/powersave_off b/src/modules/octopi/filesystem/root/etc/network/if-up.d/powersave_off new file mode 100755 index 00000000..9801cf33 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/network/if-up.d/powersave_off @@ -0,0 +1,23 @@ +#!/bin/sh + +set -e + +# Don't bother for loopback +if [ "$IFACE" = lo ]; then + exit 0 +fi + +# Only run from ifup. +if [ "$MODE" != start ]; then + exit 0 +fi + +# Only run once +if [ "$ADDRFAM" != meta ]; then + exit 0 +fi + +/usr/sbin/iw dev wlan0 set power_save off + +exit 0 + diff --git a/src/modules/octopi/filesystem/root/etc/nginx/sites-available/default b/src/modules/octopi/filesystem/root/etc/nginx/sites-available/default new file mode 100644 index 00000000..a4183d87 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/nginx/sites-available/default @@ -0,0 +1,11 @@ +server { + listen 127.0.0.1:28126; + + root /run/webcam; + + location / { + # First attempt to serve request as file, then + # as directory, then fall back to displaying a 404. + try_files $uri $uri/ =404; + } +} \ No newline at end of file diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/ffmpeg_hls.service b/src/modules/octopi/filesystem/root/etc/systemd/system/ffmpeg_hls.service new file mode 100644 index 00000000..3a1f463b --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/ffmpeg_hls.service @@ -0,0 +1,54 @@ +[Unit] +Description=FFMPEG HLS webcam streaming service +ConditionPathExists=/etc/octopi_streamer/hls + +[Service] +User=root +Restart=always +RestartSec=5 +WatchdogSec=21600 +Nice=10 +ExecStartPre=/bin/rm -rf /run/webcam +ExecStartPre=/bin/mkdir -p /run/webcam/hls +ExecStartPre=/bin/mkdir -p /run/webcam/hls/240p +ExecStartPre=/bin/mkdir -p /run/webcam/hls/480p +ExecStartPre=/bin/mkdir -p /run/webcam/jpeg +ExecStartPre=/bin/cp /var/lib/ffmpeg_hls/stream.m3u8 /run/webcam/hls/stream.m3u8 +ExecStartPre=/bin/chown -R webcam:webcam /run/webcam +ExecStartPre=/bin/chmod -R 0755 /run/webcam + +ExecStart=/usr/bin/sudo -u webcam \ + /opt/ffmpeg-hls/ffmpeg \ + \ + -framerate 30 -video_size 640x480 \ + -i /dev/video0 \ + -pix_fmt yuv420p \ + \ + -c:v mjpeg -q:v 0 \ + -f image2 -r 1 -update 1 -atomic_writing 1 \ + /run/webcam/jpeg/frame.jpg \ + \ + -c:v h264_v4l2m2m -level:v 4.0 \ + -b:v 1264k -flags +cgop \ + -g 30 -keyint_min 30 \ + \ + -f hls -hls_time 1 \ + -hls_flags delete_segments+program_date_time+temp_file+independent_segments \ + -hls_allow_cache 0 -hls_segment_type fmp4 \ + -hls_list_size 32 -hls_delete_threshold 64 \ + /run/webcam/hls/480p/stream.m3u8 \ + \ + -vf scale=-1:240 \ + \ + -c:v h264_v4l2m2m -level:v 4.0 \ + -b:v 240k -flags +cgop \ + -g 30 -keyint_min 30 \ + \ + -f hls -hls_time 1 \ + -hls_flags delete_segments+program_date_time+temp_file+independent_segments \ + -hls_allow_cache 0 -hls_segment_type fmp4 \ + -hls_list_size 32 -hls_delete_threshold 64 \ + /run/webcam/hls/240p/stream.m3u8 + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/networkcheck.service b/src/modules/octopi/filesystem/root/etc/systemd/system/networkcheck.service new file mode 100644 index 00000000..ec4a008e --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/networkcheck.service @@ -0,0 +1,8 @@ +[Unit] + Description=Network Monitor + ConditionPathExists=/usr/local/bin/networkcheck + +[Service] + User=root + Type=simple + ExecStart=/usr/local/bin/networkcheck & diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/networkcheck.timer b/src/modules/octopi/filesystem/root/etc/systemd/system/networkcheck.timer new file mode 100644 index 00000000..940694fe --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/networkcheck.timer @@ -0,0 +1,10 @@ +[Unit] + Description=Network Monitor Trigger (every 1 minutes) + After=network.target + +[Timer] + OnCalendar=*-*-* *:*:00 + AccuracySec=1s + +[Install] + WantedBy=timers.target diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/octoprint.service b/src/modules/octopi/filesystem/root/etc/systemd/system/octoprint.service new file mode 100644 index 00000000..191f4e05 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/octoprint.service @@ -0,0 +1,14 @@ +[Unit] +Description=The snappy web interface for your 3D printer +After=network.online.target +Wants=network.online.target + +[Service] +Environment="HOST=127.0.0.1" +Environment="PORT=5000" +Type=simple +User=pi +ExecStart=/home/pi/oprint/bin/octoprint serve --host=${HOST} --port=${PORT} + +[Install] +WantedBy=multi-user.target diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/streamer_select.service b/src/modules/octopi/filesystem/root/etc/systemd/system/streamer_select.service new file mode 100644 index 00000000..402fd512 --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/streamer_select.service @@ -0,0 +1,10 @@ +[Unit] +Description=OctoPi streamer selector +Before=webcamd.service ffmpeg_hls.service nginx.service + +[Service] +Type=oneshot +ExecStart=/root/bin/streamer_select + +[Install] +WantedBy=multi-user.target diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/user-fix.service b/src/modules/octopi/filesystem/root/etc/systemd/system/user-fix.service new file mode 100644 index 00000000..b95981ca --- /dev/null +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/user-fix.service @@ -0,0 +1,18 @@ +# Written by Gina Häußge originally at https://github.com/OctoPrint/OctoPi-UpToDate/blob/e70ccdaf0cd4ef4adfaa3f9b6b288fb6bfda116a/scripts/files/user-fix.service +[Unit] +Description=Ensure that user name changes are applied as needed + +DefaultDependencies=no + +Before=network-pre.target +Wants=network-pre.target + +After=local-fs.target +Wants=local-fs.target + +[Service] +Type=oneshot +ExecStart=/root/bin/user-fix + +[Install] +WantedBy=multi-user.target diff --git a/src/modules/octopi/filesystem/root/etc/systemd/system/webcamd.service b/src/modules/octopi/filesystem/root/etc/systemd/system/webcamd.service index 0586c8ac..451d2377 100644 --- a/src/modules/octopi/filesystem/root/etc/systemd/system/webcamd.service +++ b/src/modules/octopi/filesystem/root/etc/systemd/system/webcamd.service @@ -1,11 +1,15 @@ [Unit] Description=the OctoPi webcam daemon with the user specified config +ConditionPathExists=/etc/octopi_streamer/mjpeg [Service] WorkingDirectory=/root/bin +StandardOutput=append:/var/log/webcamd.log +StandardError=append:/var/log/webcamd.log ExecStart=/root/bin/webcamd Restart=always -Type=forking +Type=simple +RestartSec=1 [Install] WantedBy=multi-user.target diff --git a/src/modules/octopi/filesystem/root/usr/lib/systemd/system/nginx.service b/src/modules/octopi/filesystem/root/usr/lib/systemd/system/nginx.service new file mode 100644 index 00000000..8ef64228 --- /dev/null +++ b/src/modules/octopi/filesystem/root/usr/lib/systemd/system/nginx.service @@ -0,0 +1,20 @@ +# NGINX service definition based on Debian buster version. +[Unit] +Description=NGINX server for serving HLS and JPEG frames +Documentation=man:nginx(8) +After=network.target nss-lookup.target +ConditionPathExists=/etc/octopi_streamer/hls + +[Service] +Type=forking +PIDFile=/run/nginx.pid +ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;' +ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;' +ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload +ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid +TimeoutStopSec=5 +KillMode=mixed +Nice=10 + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/src/modules/octopi/filesystem/root/usr/local/bin/networkcheck b/src/modules/octopi/filesystem/root/usr/local/bin/networkcheck new file mode 100755 index 00000000..0ab1f406 --- /dev/null +++ b/src/modules/octopi/filesystem/root/usr/local/bin/networkcheck @@ -0,0 +1,28 @@ +#!/bin/bash + +source /boot/octopi.txt + +if [ $enable_network_monitor == 1 ] && [ "$destination_host" != "" ]; then + + if [ -f /boot/octopi-wpa-supplicant.txt ]; then # check if config file exists + input="/boot/octopi-wpa-supplicant.txt" + while IFS= read -r line; do # read config file line by line + if [[ $line =~ ^network=.* ]]; then # check if we have a network config if a line starts with "network=" + echo "network config found..." + ping -c4 $destination_host > /dev/null # check if destination is reachable - possible by default the router + if [ $? != 0 ]; then + echo "Destination not reachable - reconfigure interface..." + sudo wpa_cli -i wlan0 reconfigure # reconfigure network to trigger reconnect + sudo dhclient -v # ensure connection will be established by refresh dhcp lease + echo "Reconnect done." + exit 0 # if we detect multiple network configs exit after 1st one - one reconnect is enough :-) + else + echo "Destination reachable - no action needed." + exit 0 # destination reached - exit loop + fi + fi + done < "$input" + fi +else + echo "Network monitoring not enabled." +fi diff --git a/src/modules/octopi/filesystem/root/var/lib/ffmpeg_hls/stream.m3u8 b/src/modules/octopi/filesystem/root/var/lib/ffmpeg_hls/stream.m3u8 new file mode 100644 index 00000000..a28b385e --- /dev/null +++ b/src/modules/octopi/filesystem/root/var/lib/ffmpeg_hls/stream.m3u8 @@ -0,0 +1,6 @@ +#EXTM3U +#EXT-X-VERSION:3 +#EXT-X-STREAM-INF:BANDWIDTH=245760,RESOLUTION=320x240 +240p/stream.m3u8 +#EXT-X-STREAM-INF:BANDWIDTH=1294336,RESOLUTION=640x480 +480p/stream.m3u8 \ No newline at end of file diff --git a/src/modules/octopi/start_chroot_script b/src/modules/octopi/start_chroot_script index d2e88477..d78f49e6 100755 --- a/src/modules/octopi/start_chroot_script +++ b/src/modules/octopi/start_chroot_script @@ -11,11 +11,23 @@ export LC_ALL=C source /common.sh +if [ -n "$OCTOPI_APTMIRROR" ]; +then + echo "Switching apt mirror in /etc/apt/sources.list to $OCTOPI_APTMIRROR" + cp /etc/apt/sources.list /etc/apt/sources.list.backup + sed -i "s@http://raspbian.raspberrypi.org/raspbian/@$OCTOPI_APTMIRROR@g" /etc/apt/sources.list +fi + +WEBCAM_USER=webcam +FFMPEG_HLS_COMMIT=c6fdbe26ef30fff817581e5ed6e078d96111248a +FFMPEG_HLS_DIR=/opt/ffmpeg-hls + ### Script #### -unpack /filesystem/home/pi /home/pi pi +unpack /filesystem/home/pi /home/"${BASE_USER}" "${BASE_USER}" unpack /filesystem/home/root /root root unpack /filesystem/boot /boot + apt-get update # in case we are building from a regular raspbian image instead of the lite one... @@ -24,50 +36,69 @@ echo "removing:" $remove_extra apt-get remove -y --purge $remove_extra apt-get autoremove -y -apt-get -y --force-yes install python2.7 python-virtualenv python-dev git screen subversion cmake checkinstall avahi-daemon libavahi-compat-libdnssd1 libffi-dev libssl-dev +apt-get -y --force-yes install python3 python3-virtualenv python3-dev git screen subversion cmake cmake-data avahi-daemon libavahi-compat-libdnssd1 libffi-dev libssl-dev libatlas3-base unzip echo " - Reinstall iputils-ping" apt-get install --reinstall iputils-ping +pushd /home/"${BASE_USER}" -pushd /home/pi - - #build virtualenv - sudo -u pi virtualenv oprint - - sudo -u pi /home/pi/oprint/bin/pip install --upgrade pip + # build virtualenv + sudo -u "${BASE_USER}" python3 -m virtualenv --python=python3 oprint + sudo -u "${BASE_USER}" /home/"${BASE_USER}"/oprint/bin/pip install --upgrade pip - # OctoPrint & pyserial + # OctoPrint if [ "$OCTOPI_INCLUDE_OCTOPRINT" == "yes" ] then echo "--- Installing OctoPrint" - - #pybonjour (for mdns discovery) - sudo -u pi /home/pi/oprint/bin/pip install $OCTOPI_PYBONJOUR_ARCHIVE - - #OctoPrint - PIP_DEFAULT_TIMEOUT=60 sudo -u pi /home/pi/oprint/bin/pip install $OCTOPI_OCTOPRINT_ARCHIVE + PIP_DEFAULT_TIMEOUT=60 sudo -u "${BASE_USER}" /home/"${BASE_USER}"/oprint/bin/pip install $OCTOPI_OCTOPRINT_PACKAGE fi #mjpg-streamer if [ "$OCTOPI_INCLUDE_MJPGSTREAMER" == "yes" ] then - echo "--- Installing mjpg-streamer" - if [ $( is_in_apt libjpeg62-turbo-dev ) -eq 1 ]; then - apt-get -y --force-yes install libjpeg62-turbo-dev - elif [ $( is_in_apt libjpeg8-dev ) -eq 1 ]; then - apt-get -y --force-yes install libjpeg8-dev + install_dir=/opt/mjpg-streamer + echo "--- Installing mjpg-streamer to $install_dir" + if [ "${BASE_DISTRO}" == "ubuntu" ]; then + apt-get -y --allow-downgrades --allow-remove-essential --allow-change-held-packages install libjpeg8-dev + else + if [ $( is_in_apt libjpeg62-turbo-dev ) -eq 1 ]; then + apt-get -y --force-yes install libjpeg62-turbo-dev + elif [ $( is_in_apt libjpeg8-dev ) -eq 1 ]; then + apt-get -y --force-yes install libjpeg8-dev + fi fi - + apt-get -y --force-yes --no-install-recommends install imagemagick ffmpeg libv4l-dev - gitclone OCTOPI_MJPGSTREAMER_REPO mjpg-streamer - pushd mjpg-streamer - mv mjpg-streamer-experimental/* . - sudo -u pi make + + wget $OCTOPI_MJPGSTREAMER_ARCHIVE -O mjpg-streamer.zip + unzip mjpg-streamer.zip + rm mjpg-streamer.zip + + pushd mjpg-streamer-master/mjpg-streamer-experimental + # As said in Makefile, it is just a wrapper around CMake. + # To apply -j option, we have to unwrap it. + build_dir=_build + mkdir -p $build_dir + pushd $build_dir + cmake -DCMAKE_BUILD_TYPE=Release .. + popd + + make -j $(nproc) -C $build_dir + + mkdir -p $install_dir + + install -m 755 $build_dir/mjpg_streamer $install_dir + find $build_dir -name "*.so" -type f -exec install -m 644 {} $install_dir \; + + # copy bundled web folder + cp -a -r ./www $install_dir + chmod 755 $install_dir/www + chmod -R 644 $install_dir/www # create our custom web folder and add a minimal index.html to it - sudo -u pi mkdir www-octopi - pushd www-octopi + mkdir $install_dir/www-octopi + pushd $install_dir/www-octopi cat <> index.html mjpg_streamer test page @@ -82,8 +113,47 @@ pushd /home/pi EOT popd popd + rm -rf mjpg-streamer-master + + # symlink for backwards compatibility + sudo -u "${BASE_USER}" ln -s $install_dir /home/"${BASE_USER}"/mjpg-streamer + fi + + # FFMPEG HLS + if [ "$OCTOPI_INCLUDE_FFMPEG_HLS" == "yes" ] + then + apt-get install -y --force-yes --no-install-recommends nginx + + ARCH=arm + if [ "${BASE_ARCH}" == "aarch64" ]; then + ARCH=aarch64 + fi + + FFMPEG_BUILD_DIR=$(mktemp -d) + pushd ${FFMPEG_BUILD_DIR} + FFMPEG_ARCHIVE=ffmpeg.tar.gz + wget https://api.github.com/repos/FFmpeg/FFmpeg/tarball/${FFMPEG_COMMIT} -O ${FFMPEG_ARCHIVE} + tar xvzf ${FFMPEG_ARCHIVE} + cd FFmpeg* + ./configure \ + --arch="${ARCH}" \ + --disable-doc \ + --disable-htmlpages \ + --disable-manpages \ + --disable-podpages \ + --disable-txtpages \ + --disable-ffplay \ + --disable-ffprobe + make -j$(nproc) + mkdir -p ${FFMPEG_HLS_DIR} + copy_and_export ffmpeg-hls-"${ARCH}" ffmpeg "${FFMPEG_HLS_DIR}" + popd + rm -r ${FFMPEG_BUILD_DIR} + + useradd ${WEBCAM_USER} + usermod -aG video ${WEBCAM_USER} fi - + #CuraEngine if [ "$OCTOPI_INCLUDE_CURAENGINE" == "yes" ] then @@ -91,13 +161,13 @@ EOT folder=CuraEngine-$OCTOPI_CURAENGINE_VERSION zipfile=$folder.zip apt-get -y install gcc-4.9 g++-4.9 - sudo -u pi wget -O$zipfile $OCTOPI_CURAENGINE_ARCHIVE - sudo -u pi unzip $zipfile + sudo -u "${BASE_USER}" wget -O$zipfile $OCTOPI_CURAENGINE_ARCHIVE + sudo -u "${BASE_USER}" unzip $zipfile pushd $folder - sudo -u pi make CXX=g++-4.9 VERSION=$OCTOPI_CURAENGINE_VERSION + sudo -u "${BASE_USER}" make -j$(nproc) CXX=g++-4.9 VERSION=$OCTOPI_CURAENGINE_VERSION cp build/CuraEngine /usr/local/bin/cura_engine popd - sudo -u pi rm -r $folder $zipfile + sudo -u "${BASE_USER}" rm -r $folder $zipfile fi #setup haproxy for http and https, and webcam @@ -108,20 +178,20 @@ EOT rm /etc/ssl/private/ssl-cert-snakeoil.key /etc/ssl/certs/ssl-cert-snakeoil.pem fi - if [ "$OCTOPI_INCLUDE_WIRINGPI" == "yes" ] - then - echo "--- Installing WiringPi" - apt-get install wiringpi - fi - # fetch current yq build and install to /usr/local/bin wget -O yq $OCTOPI_YQ_DOWNLOAD && chmod +x yq && mv yq /usr/local/bin - + popd -#Make sure user pi has access to serial ports -usermod -a -G tty pi -usermod -a -G dialout pi +#Make sure user pi / ${BASE_USER} has access to serial ports +usermod -a -G tty "${BASE_USER}" +usermod -a -G dialout "${BASE_USER}" + +# If building against Ubuntu, make sure vcgencmd is available and pi has the rights to use it +if [ "${BASE_DISTRO}" == "ubuntu" ]; then + apt-get -y --force-yes install libraspberrypi-bin + usermod -a -G video "${BASE_USER}" +fi # store octopi commit used to build this image echo "$OCTOPI_COMMIT" > /etc/octopi_commit @@ -129,9 +199,9 @@ echo "$OCTOPI_COMMIT" > /etc/octopi_commit # Keep legacy compatibility ln -s /etc/custompios_buildbase /etc/octopi_buildbase -# allow pi user to run shutdown and service commands -echo "pi ALL=NOPASSWD: /sbin/shutdown" > /etc/sudoers.d/octoprint-shutdown -echo "pi ALL=NOPASSWD: /usr/sbin/service" > /etc/sudoers.d/octoprint-service +# allow pi / ${BASE_USER} user to run shutdown and service commands +echo "${BASE_USER} ALL=NOPASSWD: /sbin/shutdown" > /etc/sudoers.d/octoprint-shutdown +echo "${BASE_USER} ALL=NOPASSWD: /usr/sbin/service" > /etc/sudoers.d/octoprint-service #make sure users don't run git with sudo, thus breaking permissions, by adding /root/bin to the #default sudo path and placing a git wrapper script there that checks if it's run as root @@ -156,21 +226,21 @@ do done for ip in $(hostname -I); -do +do echo " http://$ip" done echo echo "https is also available, with a self-signed certificate." -echo +echo echo "------------------------------------------------------------" echo EOT echo 'exit 0' >> /etc/rc.local -# add a longer welcome text to ~pi/.bashrc -echo "source /home/pi/scripts/welcome" >> /home/pi/.bashrc +# add a longer welcome text to ~pi/.bashrc / ~${BASE_USER}/.bashrc +echo "source /home/${BASE_USER}/scripts/welcome" >> /home/${BASE_USER}/.bashrc #unpack root in the end, so etc file are not overwritten, might need to add two roots int he future unpack /filesystem/root / @@ -189,11 +259,10 @@ update-rc.d change_hostname defaults if [ "$OCTOPI_INCLUDE_OCTOPRINT" == "yes" ] then - update-rc.d octoprint defaults 95 + systemctl_if_exists enable octoprint.service else # let's remove the configs for system services we don't need - rm /etc/init.d/octoprint - rm /etc/default/octoprint + rm /etc/systemd/system/octoprint.service fi ### haproxy @@ -201,13 +270,22 @@ fi if [ "$OCTOPI_INCLUDE_HAPROXY" == "yes" ] then systemctl_if_exists enable gencert.service + + haproxy_version=$(dpkg -s haproxy | grep '^Version:' | awk '{print $2}') + if [[ $haproxy_version = 2.* ]]; then + mv /etc/haproxy/haproxy.2.x.cfg /etc/haproxy/haproxy.cfg + rm /etc/haproxy/haproxy.1.x.cfg + else + mv /etc/haproxy/haproxy.1.x.cfg /etc/haproxy/haproxy.cfg + rm /etc/haproxy/haproxy.2.x.cfg + fi else # let's remove the configs for system services we don't need rm /etc/systemd/system/gencert.service # also we need to make OctoPrint bind to all interfaces because otherwise # it will be unaccessible... - [ -f /etc/default/octoprint ] && sed -i "s@HOST=127.0.0.1@HOST=0.0.0.0@" /etc/default/octoprint + [ -f /etc/systemd/system/octoprint.service ] && sed -i "s@HOST=127.0.0.1@HOST=0.0.0.0@" /etc/systemd/system/octoprint.service fi ### CuraEngine @@ -215,22 +293,57 @@ fi if [ ! "$OCTOPI_INCLUDE_CURAENGINE" == "yes" ] then # unconfigure the cura engine path in octoprint's config.yaml - sudo -u pi sed -i -e "s@cura_engine: /usr/local/bin/cura_engine@cura_engine:@g" /home/pi/.octoprint/config.yaml + sudo -u "${BASE_USER}" sed -i -e "s@cura_engine: /usr/local/bin/cura_engine@cura_engine:@g" /home/"${BASE_USER}"/.octoprint/config.yaml fi +### Streamer select service. + +systemctl_if_exists enable streamer_select.service + ### mjpg_streamer if [ "$OCTOPI_INCLUDE_MJPGSTREAMER" == "yes" ] then systemctl_if_exists enable webcamd.service +### use legacy camera stack on bullseye for now + if grep "camera_auto_detect=1" /boot/config.txt + then + sed -i "s/camera_auto_detect=1/camera_auto_detect=0/g" /boot/config.txt + fi else rm /etc/logrotate.d/webcamd - rm /etc/init.d/webcamd - rm /etc/default/webcamd + rm /etc/systemd/system/webcamd.service rm /root/bin/webcamd fi +### HLS streamer + +systemctl_if_exists enable ffmpeg_hls.service + +### Network monitoring + +systemctl_if_exists enable networkcheck.timer + +### Firmare flashing + +echo "--- Installing avrdude" +apt-get -y install avrdude + +### User-fixing +# Users can change their username easily via the Raspberry Pi imager, which breaks some of OctoPi's scripts +# we need to install virtualenv-tools3, so let's get pip and that +apt install -y python3-pip +sudo -u pi pip3 install --user virtualenv-tools3 + +systemctl_if_exists enable user-fix.service + + #cleanup apt-get clean apt-get autoremove -y +if [ -n "$OCTOPI_APTMIRROR" ]; +then + echo "Reverting /etc/apt/sources.list" + mv /etc/apt/sources.list.backup /etc/apt/sources.list +fi diff --git a/src/nightly_build_scripts/generate_nightly_page.js b/src/nightly_build_scripts/generate_nightly_page.js index 2d25ceb7..5d761ab8 100644 --- a/src/nightly_build_scripts/generate_nightly_page.js +++ b/src/nightly_build_scripts/generate_nightly_page.js @@ -162,7 +162,7 @@ var outputPage = function(files, s) { var output = new StringStream(); - output.write(""); + output.write(""); output.write("

Raspberry Pi

\n"); @@ -174,18 +174,18 @@ var outputPage = function(files, s) { output.write("

Nightly Builds

\n"); output.write("Warning: These builds are untested and can be unstable and/or broken. If in doubt use a stable build."); - outputTable(filterNameByRegex(files.filter(function (obj) { return !obj.name.startsWith("stable/") && !obj.name.startsWith("bananapi-m1/") }), /octopi-(wheezy|jessie|stretch|buster)-/), + outputTable(filterNameByRegex(files.filter(function (obj) { return !obj.name.startsWith("stable/") && !obj.name.startsWith("bananapi-m1/") }), /octopi-(wheezy|jessie|stretch|buster)-armhf/), output, function(name) { return name }, 14); - output.write("

Banana Pi M1

\n") + output.write("

64Bit Nightly Builds

\n") - output.write("

Nightly Builds

\n"); + output.write("

Nightly Builds arm64

\n"); output.write("Warning: These builds are untested and can be unstable and/or broken."); - outputTable(filterNameByRegex(files, /^bananapi-m1\//), + outputTable(filterNameByRegex(files.filter(function (obj) { return !obj.name.startsWith("stable/") && !obj.name.startsWith("bananapi-m1/") }), /octopi-(wheezy|jessie|stretch|buster)-arm64/), output, - function(name) { return stripLeading(name, "bananapi-m1/") }, + function(name) { return name }, 14); var content = output.buffer; @@ -212,3 +212,4 @@ client.getFiles(container, function (err, files) { var stream = fs.createWriteStream(outputfile); outputPage(filterByExtension(files, [".zip"]), stream); }); + diff --git a/src/variants/rpios_arm64/config b/src/variants/rpios_arm64/config new file mode 100755 index 00000000..36278105 --- /dev/null +++ b/src/variants/rpios_arm64/config @@ -0,0 +1,8 @@ +export BASE_ARCH=aarch64 +export BASE_DISTRO=raspios64 +export BASE_IMAGE_PATH=${DIST_PATH}/image-rpios_arm64 +# export BASE_ZIP_IMG=`ls -t $BASE_IMAGE_PATH/*-{ubuntu}-*-arm64-*.xz | head -n 1` +export BASE_IGNORE_VARIANT_NAME=yes +export BASE_USER=pi +export BASE_USER_PASSWORD=raspberry +export RPI_IMAGER_NAME="${DIST_NAME} version ${DIST_VERSION} 64-bit" diff --git a/src/variants/rpios_arm64/filesystem/root/etc/haproxy/haproxy.cfg b/src/variants/rpios_arm64/filesystem/root/etc/haproxy/haproxy.cfg new file mode 100644 index 00000000..8ef4d164 --- /dev/null +++ b/src/variants/rpios_arm64/filesystem/root/etc/haproxy/haproxy.cfg @@ -0,0 +1,49 @@ +global + maxconn 4096 + user haproxy + group haproxy + log /dev/log local1 debug + tune.ssl.default-dh-param 2048 + +defaults + log global + mode http + compression algo gzip + option httplog + option dontlognull + retries 3 + option redispatch + option http-server-close + option forwardfor + maxconn 2000 + timeout connect 5s + timeout client 15min + timeout server 15min + +frontend public + bind :::80 v4v6 + bind :::443 v4v6 ssl crt /etc/ssl/snakeoil.pem + option forwardfor except 127.0.0.1 + use_backend webcam if { path_beg /webcam/ } + use_backend webcam_hls if { path_beg /hls/ } + use_backend webcam_hls if { path_beg /jpeg/ } + default_backend octoprint + +backend octoprint + acl needs_scheme req.hdr_cnt(X-Scheme) eq 0 + + http-request replace-path ^([^\ :]*)\ /(.*) \1\ /\2 + http-request add-header X-Scheme https if needs_scheme { ssl_fc } + http-request add-header X-Scheme http if needs_scheme !{ ssl_fc } + option forwardfor + server octoprint1 127.0.0.1:5000 + errorfile 503 /etc/haproxy/errors/503-no-octoprint.http + +backend webcam + http-request replace-path /webcam/(.*) /\1 + server webcam1 127.0.0.1:8080 + errorfile 503 /etc/haproxy/errors/503-no-webcam.http + +backend webcam_hls + server webcam_hls_1 127.0.0.1:28126 + errorfile 503 /etc/haproxy/errors/503-no-webcam-hls.http diff --git a/src/variants/rpios_arm64/filesystem/root/etc/systemd/system/webcamd.service b/src/variants/rpios_arm64/filesystem/root/etc/systemd/system/webcamd.service new file mode 100644 index 00000000..5154d6e8 --- /dev/null +++ b/src/variants/rpios_arm64/filesystem/root/etc/systemd/system/webcamd.service @@ -0,0 +1,15 @@ +[Unit] +Description=the OctoPi webcam daemon with the user specified config +# ConditionPathExists=/etc/octopi_streamer/mjpeg + +[Service] +WorkingDirectory=/root/bin +StandardOutput=append:/var/log/webcamd.log +StandardError=append:/var/log/webcamd.log +ExecStart=/root/bin/webcamd +Restart=always +Type=simple +RestartSec=1 + +[Install] +WantedBy=multi-user.target diff --git a/src/variants/rpios_arm64/post_chroot_script b/src/variants/rpios_arm64/post_chroot_script new file mode 100644 index 00000000..918c8bc9 --- /dev/null +++ b/src/variants/rpios_arm64/post_chroot_script @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -x +set -e + +export LC_ALL=C + +source /common.sh +install_cleanup_trap + +# Unpack the filesystem changes for the variant +unpack /filesystem/root / + +# add-apt-repository ppa:ubuntu-raspi2/ppa -y +apt-get update +apt-get -y --force-yes install libraspberrypi-bin rpi.gpio-common +apt-get clean +apt-get autoremove -y diff --git a/src/variants/ubuntu_arm64/config b/src/variants/ubuntu_arm64/config new file mode 100755 index 00000000..1f54aa96 --- /dev/null +++ b/src/variants/ubuntu_arm64/config @@ -0,0 +1,10 @@ +export BASE_ARCH=aarch64 +export BASE_DISTRO=ubuntu + +export BASE_IMAGE_PATH=${DIST_PATH}/image-ubuntu_arm64 +export BASE_ZIP_IMG=`ls -t $BASE_IMAGE_PATH/*-{ubuntu}-*-arm64-*.xz | head -n 1` +export BASE_IGNORE_VARIANT_NAME=yes +export BASE_USER=pi +export BASE_USER_PASSWORD=raspberry +export RPI_IMAGER_NAME="${DIST_NAME} version ${DIST_VERSION} 64bit" + diff --git a/src/variants/ubuntu_arm64/filesystem/root/etc/haproxy/haproxy.cfg b/src/variants/ubuntu_arm64/filesystem/root/etc/haproxy/haproxy.cfg new file mode 100644 index 00000000..8ef4d164 --- /dev/null +++ b/src/variants/ubuntu_arm64/filesystem/root/etc/haproxy/haproxy.cfg @@ -0,0 +1,49 @@ +global + maxconn 4096 + user haproxy + group haproxy + log /dev/log local1 debug + tune.ssl.default-dh-param 2048 + +defaults + log global + mode http + compression algo gzip + option httplog + option dontlognull + retries 3 + option redispatch + option http-server-close + option forwardfor + maxconn 2000 + timeout connect 5s + timeout client 15min + timeout server 15min + +frontend public + bind :::80 v4v6 + bind :::443 v4v6 ssl crt /etc/ssl/snakeoil.pem + option forwardfor except 127.0.0.1 + use_backend webcam if { path_beg /webcam/ } + use_backend webcam_hls if { path_beg /hls/ } + use_backend webcam_hls if { path_beg /jpeg/ } + default_backend octoprint + +backend octoprint + acl needs_scheme req.hdr_cnt(X-Scheme) eq 0 + + http-request replace-path ^([^\ :]*)\ /(.*) \1\ /\2 + http-request add-header X-Scheme https if needs_scheme { ssl_fc } + http-request add-header X-Scheme http if needs_scheme !{ ssl_fc } + option forwardfor + server octoprint1 127.0.0.1:5000 + errorfile 503 /etc/haproxy/errors/503-no-octoprint.http + +backend webcam + http-request replace-path /webcam/(.*) /\1 + server webcam1 127.0.0.1:8080 + errorfile 503 /etc/haproxy/errors/503-no-webcam.http + +backend webcam_hls + server webcam_hls_1 127.0.0.1:28126 + errorfile 503 /etc/haproxy/errors/503-no-webcam-hls.http diff --git a/src/variants/ubuntu_arm64/filesystem/root/etc/systemd/system/webcamd.service b/src/variants/ubuntu_arm64/filesystem/root/etc/systemd/system/webcamd.service new file mode 100644 index 00000000..5154d6e8 --- /dev/null +++ b/src/variants/ubuntu_arm64/filesystem/root/etc/systemd/system/webcamd.service @@ -0,0 +1,15 @@ +[Unit] +Description=the OctoPi webcam daemon with the user specified config +# ConditionPathExists=/etc/octopi_streamer/mjpeg + +[Service] +WorkingDirectory=/root/bin +StandardOutput=append:/var/log/webcamd.log +StandardError=append:/var/log/webcamd.log +ExecStart=/root/bin/webcamd +Restart=always +Type=simple +RestartSec=1 + +[Install] +WantedBy=multi-user.target diff --git a/src/variants/ubuntu_arm64/post_chroot_script b/src/variants/ubuntu_arm64/post_chroot_script new file mode 100644 index 00000000..918c8bc9 --- /dev/null +++ b/src/variants/ubuntu_arm64/post_chroot_script @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -x +set -e + +export LC_ALL=C + +source /common.sh +install_cleanup_trap + +# Unpack the filesystem changes for the variant +unpack /filesystem/root / + +# add-apt-repository ppa:ubuntu-raspi2/ppa -y +apt-get update +apt-get -y --force-yes install libraspberrypi-bin rpi.gpio-common +apt-get clean +apt-get autoremove -y