Skip to content

Commit

Permalink
6.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
lbr38 committed Feb 23, 2025
1 parent 69e4a09 commit 14ee063
Show file tree
Hide file tree
Showing 31 changed files with 410 additions and 111 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@
A dockerized web responsive interface to manage <a href="https://github.com/Motion-Project/motion"><b>motion</b></a> (an open-source motion detection software) and visualize cameras live stream.

<div align="center">
<img src="https://github.com/user-attachments/assets/bdae2550-819d-40c4-895b-541ee64bdc03" width=25% align="top">
<img src="https://github.com/user-attachments/assets/964f1307-c295-49f6-82e5-db6326f909b4" width=25% align="top">
&nbsp;
<img src="https://github.com/user-attachments/assets/afe3e48a-3a26-4e75-a6a7-a97b2ac2bf9e" width=25% align="top">
<img src="https://github.com/user-attachments/assets/caa8944d-5d8e-4b4b-a706-5a2e469dac7e" width=25% align="top">
&nbsp;
<img src="https://github.com/user-attachments/assets/a2472f8b-24fc-4967-bb6a-f8ad8af95270" width=25% align="top">
<img src="https://github.com/user-attachments/assets/7a9f1efd-bef0-42b9-ba8f-6c7bde8be028" width=25% align="top">
</div>
<br>
<div align="center">
<img src="https://github.com/user-attachments/assets/cb9137c7-484a-4c2c-ad0f-c33ef7a602bd" width=25% align="top">
<img src="https://github.com/user-attachments/assets/0c3876f5-dfa6-45bd-a750-ca8b4cfe1133" width=25% align="top">
&nbsp;
<img src="https://github.com/user-attachments/assets/81c05e3f-599d-4cc1-9d9a-9748fce54763" width=25% align="top">
<img src="https://github.com/user-attachments/assets/68cd77fd-69cf-46f4-aca2-528d5d42077f" width=25% align="top">
&nbsp;
<img src="https://github.com/user-attachments/assets/04b18116-2af0-4bd3-8438-e9f1fed8c7ed" width=25% align="top">
<img src="https://github.com/user-attachments/assets/ba3352ea-4174-4707-9f4c-9f6bf2074968" width=25% align="top">
</div>

<br>
Expand Down
102 changes: 84 additions & 18 deletions docker/config/go2rtc/init
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,20 @@ test -f $DAEMON || exit 0
#
function start()
{
LOGFILE="/var/lib/motionui/go2rtc/logs/$(date +'%Y-%m-%d_%H-%M-%S')-go2rtc.log"
# If go2rtc is running
if ps aux | grep "/usr/local/bin/go2rtc" | grep -q -v "grep"; then
echo "go2rtc is already running"
exit 0
fi

echo "Starting go2rtc"
# Clean any existing PID file
rm -f "$PIDFILE"

LOGFILE="/var/lib/motionui/go2rtc/logs/$(date +'%Y-%m-%d_%H-%M-%S')-go2rtc.log"

# Create PID directory
mkdir -p /run/go2rtc -m 750
mkdir -p /run/go2rtc
chmod 755 /run/go2rtc
chown www-data:www-data /run/go2rtc

# Create log directory
Expand Down Expand Up @@ -61,34 +69,58 @@ function start()
start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile \
--chuid www-data --umask 002 \
--startas /bin/bash -- -c "exec $DAEMON $DAEMON_OPTS > /var/lib/motionui/go2rtc/logs/go2rtc.log 2>&1"

# If no PID file was created, the process did not start properly
if [ ! -f "$PIDFILE" ]; then
echo "Error starting go2rtc: PID file is missing"
exit 1
fi

chmod 600 "$PIDFILE"
chown www-data:www-data /run/go2rtc/go2rtc.pid

PID=$(cat "$PIDFILE")

# If the PID is empty, the process is not running
if [ -z "$PID" ]; then
echo "Error starting go2rtc: PID file is empty"
exit 1
fi

echo "go2rtc started, PID: $PID"
}

#
# Stop the go2rtc stream server
#
function stop()
{
echo "Stopping go2rtc"
i="0"

if [ -f "$PIDFILE" ]; then
PID=$(cat "$PIDFILE")
# If go2rtc is running
if ps aux | grep "/usr/local/bin/go2rtc" | grep -q -v "grep"; then
echo "Stopping go2rtc"

# If the PID is empty, the process is not running
if [ -z "$PID" ]; then
exit 0
fi
# If a PID file exists, get the PID and kill the process
if [ -f "$PIDFILE" ]; then
PID=$(cat "$PIDFILE")

# Check if a process with this PID is still running
if /usr/bin/ps -p "$PID" > /dev/null; then
# echo "Force stopping go2rtc (kill)"
kill "$PID"
# If the PID is empty, the process is not running
if [ -z "$PID" ]; then
exit 0
fi

# Check if a process with this PID is still running
if /usr/bin/ps -p "$PID" > /dev/null; then
# echo "Force stopping go2rtc (kill)"
kill "$PID"
fi
fi

# Wait for the process to stop (timeout 10s)
i="0"
while true; do
# Check if the process is still running, quit if not
if ! ps aux | grep -q "/usr/local/bin/go2rtc" | grep -v "grep"; then
if ! ps aux | grep "/usr/local/bin/go2rtc" | grep -q -v "grep"; then
break
fi

Expand All @@ -100,10 +132,40 @@ function stop()
(( i++ ))
sleep 1
done
fi

# Remove PID file
rm -f "$PIDFILE"
# Remove PID file
rm -f "$PIDFILE"
}

#
# Get go2rtc service status
#
function status()
{
# If go2rtc is not running, exit
if ! ps aux | grep "/usr/local/bin/go2rtc" | grep -q -v "grep"; then
echo "go2rtc is not running"
exit 1
fi

# If the process is running with no PID file, exit with an error
if [ ! -f "$PIDFILE" ]; then
echo "go2rtc is running but PID file is missing"
exit 1
fi

# Get PID from PID file
PID=$(cat "$PIDFILE")

# If the PID is empty, exit with an error
if [ -z "$PID" ]; then
echo "go2rtc is running but PID file is empty"
exit 1
fi

echo "go2rtc is running, PID: $PID"
exit 0
}

case "$1" in
Expand All @@ -119,6 +181,10 @@ case "$1" in
stop && start
;;
status)
status



echo "Status go2rtc"
if [ -f $PIDFILE ]; then
echo -n "Running process for $NAME : "
Expand Down
2 changes: 1 addition & 1 deletion docker/config/motion/init
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ case "$1" in
i="0"
while true; do
# Check if the process is still running, quit if not
if ! ps aux | grep -q "/usr/bin/motion" | grep -v "grep"; then
if ! ps aux | grep "/usr/bin/motion" | grep -q -v "grep"; then
break
fi

Expand Down
2 changes: 1 addition & 1 deletion docker/config/nginx/motionui.conf
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ server {
}

# Go2rtc embedded websocket server access
# Used to stream via WebRTC
# Used to stream via WebRTC and MSE
location /api/ws {
proxy_pass http://127.0.0.1:1984;
proxy_http_version 1.1;
Expand Down
6 changes: 2 additions & 4 deletions docker/init
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,8 @@ fi
/bin/su -s /bin/bash -c "php $WWW_DIR/tools/database/initialize.php" www-data
/bin/su -s /bin/bash -c "php $WWW_DIR/tools/database/update.php" www-data

# Start go2rtc in background, if not already running (database update may haved started it)
if ! ps aux | grep "/usr/local/bin/go2rtc" | grep -v -q "grep"; then
/usr/sbin/service go2rtc start
fi
# Make sure go2rtc service is started
/usr/sbin/service go2rtc start

# Start shell service in background
/bin/bash "$WWW_DIR/bin/service.sh" &
Expand Down
55 changes: 48 additions & 7 deletions www/controllers/Camera/Camera.php
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,9 @@ public function add(array $params) : void
$motionParams['v4l2_device'] = ['status' => 'disabled', 'value' => ''];
// Case the URL is /dev/video
} else if (preg_match('#^/dev/video#', $url)) {
$motionParams['v4l2_device'] = ['status' => 'enabled', 'value' => $url];
$motionParams['netcam_url'] = ['status' => 'disabled', 'value' => ''];
$motionParams['netcam_url'] = ['status' => 'enabled', 'value' => 'rtsp://127.0.0.1:8554/camera_' . $id . '?mp4'];
$motionParams['movie_passthrough'] = ['status' => 'enabled', 'value' => 'off'];
$motionParams['v4l2_device'] = ['status' => 'disabled', 'value' => ''];
}

/**
Expand Down Expand Up @@ -314,6 +314,9 @@ public function edit(int $id, array $params) : void
Param\Rotate::check($params['rotate']);
Param\BasicAuthUsername::check($params['basic-auth-username']);
Param\BasicAuthPassword::check($params['basic-auth-password']);
Param\OnvifEnable::check($params['onvif-enable']);
Param\OnvifPort::check($params['onvif-port']);
// Param\OnvifUri::check($params['onvif-uri']);

/**
* Set camera configuration
Expand All @@ -334,6 +337,47 @@ public function edit(int $id, array $params) : void
$configuration['motion-detection-enable'] = $params['motion-detection-enable'];
$configuration['timelapse-enable'] = $params['timelapse-enable'];
$configuration['hardware-acceleration'] = $params['hardware-acceleration'];
$configuration['onvif']['enable'] = $params['onvif-enable'];
$configuration['onvif']['port'] = $params['onvif-port'];
// $configuration['onvif']['uri'] = $params['onvif-uri'];

/**
* Try to generate Onvif Url
*/
if ($params['onvif-enable'] == 'true') {
// If the Url is a device, it cannot be moved
if (preg_match('#/dev/video#', $params['url'])) {
throw new Exception('Device camera are not movable');
}

// Parse camera URL to extract IP/hostname
$parsedUrl = parse_url($params['url']);

if ($parsedUrl === false or empty($parsedUrl)) {
throw new Exception('Could not retrieve camera IP from URL');
}

if (empty($parsedUrl['host'])) {
throw new Exception('Could not determine camera IP from URL');
}

$cameraIp = $parsedUrl['host'];

// Build Onvif URL
$onvifUrl = 'http://' . $cameraIp;

// If a port is set, add it to the URL
if (isset($params['onvif-port']) and $params['onvif-port'] > 0) {
$onvifUrl .= ':' . $params['onvif-port'];
}

// If a URI is set, add it to the URL
// if (!empty($params['onvif-uri'])) {
// $onvifUrl .= $params['onvif-uri'];
// }

$configuration['onvif']['url'] = $onvifUrl;
}

/**
* Define proper URL for go2rtc and motion
Expand All @@ -345,9 +389,6 @@ public function edit(int $id, array $params) : void
$url = preg_replace('#://#i', '://' . $configuration['basic-auth-username'] . ':' . $configuration['basic-auth-password'] . '@', $url);
}

// First, add URL without filter to go2rtc
// $go2rtcStreams[] = $url;

// Case the URL is http(s)://
if (preg_match('#^https?://#', $url)) {
$ffmpeg = true;
Expand Down Expand Up @@ -434,9 +475,9 @@ public function edit(int $id, array $params) : void
$motionParams['v4l2_device'] = ['status' => 'disabled', 'value' => ''];
// Case the URL is /dev/video
} else if (preg_match('#^/dev/video#', $url)) {
$motionParams['v4l2_device'] = ['status' => 'enabled', 'value' => $url];
$motionParams['netcam_url'] = ['status' => 'disabled', 'value' => ''];
$motionParams['netcam_url'] = ['status' => 'enabled', 'value' => 'rtsp://127.0.0.1:8554/camera_' . $id . '?mp4'];
$motionParams['movie_passthrough'] = ['status' => 'enabled', 'value' => 'off'];
$motionParams['v4l2_device'] = ['status' => 'disabled', 'value' => ''];
}

/**
Expand Down
6 changes: 6 additions & 0 deletions www/controllers/Camera/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ public function getTemplate()
'motion-detection-enable' => 'true',
'timelapse-enable' => 'false',
'hardware-acceleration' => 'false',
'onvif' => [
'enable' => 'false',
'port' => '80',
'uri' => '',
'url' => '',
],
];
}
}
18 changes: 18 additions & 0 deletions www/controllers/Camera/Param/OnvifEnable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Controllers\Camera\Param;

use Exception;

class OnvifEnable
{
/**
* Check that Onvif enable is valid
*/
public static function check(string $enable) : void
{
if ($enable != "true" and $enable != "false") {
throw new Exception('Onvif enable is invalid');
}
}
}
22 changes: 22 additions & 0 deletions www/controllers/Camera/Param/OnvifPort.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

namespace Controllers\Camera\Param;

use Exception;

class OnvifPort
{
/**
* Check that port is valid
*/
public static function check(string $port) : void
{
if (empty($port)) {
return;
}

if ($port < 0 or $port > 65535) {
throw new Exception('Onvif port is invalid');
}
}
}
26 changes: 26 additions & 0 deletions www/controllers/Camera/Param/OnvifUri.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Controllers\Camera\Param;

use Exception;

class OnvifUri
{
/**
* Check that URI is valid
*/
public static function check(string $uri) : void
{
if (empty($uri)) {
return;
}

/**
* Check that URI is valid
* Should start with '/' or '?' and contain only allowed characters
*/
if (!preg_match('/^[\?\/a-zA-Z0-9\-\_\&\=\%]+$/', $uri)) {
throw new Exception('Invalid ONVIF URI');
}
}
}
Loading

0 comments on commit 14ee063

Please sign in to comment.