`_
+
Building Using Vagrant
~~~~~~~~~~~~~~~~~~~~~~
There is a vagrant machine configuration to let build OctoPi in case your build environment behaves differently. Unless you do extra configuration, vagrant must run as root to have nfs folder sync working.
@@ -120,7 +148,7 @@ To build a variant on the machine simply run::
Usage
~~~~~
-#. If needed, override existing config settings by creating a new file ``src/config.local``. You can override all settings found in ``src/modules/octopi/config``. If you need to override the path to the Raspbian image to use for building OctoPi, override the path to be used in ``ZIP_IMG``. By default the most recent file matching ``*-raspbian.zip`` found in ``src/image`` will be used.
+#. If needed, override existing config settings by creating a new file ``src/config.local``. You can override all settings found in ``src/modules/octopi/config``. If you need to override the path to the Raspberry Pi OS image to use for building OctoPi, override the path to be used in ``ZIP_IMG``. By default the most recent file matching ``*-raspios*.xz`` found in ``src/image`` will be used.
#. Run ``src/build_dist`` as root.
#. The final image will be created at the ``src/workspace``
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 05352183..f6c967a3 100755
--- a/src/config
+++ b/src/config
@@ -1,4 +1,11 @@
export DIST_NAME=OctoPi
-export DIST_VERSION=0.15.0
+export DIST_VERSION=1.1.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-armbian/README b/src/image-armbian/README
new file mode 100644
index 00000000..a75e65a5
--- /dev/null
+++ b/src/image-armbian/README
@@ -0,0 +1,8 @@
+Place zipped armbian images here.
+
+
+This folder is used in the armbian build variant.
+
+Not that if not otherwise specified in the variant, 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-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-network.txt b/src/modules/octopi/filesystem/boot/octopi-network.txt
index 85c4c0b1..7df0ba02 100644
--- a/src/modules/octopi/filesystem/boot/octopi-network.txt
+++ b/src/modules/octopi/filesystem/boot/octopi-network.txt
@@ -1,3 +1,3 @@
# Using this file to configure your network connection is no longer supported.
#
-# Please use octopi-wpa-supplicant.txt instead.
+# Please use wifi.nmconnection instead.
diff --git a/src/modules/octopi/filesystem/boot/octopi.txt b/src/modules/octopi/filesystem/boot/octopi.txt
index b09fa8be..bf348dcc 100644
--- a/src/modules/octopi/filesystem/boot/octopi.txt
+++ b/src/modules/octopi/filesystem/boot/octopi.txt
@@ -4,21 +4,12 @@
### MacOSX users: If you use Textedit to edit this file make sure to use
### "plain text format" and "disable smart quotes" in "Textedit > Preferences"
-### Configure which camera to use
-#
-# Available options are:
-# - auto: tries first usb webcam, if that's not available tries raspi cam
-# - usb: only tries usb webcam
-# - raspi: only tries raspi cam
-#
-# Defaults to auto
-#
-#camera="auto"
+### Heads-up: The "input_raspi" input module of mjpg-streamer is no longer supported.
+### Raspicam support is now available on the "input_uvc" module.
### Additional options to supply to MJPG Streamer for the USB camera
#
-# See https://github.com/foosel/OctoPrint/wiki/MJPG-Streamer-configuration
-# for available options
+# See https://faq.octoprint.org/mjpg-streamer-config for available options
#
# Defaults to a resolution of 640x480 px and a framerate of 10 fps
#
@@ -52,15 +43,6 @@
#
#additional_brokenfps_usb_devices=()
-### Additional options to supply to MJPG Streamer for the RasPi Cam
-#
-# See https://github.com/foosel/OctoPrint/wiki/MJPG-Streamer-configuration
-# for available options
-#
-# Defaults to 10fps
-#
-#camera_raspi_options="-fps 10"
-
### Configuration of camera HTTP output
#
# Usually you should NOT need to change this at all! Only touch if you
@@ -74,3 +56,11 @@
#
#camera_http_webroot="./www-octopi"
#camera_http_options="-n"
+
+### 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/.octoprint/config.yaml b/src/modules/octopi/filesystem/home/pi/.octoprint/config.yaml
index 88361e3e..b6002e8a 100644
--- a/src/modules/octopi/filesystem/home/pi/.octoprint/config.yaml
+++ b/src/modules/octopi/filesystem/home/pi/.octoprint/config.yaml
@@ -1,7 +1,7 @@
webcam:
stream: /webcam/?action=stream
snapshot: http://127.0.0.1:8080/?action=snapshot
- ffmpeg: /usr/bin/avconv
+ ffmpeg: /usr/bin/ffmpeg
plugins:
cura:
cura_engine: /usr/local/bin/cura_engine
diff --git a/src/modules/octopi/filesystem/home/pi/OctoPrint/README.txt b/src/modules/octopi/filesystem/home/pi/OctoPrint/README.txt
index 4214bd8f..48cf310b 100644
--- a/src/modules/octopi/filesystem/home/pi/OctoPrint/README.txt
+++ b/src/modules/octopi/filesystem/home/pi/OctoPrint/README.txt
@@ -4,4 +4,4 @@ so OctoPi no longer goes that route either.
Feel free to manually create a git clone though if you need it (e.g. for
branch based updates or on board development):
- ~/scripts/add-octoprint-checkout
+ /opt/octopi/scripts/add-octoprint-checkout
diff --git a/src/modules/octopi/filesystem/home/root/bin/git b/src/modules/octopi/filesystem/home/root/bin/git
index d10f25c0..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:"
@@ -13,4 +15,4 @@ then
exit 1
fi
-/usr/bin/git "$@"
+exec /usr/bin/git "$@"
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..3b6662af
--- /dev/null
+++ b/src/modules/octopi/filesystem/home/root/bin/streamer_select
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# Exit on any error.
+set -e
+
+CONFIG_FILE=/boot/firmware/octopi.txt
+# Fallback for older images
+if [ ! -f "${CONFIG_FILE}" ] && [ -f "/boot/octopi.txt" ]; then
+CONFIG_FILE=/boot/octopi.txt
+fi
+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
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..356dfc9d
--- /dev/null
+++ b/src/modules/octopi/filesystem/home/root/bin/user-fix
@@ -0,0 +1,40 @@
+#!/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 "ALL\=NOPASSWD" /etc/sudoers.d/octoprint-service | cut -d\ -f1)
+
+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 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" /opt/octopi/scripts/add-octoprint-checkout
+ sed -i "s!/home/pi/!$FIRSTUSERHOME/!g" /root/bin/webcamd
+
+ # finally, reboot for all of this to actually take affect
+ echo "Adjusted scripts to new user, restarting services..."
+ systemctl reboot
+fi
diff --git a/src/modules/octopi/filesystem/home/root/bin/webcamd b/src/modules/octopi/filesystem/home/root/bin/webcamd
index 0a32abaf..b05f3958 100755
--- a/src/modules/octopi/filesystem/home/root/bin/webcamd
+++ b/src/modules/octopi/filesystem/home/root/bin/webcamd
@@ -1,33 +1,98 @@
#!/bin/bash
-########################################################################
-### DO NOT EDIT THIS FILE TO CHANGE THE CONFIG!!! ###
-### ---------------------------------------------------------------- ###
-### There is no need to edit this file for changing resolution, ###
-### frame rates or any other mjpg-streamer parameters. Please edit ###
-### /boot/octopi.txt instead - that's what it's there for! You can ###
-### even do this with your Pi powered down by directly accessing the ###
-### file when using the SD card as thumb drive in your regular ###
-### computer. ###
-########################################################################
-
-MJPGSTREAMER_HOME=/home/pi/mjpg-streamer
+###############################################################################
+### DO NOT EDIT THIS FILE TO CHANGE THE CONFIG!!! ###
+### ----------------------------------------------------------------------- ###
+### There is no need to edit this file for changing resolution, ###
+### frame rates or any other mjpg-streamer parameters. Please edit ###
+### /boot/firmware/octopi.txt instead - that's what it's there for! You can ###
+### even do this with your Pi powered down by directly accessing the ###
+### file when using the SD card as thumb drive in your regular ###
+### computer. ###
+###############################################################################
+
+MJPGSTREAMER_HOME=/opt/mjpg-streamer
MJPGSTREAMER_INPUT_USB="input_uvc.so"
MJPGSTREAMER_INPUT_RASPICAM="input_raspicam.so"
-# init configuration - DO NOT EDIT, USE /boot/octopi.txt INSTEAD!
-camera="auto"
-camera_usb_options="-r 640x480 -f 10"
-camera_raspi_options="-fps 10"
-camera_http_webroot="./www-octopi"
-camera_http_options="-n"
-additional_brokenfps_usb_devices=()
+CONFIG_FILE=/boot/firmware/octopi.txt
+# Fallback for older images
+if [ ! -f "${CONFIG_FILE}" ] && [ -f "/boot/octopi.txt" ]; then
+CONFIG_FILE=/boot/octopi.txt
+fi
+
+brokenfps_usb_devices=("046d:082b" "1908:2310" "0458:708c" "0458:6006" "1e4e:0102" "0471:0311" "038f:6001" "046d:0804" "046d:0994" "0ac8:3450")
+
+config_dir="${CONFIG_FILE}/octopi.conf.d"
+
+echo "Starting up webcamDaemon..."
+echo ""
-if [ -e "/boot/octopi.txt" ]; then
- source "/boot/octopi.txt"
+cfg_files=()
+cfg_files+="${CONFIG_FILE}"
+if [[ -d ${config_dir} ]]; then
+ cfg_files+=( `ls ${config_dir}/*.txt` )
fi
-brokenfps_usb_devices=("046d:082b" "1908:2310" "0458:708c" "1e4e:0102" "${additional_brokenfps_usb_devices[@]}")
+array_camera_config=()
+array_camera=()
+array_camera_usb_options=()
+array_camera_usb_device=()
+array_camera_raspi_options=()
+array_camera_http_webroot=()
+array_camera_http_options=()
+array_additional_brokenfps_usb_devices=()
+array_camera_device=()
+array_assigned_device=()
+
+echo "--- Configuration: ----------------------------"
+for cfg_file in ${cfg_files[@]}; do
+ # init configuration - DO NOT EDIT, USE /boot/firmware/octopi.conf.d/*.txt INSTEAD!
+ camera="auto"
+ camera_usb_options="-r 640x480 -f 10"
+ camera_raspi_options="-fps 10"
+ camera_http_webroot="./www-octopi"
+ camera_http_options="-n --listen 127.0.0.1"
+ additional_brokenfps_usb_devices=()
+
+ if [[ -e ${cfg_file} ]]; then
+ source "$cfg_file"
+ fi
+ usb_options="$camera_usb_options"
+
+ # if webcam device is explicitly given in /boot/firmware/octopi.txt, save the path of the device
+ # to a variable and remove its parameter from usb_options
+ extracted_device=`echo $usb_options | sed 's@.*-d \(/dev/\(video[0-9]\+\|v4l/[^ ]*\)\).*@\1@'`
+ if [ "$extracted_device" != "$usb_options" ]
+ then
+ # the camera options refer to a device, save it in a variable
+ # replace video device parameter with empty string and strip extra whitespace
+ usb_options=`echo $usb_options | sed 's/\-d \/dev\/\(video[0-9]\+\|v4l\/[^ ]*\)//g' | awk '$1=$1'`
+ else
+ extracted_device=""
+ fi
+
+ # echo configuration
+ echo "cfg_file: $cfg_file"
+ echo "camera: $camera"
+ echo "usb options: $camera_usb_options"
+ echo "raspi options: $camera_raspi_options"
+ echo "http options: -w $camera_http_webroot $camera_http_options"
+ echo ""
+ echo "Explicitly set USB device: $extracted_device"
+ echo "-----------------------------------------------"
+ echo ""
+
+ array_camera_config+=( $cfg_file )
+ array_camera+=( $camera )
+ array_camera_usb_options+=("$usb_options")
+ array_camera_usb_device+=("$extracted_device")
+ array_camera_raspi_options+=("$camera_raspi_options")
+ array_camera_http_webroot+=("$camera_http_webroot")
+ array_camera_http_options+=("$camera_http_options")
+ array_camera_brokenfps_usb_devices+=("${brokenfps_usb_devices[*]} ${additional_brokenfps_usb_devices[*]}")
+ array_camera_device+=("")
+done
# check if array contains a string
function containsString() {
@@ -45,6 +110,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
@@ -56,10 +129,43 @@ 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" &
- wait
+ sleep 1 &
+ sleep_pid=$!
+ wait ${sleep_pid}
popd > /dev/null 2>&1
}
@@ -89,19 +195,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"
@@ -113,76 +222,109 @@ trap "cleanup" SIGINT SIGTERM
# say goodbye when we EXIT
trap "goodbye" EXIT
-# echo configuration
-echo "Starting up webcamDaemon..."
-echo ""
-echo "--- Configuration: ----------------------------"
-echo "camera: $camera"
-echo "usb options: $camera_usb_options"
-echo "raspi options: $camera_raspi_options"
-echo "http options: -w $camera_http_webroot $camera_http_options"
-echo "-----------------------------------------------"
-echo ""
-
# we need this to prevent the later calls to vcgencmd from blocking
# I have no idea why, but that's how it is...
vcgencmd version > /dev/null 2>&1
-usb_options="$camera_usb_options"
-
-# if webcam device is explicitly given in /boot/octopi.txt, save the path of the device
-# to a variable and remove its parameter from usb_options
-extracted_device=`echo $usb_options | sed 's@.*-d \(/dev/video[0-9]\+\).*@\1@'`
-if [ "$extracted_device" != "$usb_options" ]
-then
- # the camera options refer to a device, save it in a variable
- usb_device_path="$extracted_device"
- # replace video device parameter with empty string and strip extra whitespace
- usb_options=`echo $usb_options | sed 's/\-d \/dev\/video[0-9]\+//g' | awk '$1=$1'`
- echo "Explicitly set USB device was found in options: $usb_device_path"
-fi
-
# keep mjpg streamer running if some camera is attached
while true; do
- # get list of usb video devices into an array
- video_devices=($(find /dev -regextype sed -regex '\/dev/video[0-9]\+' | sort 2> /dev/null))
-
- if [ ${#video_devices[@]} != 0 ] && { [ "$camera" = "auto" ] || [ "$camera" = "usb" ] ; }; then
-
- echo "Found video devices:"
- printf '%s\n' "${video_devices[@]}"
-
- if [[ $usb_device_path ]]; then
- # usb device is explicitly set in options
- if containsString "$usb_device_path" "${video_devices[@]}"; then
- # explicitly set usb device was found in video_devices array, start usb with the found device
- echo "USB device was set in options and found in devices, start MJPG-streamer with the configured USB video device: $usb_device_path"
- startUsb "$usb_device_path"
- else
- # explicitly set usb device was not found
- echo "Configured USB camera was not detected, trying again in two minutes"
- sleep 120 &
- wait
+ # get list of usb video devices into an array
+ video_devices=($(find /dev -regextype sed -regex '\/dev/video[0-9]\+' | sort 2> /dev/null))
+
+ # add list of raspi camera into an array
+ 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
+
+ echo "Found video devices:"
+ printf '%s\n' "${video_devices[@]}"
+
+ for scan_mode in "usb" "usb-auto" "raspi" "auto"; do
+ camera=$scan_mode
+ if [[ "usb-auto" == "$scan_mode" ]]; then
+ camera="usb"
+ fi
+ for ((i=0;i<${#array_camera[@]};i++)); do
+ if [[ -z ${array_camera_device[${i}]} ]] && [[ $camera == ${array_camera[${i}]} ]]; then
+ camera_config="${array_camera_config[${i}]}"
+ usb_options="${array_camera_usb_options[${i}]}"
+ camera_usb_device="${array_camera_usb_device[${i}]}"
+ camera_raspi_options="${array_camera_raspi_options[${i}]}"
+ 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}]="already_in_use"
+ echo "config file='$camera_config':Video device already in use."
+ continue
fi
- else
- # device is not set explicitly in options, start usb with first found usb camera as the device
- echo "USB device was not set in options, start MJPG-streamer with the first found video device: ${video_devices[0]}"
- startUsb "${video_devices[0]}"
+ 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, 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
+ if containsString "$video_device" "${array_camera_device[@]}"; then
+ : #already in use
+ 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, starting MJPG-streamer with the first found video device: ${video_device}"
+ startUsb "${video_device}"
+ break
+ fi
+ fi
+ done
+ if [[ -n ${array_camera_device[${i}]} ]]; then
+ continue
+ fi
fi
- sleep 30 &
- wait
+ 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}]="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':Starting MJPG-streamer with video device: ${video_device}"
+ startRaspi
+ sleep 30 &
+ sleep_pid=$!
+ wait ${sleep_pid}
+ fi
+ fi
+ fi
+ done
+ done
- elif [ "`vcgencmd get_camera`" = "supported=1 detected=1" ] && { [ "$camera" = "auto" ] || [ "$camera" = "raspi" ] ; }; then
- startRaspi
- sleep 30 &
- wait
+ array_assigned_device=( ${array_camera_device[*]} )
+ if [[ ${#array_camera[@]} -eq ${#array_assigned_device[@]} ]]; then
+ echo "Done bringing up all configured video devices"
+ awaitChildren
- else
- echo "No camera detected, trying again in two minutes"
- sleep 120 &
- wait
+ # reset array_camera_device to empty
+ array_camera_device=()
+ for cam in ${array_camera[@]}; do
+ array_camera_device+=("")
+ done
+ fi
- 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/change_hostname b/src/modules/octopi/filesystem/root/etc/init.d/change_hostname
index 7c5ef568..2eb943d0 100755
--- a/src/modules/octopi/filesystem/root/etc/init.d/change_hostname
+++ b/src/modules/octopi/filesystem/root/etc/init.d/change_hostname
@@ -11,8 +11,14 @@
. /lib/lsb/init-functions
+BOOT_FOLDER=/boot/firmware
+# Fallback for older images
+if [ ! -f "${CONFIG_FILE}" ] && [ -f "/boot/octopi.txt" ]; then
+BOOT_FOLDER=/boot
+fi
+
do_start () {
- text_file="/boot/octopi-hostname.txt"
+ text_file="${BOOT_FOLDER}/octopi-hostname.txt"
if [ ! -f "$text_file" ]
then
exit 0
diff --git a/src/modules/octopi/filesystem/root/etc/init.d/change_password b/src/modules/octopi/filesystem/root/etc/init.d/change_password
index 851d3e2b..bcd60409 100755
--- a/src/modules/octopi/filesystem/root/etc/init.d/change_password
+++ b/src/modules/octopi/filesystem/root/etc/init.d/change_password
@@ -11,8 +11,14 @@
. /lib/lsb/init-functions
+BOOT_FOLDER=/boot/firmware
+# Fallback for older images
+if [ ! -f "${CONFIG_FILE}" ] && [ -f "/boot/octopi.txt" ]; then
+BOOT_FOLDER=/boot
+fi
+
do_start () {
- text_file="/boot/octopi-password.txt"
+ text_file="${BOOT_FOLDER}/octopi-password.txt"
if [ ! -f "$text_file" ]
then
exit 0
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/init.d/webcamd b/src/modules/octopi/filesystem/root/etc/init.d/webcamd
deleted file mode 100755
index a7cf3959..00000000
--- a/src/modules/octopi/filesystem/root/etc/init.d/webcamd
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/bin/sh
-
-### BEGIN INIT INFO
-# Provides: webcamd
-# Required-Start: $local_fs networking
-# Required-Stop:
-# Should-Start:
-# Should-Stop:
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: webcam daemon
-# Description: Starts the OctoPi webcam daemon with the user specified config in
-# /etc/default/webcamd.
-### END INIT INFO
-
-# Author: Gina Haeussge
-
-PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
-DESC="Webcam Daemon"
-NAME="webcamd"
-DAEMON=/root/bin/webcamd
-USER=pi
-PIDFILE=/var/run/$NAME.pid
-PKGNAME=webcamd
-SCRIPTNAME=/etc/init.d/$PKGNAME
-LOG=/var/log/webcamd.log
-
-# 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 "$ENABLED" -o "$ENABLED" != "1" ]
-then
- log_warning_msg "Not starting $PKGNAME, edit /etc/default/$PKGNAME to start it."
- 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 --no-close --quiet --pidfile $PIDFILE --make-pidfile \
- --startas /bin/bash --chuid $USER --user $USER -- -c "exec $DAEMON" >> $LOG 2>&1
- 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 $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/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/octoprint.service b/src/modules/octopi/filesystem/root/etc/systemd/system/octoprint.service
new file mode 100644
index 00000000..656ce446
--- /dev/null
+++ b/src/modules/octopi/filesystem/root/etc/systemd/system/octoprint.service
@@ -0,0 +1,15 @@
+[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"
+Environment="REQUESTS_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt"
+Type=simple
+User=1000
+ExecStart=/opt/octopi/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
new file mode 100644
index 00000000..451d2377
--- /dev/null
+++ b/src/modules/octopi/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/modules/octopi/filesystem/root/etc/systemd/system/wifi_powersave@.service b/src/modules/octopi/filesystem/root/etc/systemd/system/wifi_powersave@.service
new file mode 100644
index 00000000..bed5fb8d
--- /dev/null
+++ b/src/modules/octopi/filesystem/root/etc/systemd/system/wifi_powersave@.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=Set WiFi power save %i
+After=sys-subsystem-net-devices-wlan0.device
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=/sbin/iw dev wlan0 set power_save %i
+
+[Install]
+WantedBy=sys-subsystem-net-devices-wlan0.device
diff --git a/src/modules/octopi/filesystem/home/pi/scripts/add-octoprint-checkout b/src/modules/octopi/filesystem/root/opt/octopi/scripts/add-octoprint-checkout
similarity index 76%
rename from src/modules/octopi/filesystem/home/pi/scripts/add-octoprint-checkout
rename to src/modules/octopi/filesystem/root/opt/octopi/scripts/add-octoprint-checkout
index 615a2d92..d5cfbd7b 100755
--- a/src/modules/octopi/filesystem/home/pi/scripts/add-octoprint-checkout
+++ b/src/modules/octopi/filesystem/root/opt/octopi/scripts/add-octoprint-checkout
@@ -1,7 +1,13 @@
#!/bin/bash
-
-OCTOPRINT_FOLDER=/home/pi/OctoPrint
-OCTOPRINT_CONFIG=/home/pi/.octoprint/config.yaml
+USER_NAME=$(id -nu 1000)'
+OCTOPRINT_FOLDER=/home/"${USER_NAME}"/OctoPrint
+OCTOPRINT_CONFIG=/home/"${USER_NAME}"/.octoprint/config.yaml
+
+if [ "${PWD}" == "${OCTOPRINT_FOLDER}" ]; then
+ echo "Error: you are in the folder: "${OCTOPRINT_FOLDER}
+ echo "This is where OctoPrint is going to be checked out, please change to a different folder before running this script"
+ exit 1
+fi
pause() {
read -n1 -r -p $'Press any key to continue or Ctrl+C to exit...\n' key
diff --git a/src/modules/octopi/filesystem/home/pi/scripts/install-desktop b/src/modules/octopi/filesystem/root/opt/octopi/scripts/install-desktop
similarity index 100%
rename from src/modules/octopi/filesystem/home/pi/scripts/install-desktop
rename to src/modules/octopi/filesystem/root/opt/octopi/scripts/install-desktop
diff --git a/src/modules/octopi/filesystem/root/opt/octopi/scripts/safemode b/src/modules/octopi/filesystem/root/opt/octopi/scripts/safemode
new file mode 100755
index 00000000..1965f0c2
--- /dev/null
+++ b/src/modules/octopi/filesystem/root/opt/octopi/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/pi/scripts/welcome b/src/modules/octopi/filesystem/root/opt/octopi/scripts/welcome
similarity index 76%
rename from src/modules/octopi/filesystem/home/pi/scripts/welcome
rename to src/modules/octopi/filesystem/root/opt/octopi/scripts/welcome
index ec030680..7bc503ca 100755
--- a/src/modules/octopi/filesystem/home/pi/scripts/welcome
+++ b/src/modules/octopi/filesystem/root/opt/octopi/scripts/welcome
@@ -2,7 +2,7 @@
_NAME=$(hostname)
_IP=$(hostname -I)
-_OCTOPRINT_VERSION=$(/home/pi/oprint/bin/python -c "from octoprint._version import get_versions; print(get_versions()['version'])" || echo "unknown")
+_OCTOPRINT_VERSION=$(/opt/octopi/oprint/bin/python -c "from octoprint._version import get_versions; print(get_versions()['version'])" || echo "unknown")
_OCTOPI_VERSION=$(cat /etc/octopi_version || echo "unknown")
echo
@@ -16,7 +16,12 @@ do
done
for ip in $_IP;
do
- echo " http://$ip"
+ if [[ $ip =~ .*:.* ]]
+ then
+ echo " http://[$ip]"
+ else
+ echo " http://$ip"
+ fi
done
echo
@@ -29,7 +34,7 @@ then
echo "required for running OctoPrint. If you want a desktop environment you can "
echo "install it via"
echo
- echo " sudo /home/pi/scripts/install-desktop"
+ echo " sudo /opt/octopi/scripts/install-desktop"
fi
echo "------------------------------------------------------------------------------"
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/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 b5d250c5..4c594815 100755
--- a/src/modules/octopi/start_chroot_script
+++ b/src/modules/octopi/start_chroot_script
@@ -11,64 +11,100 @@ 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
+unpack /filesystem/boot /boot/firmware
+apt_update_skip
# in case we are building from a regular raspbian image instead of the lite one...
remove_extra=$(remove_if_installed scratch squeak-plugins-scratch squeak-vm wolfram-engine python-minecraftpi minecraft-pi sonic-pi oracle-java8-jdk bluej libreoffice-common libreoffice-core freepats greenfoot nodered)
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 --allow-change-held-packages install python3 python3-virtualenv python3-dev git screen subversion cmake cmake-data avahi-daemon libavahi-compat-libdnssd1 libffi-dev libssl-dev unzip libopenblas0-pthread libgfortran5
echo " - Reinstall iputils-ping"
-apt-get install --reinstall iputils-ping
-
-
-pushd /home/pi
-
- #build virtualenv
- sudo -u pi virtualenv oprint
-
- # first lets upgrade pip (the shipped version is way too old...)
- sudo -u pi /home/pi/oprint/bin/pip install --upgrade pip
-
- # OctoPrint & pyserial
+apt-get -y --force-yes install --reinstall iputils-ping
+
+# Path is hardcoded systemd service, this is not configurable
+OCTOPI_OPT_FOLDER=/opt/octopi
+mkdir -p "${OCTOPI_OPT_FOLDER}"
+chown "${BASE_USER}":"${BASE_USER}" "${OCTOPI_OPT_FOLDER}"
+OCTOPI_OCTOPRINT_FOLDER="${OCTOPI_OPT_FOLDER}"/oprint
+ln -s "${OCTOPI_OCTOPRINT_FOLDER}" /home/"${BASE_USER}"/oprint
+PIP="${OCTOPI_OCTOPRINT_FOLDER}"/bin/pip
+pushd "${OCTOPI_OPT_FOLDER}"
+
+ # build virtualenv
+ sudo -u "${BASE_USER}" python3 -m virtualenv --python=python3 oprint
+ sudo -u "${BASE_USER}" "${PIP}" install --upgrade pip
+
+ # 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}" "${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 --allow-change-held-packages install libjpeg62-turbo-dev
+ elif [ $( is_in_apt libjpeg8-dev ) -eq 1 ]; then
+ apt-get -y --allow-change-held-packages install libjpeg8-dev
+ fi
fi
-
- apt-get -y --force-yes --no-install-recommends install imagemagick libav-tools libv4l-dev
- gitclone OCTOPI_MJPGSTREAMER_REPO mjpg-streamer
- pushd mjpg-streamer
- mv mjpg-streamer-experimental/* .
- sudo -u pi make
+
+ apt-get -y --allow-change-held-packages --no-install-recommends install imagemagick ffmpeg libv4l-dev
+
+ 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
@@ -83,8 +119,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 --allow-change-held-packages --no-install-recommends nginx
+
+ ARCH=arm
+ if [ "${BASE_ARCH}" == "aarch64" ] || [ "${BASE_ARCH}" == "arm64" ]; 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
@@ -92,37 +167,37 @@ 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
if [ "$OCTOPI_INCLUDE_HAPROXY" == "yes" ]
then
echo "--- Installing haproxy"
- apt-get -y --force-yes install ssl-cert haproxy
+ DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confold" -y --allow-change-held-packages install ssl-cert haproxy
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 --allow-change-held-packages install libraspberrypi-bin
+ usermod -a -G video "${BASE_USER}"
+fi
# store octopi commit used to build this image
echo "$OCTOPI_COMMIT" > /etc/octopi_commit
@@ -130,9 +205,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
@@ -140,7 +215,7 @@ sed -i "s@secure_path=\"@secure_path=\"/root/bin:@g" /etc/sudoers
chmod +x /root/bin/git
# add some "How To" info to boot output
-# Note, this code is also in /filesystem/home/pi/scripts/
+# Note, this code is also in /filesystem/root/opt/octopi/scripts
sed -i 's@exit 0@@' /etc/rc.local
cat <<'EOT' >> /etc/rc.local
@@ -157,21 +232,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 /opt/octopi/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 /
@@ -186,20 +261,14 @@ update-rc.d change_password defaults
update-rc.d change_hostname defaults
-### Try and fix https://github.com/guysoft/OctoPi/issues/424
-
-sed -i "s@ExecStart=/usr/bin/ssh-keygen -A -v@ExecStart=/bin/bash -c ' /usr/bin/ssh-keygen -A -v >> /var/log/regenerate_ssh_host_keys.log 2>\&1'@g" /lib/systemd/system/regenerate_ssh_host_keys.service
-sed -i "s@ExecStartPost=/bin/systemctl disable regenerate_ssh_host_keys@ExecStartPost=/bin/bash -c 'for i in /etc/ssh/ssh_host_*_key*; do actualsize=\$(wc -c <\"\$i\") ;if [ \$actualsize -eq 0 ]; then echo size is 0 bytes ; exit 1 ; fi ; done ; /bin/systemctl disable regenerate_ssh_host_keys'@g" /lib/systemd/system/regenerate_ssh_host_keys.service
-
### OctoPrint
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
@@ -207,13 +276,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
@@ -221,23 +299,58 @@ 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
- # make webcamd autostart
- update-rc.d webcamd defaults
+ 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
+
+### Disable Wifi Power management
+
+systemctl_if_exists enable wifi_powersave@off.service
+
+### 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
+if [ "${BASE_DISTRO}" == "raspbian" ] || [ "${BASE_DISTRO}" == "raspios64" ] || [ "${BASE_DISTRO}" == "raspios" ]; then
+ apt install -y python3-pip python3-virtualenv
+ # sudo -u pi pip3 install --user virtualenv-tools3
+ systemctl_if_exists enable user-fix.service
+fi
+
+
#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 3e0f5196..5d761ab8 100644
--- a/src/nightly_build_scripts/generate_nightly_page.js
+++ b/src/nightly_build_scripts/generate_nightly_page.js
@@ -162,30 +162,30 @@ var outputPage = function(files, s) {
var output = new StringStream();
- output.write("");
+ output.write("");
output.write("Raspberry Pi
\n");
output.write("Stable Builds
\n")
- outputTable(filterNameByRegex(files, /^stable\/.*octopi-(wheezy|jessie|stretch)-.*/),
+ outputTable(filterNameByRegex(files, /^stable\/.*octopi-(wheezy|jessie|stretch|buster)-.*/),
output,
function(name) { return stripLeading(name, "stable/") },
3);
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)-/),
+ 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/vagrant/Vagrantfile b/src/vagrant/Vagrantfile
index a4567d95..a5b90944 100644
--- a/src/vagrant/Vagrantfile
+++ b/src/vagrant/Vagrantfile
@@ -1,7 +1,7 @@
vagrant_root = File.dirname(__FILE__)
Vagrant.configure("2") do |o|
# o.vm.box = "octopi-build"
- o.vm.box= "debian/stretch64"
+ o.vm.box= "debian/buster64"
o.ssh.shell = "bash -c 'BASH_ENV=/etc/profile exec bash'"
o.vm.synced_folder File.read("../custompios_path").gsub("\n",""), "/CustomPiOS", create:true, type: "nfs"
o.vm.synced_folder "../", "/distro", create:true, type: "nfs"
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