Skip to content

Commit 8bcaeb1

Browse files
authored
Merge pull request #91 from lbr38/devel
6.3.0
2 parents 163ed30 + 1e9ed55 commit 8bcaeb1

File tree

41 files changed

+2317
-1039
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2317
-1039
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ A dockerized web responsive interface to manage <a href="https://github.com/Moti
3232
## 📷 Supported cameras
3333

3434
- **USB cameras**
35-
- **Raspberry Pi cameras**
3635
- **Network cameras** (RTSP, HTTP, etc.)
3736

3837
## 📦 Requirements

docker/config/nginx/motionui.conf

Lines changed: 18 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ upstream php-handler {
1212
}
1313

1414
server {
15-
# Set motionui base directories variables
15+
# Motion-UI base directory variable
1616
set $WWW_DIR '/var/www/motionui';
1717

1818
listen 8080;
@@ -71,7 +71,7 @@ server {
7171
rewrite ^ /index.php;
7272
}
7373

74-
# API
74+
# Motion-UI API
7575
location /api/v1/ {
7676
include fastcgi_params;
7777
fastcgi_param SCRIPT_FILENAME $WWW_DIR/public/api/v1/index.php;
@@ -85,31 +85,23 @@ server {
8585

8686
# Go2rtc
8787
location ~ /go2rtc/ {
88-
proxy_set_header Host $host;
89-
proxy_set_header X-Forwarded-Scheme $scheme;
90-
proxy_set_header X-Forwarded-Proto $scheme;
91-
proxy_set_header X-Forwarded-For $remote_addr;
92-
proxy_set_header X-Real-IP $remote_addr;
93-
proxy_pass http://127.0.0.1:1984;
94-
proxy_set_header Upgrade $http_upgrade;
95-
proxy_set_header Connection $http_connection;
96-
proxy_http_version 1.1;
97-
rewrite /go2rtc/(.*) /$1 break;
98-
}
99-
100-
# Go2rtc MJPEG stream access
101-
location ~ /api/stream\.(mjpeg|mp4) {
10288
proxy_pass http://127.0.0.1:1984;
10389
proxy_http_version 1.1;
10490
proxy_set_header Upgrade $http_upgrade;
105-
proxy_set_header Connection "Upgrade";
91+
proxy_set_header Connection $http_connection;
10692
proxy_set_header Host $host;
107-
proxy_read_timeout 86400;
93+
# proxy_set_header X-Forwarded-Scheme $scheme;
94+
# proxy_set_header X-Forwarded-Proto $scheme;
95+
# proxy_set_header X-Forwarded-For $remote_addr;
96+
# proxy_set_header X-Real-IP $remote_addr;
97+
auth_basic "Restricted Content";
98+
auth_basic_user_file /var/lib/motionui/go2rtc/.htpasswd;
99+
rewrite /go2rtc/(.*) /$1 break;
108100
}
109101

110-
# Go2rtc embedded websocket server access
111-
# Used to stream via WebRTC and MSE
112-
location /api/ws {
102+
# Go2rtc MJPEG stream access
103+
location ~ /api/(stream\.(mjpeg|mp4)|ws) {
104+
gzip off;
113105
proxy_pass http://127.0.0.1:1984;
114106
proxy_http_version 1.1;
115107
proxy_set_header Upgrade $http_upgrade;
@@ -131,25 +123,15 @@ server {
131123
fastcgi_request_buffering off;
132124
}
133125

134-
location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
126+
# Static files
127+
location ~ \.(?:svg|png|html|ttf|ico|jpg|jpeg|gif|css|js|map)$ {
128+
expires 1d;
129+
add_header Cache-Control "public, max-age=3600 immutable";
135130
try_files $uri $uri/ =404;
136-
add_header Cache-Control "public, max-age=3600";
137-
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
138-
add_header Referrer-Policy "no-referrer" always;
139-
add_header X-Content-Type-Options "nosniff" always;
140-
add_header X-Download-Options "noopen" always;
141-
add_header X-Frame-Options "SAMEORIGIN" always;
142-
add_header X-Permitted-Cross-Domain-Policies "none" always;
143-
add_header X-Robots-Tag "none" always;
144-
add_header X-XSS-Protection "1; mode=block" always;
145-
access_log off;
146-
}
147-
148-
location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap)$ {
149131
access_log off;
150132
}
151133

152-
# Websocket server
134+
# Motion-UI websocket server
153135
location /ws {
154136
proxy_pass http://127.0.0.1:8085;
155137
proxy_http_version 1.1;

docker/init

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,18 @@ if [ ! -f "$GO2RTC_DIR/go2rtc.yml" ]; then
2424
chown www-data:motionui "$GO2RTC_DIR/go2rtc.yml"
2525
fi
2626

27+
# Generate go2rtc .htpasswd file if not exists
28+
if [ ! -f "$GO2RTC_DIR/.htpasswd" ]; then
29+
PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
30+
printf "go2rtc:$(openssl passwd -5 $PASSWORD)\n" >> "$GO2RTC_DIR/.htpasswd"
31+
chown www-data:www-data "$GO2RTC_DIR/.htpasswd"
32+
chmod 600 "$GO2RTC_DIR/.htpasswd"
33+
34+
echo "Generated password for /go2rtc web interface:"
35+
echo "Username: go2rtc"
36+
echo "Password: $PASSWORD"
37+
fi
38+
2739
# Set permissions
2840
/bin/bash $WWW_DIR/bin/motionui -p &
2941
chown -R www-data:motionui $DATA_DIR

www/controllers/Camera/Add.php

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
<?php
2+
3+
namespace Controllers\Camera;
4+
5+
use Exception;
6+
7+
class Add extends Camera
8+
{
9+
/**
10+
* Add a new camera
11+
*/
12+
public function add(array $params) : void
13+
{
14+
if (!IS_ADMIN) {
15+
throw new Exception('You are not allowed to add a new camera');
16+
}
17+
18+
$motionParams = [];
19+
$go2rtcStreams = [];
20+
$ffmpeg = false;
21+
$ffmpegParams = '';
22+
23+
/**
24+
* Check that minimal required parameters are set
25+
*/
26+
Param\Name::check($params['name']);
27+
Param\Device::check($params['main-stream-device']);
28+
Param\Resolution::check($params['main-stream-resolution']);
29+
Param\Framerate::check($params['main-stream-framerate']);
30+
Param\BasicAuthUsername::check($params['username']);
31+
Param\BasicAuthPassword::check($params['password']);
32+
33+
/**
34+
* Get camera configuration template
35+
*/
36+
$configuration = $this->cameraConfigController->getTemplate();
37+
38+
/**
39+
* Set camera global configuration
40+
*/
41+
$configuration['name'] = $params['name'];
42+
$configuration['main-stream']['device'] = $params['main-stream-device'];
43+
$configuration['main-stream']['width'] = explode('x', $params['main-stream-resolution'])[0];
44+
$configuration['main-stream']['height'] = explode('x', $params['main-stream-resolution'])[1];
45+
$configuration['main-stream']['framerate'] = $params['main-stream-framerate'];
46+
$configuration['authentication']['username'] = \Controllers\Common::validateData($params['username']);
47+
$configuration['authentication']['password'] = \Controllers\Common::validateData($params['password']);
48+
$configuration['motion-detection']['enable'] = $params['motion-detection-enable'];
49+
// If camera is a http:// camera, use mjpeg mode for streaming
50+
if (preg_match('#^https?://#', $configuration['main-stream']['device'])) {
51+
$configuration['stream']['technology'] = 'mjpeg';
52+
}
53+
54+
/**
55+
* Add camera in database
56+
*/
57+
$this->model->add();
58+
59+
/**
60+
* Get new camera Id from database
61+
*/
62+
$id = $this->model->getLastInsertRowID();
63+
64+
if (empty($id)) {
65+
throw new Exception('Could not retrieve camera Id');
66+
}
67+
68+
/**
69+
* Get camera motion configuration template
70+
*/
71+
$motionConfiguration = $this->motionTemplateController->get($id);
72+
73+
/**
74+
* Prepare motion configuration parameters
75+
*/
76+
$motionConfiguration['device_id'] = ['enabled' => true, 'value' => $id];
77+
$motionConfiguration['device_name'] = ['enabled' => true, 'value' => $params['name']];
78+
$motionConfiguration['width'] = ['enabled' => true, 'value' => explode('x', $params['main-stream-resolution'])[0]];
79+
$motionConfiguration['height'] = ['enabled' => true, 'value' => explode('x', $params['main-stream-resolution'])[1]];
80+
$motionConfiguration['framerate'] = ['enabled' => true, 'value' => $params['main-stream-framerate']];
81+
82+
// If auth username and password are set
83+
if (!empty($configuration['authentication']['username']) and !empty($configuration['authentication']['password'])) {
84+
$motionConfiguration['netcam_userpass']['value'] = $configuration['authentication']['username'] . ':' . $configuration['authentication']['password'];
85+
$motionConfiguration['netcam_userpass']['enabled'] = true;
86+
}
87+
88+
// Case the URL is http(s)://
89+
if (preg_match('#^https?://#', $configuration['main-stream']['device'])) {
90+
$motionConfiguration['netcam_url'] = ['enabled' => true, 'value' => $configuration['main-stream']['device']];
91+
$motionConfiguration['movie_passthrough'] = ['enabled' => false, 'value' => 'on'];
92+
$motionConfiguration['v4l2_device'] = ['enabled' => false, 'value' => ''];
93+
// Case the URL is rtsp://
94+
} else if (preg_match('#^rtsp?://#', $configuration['main-stream']['device'])) {
95+
$motionConfiguration['netcam_url'] = ['enabled' => true, 'value' => $configuration['main-stream']['device']];
96+
$motionConfiguration['movie_passthrough'] = ['enabled' => true, 'value' => 'on'];
97+
$motionConfiguration['v4l2_device'] = ['enabled' => false, 'value' => ''];
98+
// Case the URL is /dev/video
99+
} else if (preg_match('#^/dev/video#', $configuration['main-stream']['device'])) {
100+
// /dev/videoX devices cannot be used by both go2rtc and motion at the same time (device is locked), so force the use of the go2rtc stream
101+
$motionConfiguration['netcam_url'] = ['enabled' => true, 'value' => 'rtsp://127.0.0.1:8554/camera_' . $id . '?mp4'];
102+
$motionConfiguration['movie_passthrough'] = ['enabled' => false, 'value' => 'on'];
103+
$motionConfiguration['v4l2_device'] = ['enabled' => true, 'value' => $configuration['main-stream']['device']];
104+
}
105+
106+
/**
107+
* Encode global configuration to JSON
108+
*/
109+
try {
110+
$configurationJson = json_encode($configuration, JSON_THROW_ON_ERROR);
111+
} catch (JsonException $e) {
112+
throw new Exception('Could not encode camera configuration to JSON');
113+
}
114+
115+
/**
116+
* Encode motion configuration to JSON
117+
*/
118+
try {
119+
$motionConfigurationJson = json_encode($motionConfiguration, JSON_THROW_ON_ERROR);
120+
} catch (JsonException $e) {
121+
throw new Exception('Could not encode camera configuration to JSON');
122+
}
123+
124+
/**
125+
* Save configurations to database
126+
*/
127+
$this->model->saveGlobalConfiguration($id, $configurationJson);
128+
$this->model->saveMotionConfiguration($id, $motionConfigurationJson);
129+
130+
/**
131+
* Edit motion configuration file for this camera
132+
*/
133+
$this->motionConfigController->write(CAMERAS_MOTION_CONF_AVAILABLE_DIR . '/camera-' . $id . '.conf', $motionConfiguration);
134+
135+
/**
136+
* Enable / disable motion configuration file
137+
*/
138+
if ($configuration['motion-detection']['enable'] == 'true') {
139+
$this->motionConfigController->enable($id);
140+
} else {
141+
$this->motionConfigController->disable($id);
142+
}
143+
144+
/**
145+
* Define proper stream URLs for go2rtc
146+
*/
147+
$go2rtcStreams = $this->generateGo2rtcStreams($id, $configuration);
148+
149+
/**
150+
* Add a new stream in go2rtc
151+
*/
152+
$this->go2rtcController->addStream($id, $go2rtcStreams);
153+
154+
unset($configuration, $configurationJson, $motionConfiguration, $motionConfigurationJson);
155+
}
156+
}

0 commit comments

Comments
 (0)