-
Notifications
You must be signed in to change notification settings - Fork 41
/
cameras.sh
executable file
·308 lines (274 loc) · 11.3 KB
/
cameras.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
#!/bin/bash
detect_camera() {
echo
echo
echo "Verify the camera is currently unplugged from USB....."
if prompt_confirm "Is the camera you are trying to detect unplugged from USB?"; then
readarray -t c1 < <(ls -1 /dev/v4l/by-id/*index0 2>/dev/null)
fi
dmesg -C
echo "Plug your camera in via USB now (detection time-out in 1 min)"
counter=0
while [[ -z "$CAM" ]] && [[ $counter -lt 60 ]]; do
CAM=$(dmesg | sed -n -e 's/^.*SerialNumber: //p')
TEMPUSBCAM=$(dmesg | sed -n -e 's|^.*input:.*/\(.*\)/input/input.*|\1|p')
counter=$(( $counter + 1 ))
if [[ -n "$TEMPUSBCAM" ]] && [[ -z "$CAM" ]]; then
break
fi
sleep 1
done
readarray -t c2 < <(ls -1 /dev/v4l/by-id/*index0 2>/dev/null)
#https://stackoverflow.com/questions/2312762
#TODO: what if there is more than one element?
BYIDCAM=(`echo ${c2[@]} ${c1[@]} | tr ' ' '\n' | sort | uniq -u `)
echo $BYIDCAM
dmesg -C
}
remove_camera() {
systemctl stop $1.service
systemctl disable $1.service
rm /etc/systemd/system/$1.service 2>/dev/null
rm /etc/$1.env 2>/dev/null
sed -i "/$1/d" /etc/udev/rules.d/99-octoprint.rules
sed -i "/$1/d" /etc/octoprint_cameras
if [ "$HAPROXY" == true ]; then
sed -i "/use_backend $1/d" /etc/haproxy/haproxy.cfg
sed -i "/#$1 start/,/#$1 stop/d" /etc/haproxy/haproxy.cfg
systemctl restart haproxy
fi
}
write_camera() {
get_settings
if [ -z "$STREAMER" ]; then
STREAMER="ustreamer"
fi
if [ -n "$BYIDCAM" ] && [ -z "$CAM" ] && [ -z "$TEMPUSBCAM" ]; then
CAMDEVICE=$BYIDCAM
else
CAMDEVICE=/dev/cam${INUM}_$INSTANCE
fi
OUTFILE=cam${INUM}_$INSTANCE
#mjpg-streamer
if [ "$STREAMER" == mjpg-streamer ]; then
cat $SCRIPTDIR/octocam_mjpg.service | \
sed -e "s/OCTOUSER/$OCTOUSER/" \
-e "s/OCTOCAM/$CAMDEVICE/" \
-e "s/RESOLUTION/$RESOLUTION/" \
-e "s/FRAMERATE/$FRAMERATE/" \
-e "s/CAMPORT/$CAMPORT/" > $SCRIPTDIR/cam${INUM}_$INSTANCE.service
fi
#ustreamer
if [ "$STREAMER" == ustreamer ]; then
if [ "$PI" == true ]; then
cat $SCRIPTDIR/octocam_ustream.service | \
sed -e "s/OCTOUSER/$OCTOUSER/" \
-e "s/OCTOCAM/cam${INUM}_$INSTANCE/" \
-e "s|ExecStart=|ExecStart=/usr/bin/libcamerify |" > $SCRIPTDIR/$OUTFILE.service
else
cat $SCRIPTDIR/octocam_ustream.service | \
sed -e "s/OCTOUSER/$OCTOUSER/" \
-e "s/OCTOCAM/cam${INUM}_$INSTANCE/" > $SCRIPTDIR/$OUTFILE.service
fi
fi
#camera-streamer
if [ "$STREAMER" == camera-streamer ]; then
if [ "$PI" == true ]; then
cat $SCRIPTDIR/picam_camstream.service | \
sed -e "s/OCTOUSER/$OCTOUSER/" \
-e "s/OCTOCAM/cam${INUM}_$INSTANCE/" > $SCRIPTDIR/$OUTFILE.service
else
cat $SCRIPTDIR/octocam_camstream.service | \
sed -e "s/OCTOUSER/$OCTOUSER/" \
-e "s/OCTOCAM/cam${INUM}_$INSTANCE/" > $SCRIPTDIR/$OUTFILE.service
fi
fi
#convert RES into WIDTH and HEIGHT for camera-streamer
CAMWIDTH=$(sed -r 's/^([0-9]+)x[0-9]+/\1/' <<<"$RESOLUTION")
CAMHEIGHT=$(sed -r 's/^[0-9]+x([0-9]+)/\1/' <<<"$RESOLUTION")
sudo -u $user echo "DEVICE=$CAMDEVICE" >> /etc/$OUTFILE.env
sudo -u $user echo "RES=$RESOLUTION" >> /etc/$OUTFILE.env
sudo -u $user echo "FRAMERATE=$FRAMERATE" >> /etc/$OUTFILE.env
sudo -u $user echo "PORT=$CAMPORT" >> /etc/$OUTFILE.env
sudo -u $user echo "WIDTH=$CAMWIDTH" >> /etc/$OUTFILE.env
sudo -u $user echo "HEIGHT=$CAMHEIGHT" >> /etc/$OUTFILE.env
cp $SCRIPTDIR/$OUTFILE.service /etc/systemd/system/
echo "camera:cam${INUM}_$INSTANCE port:$CAMPORT udev:true" >> /etc/octoprint_cameras
#config.yaml modifications - only if INUM not set
if [ -z "$INUM" ]; then
sudo -u $user $OCTOEXEC --basedir $BASE config set plugins.classicwebcam.snapshot "http://localhost:$CAMPORT?action=snapshot"
if [ -z "$CAMHAPROXY" ]; then
sudo -u $user $OCTOEXEC --basedir $BASE config set plugins.classicwebcam.stream "http://$(hostname).local:$CAMPORT?action=stream"
else
sudo -u $user $OCTOEXEC --basedir $BASE config set plugins.classicwebcam.stream "/cam_$INSTANCE/?action=stream"
fi
sudo -u $user $OCTOEXEC --basedir $BASE config append_value --json system.actions "{\"action\": \"Reset video streamer\", \"command\": \"sudo systemctl restart cam_$INSTANCE\", \"name\": \"Restart webcam\"}"
if prompt_confirm "Instance must be restarted for settings to take effect. Restart now?"; then
systemctl restart $INSTANCE
fi
fi
write_cam_udev
if [ -n "$CAMHAPROXY" ]; then
HAversion=$(haproxy -v | sed -n 's/^.*version \([0-9]\).*/\1/p')
#find frontend line, do insert
sed -i "/use_backend $INSTANCE if/a\ use_backend cam${INUM}_$INSTANCE if { path_beg /cam${INUM}_$INSTANCE/ }" /etc/haproxy/haproxy.cfg
if [ $HAversion -gt 1 ]; then
EXTRACAM="backend cam${INUM}_$INSTANCE\n\
http-request replace-path /cam${INUM}_$INSTANCE/(.*) /|\1\n\
server webcam1 127.0.0.1:$CAMPORT"
else
EXTRACAM="backend cam${INUM}_$INSTANCE\n\
reqrep ^([^|\ :]*)|\ /cam${INUM}_$INSTANCE/(.*) |\1|\ /|\2 \n\
server webcam1 127.0.0.1:$CAMPORT"
fi
echo "#cam${INUM}_$INSTANCE start" >> /etc/haproxy/haproxy.cfg
sed -i "/#cam${INUM}_$INSTANCE start/a $EXTRACAM" /etc/haproxy/haproxy.cfg
#these are necessary because sed append seems to have issues with escaping for the /\1
sed -i 's/\/|1/\/\\1/' /etc/haproxy/haproxy.cfg
sed -i 's/\/|2/\/\\2/' /etc/haproxy/haproxy.cfg
#haproxy 1.x correction
sed -i 's/|/\\/g' /etc/haproxy/haproxy.cfg
echo "#cam${INUM}_$INSTANCE stop" >> /etc/haproxy/haproxy.cfg
systemctl restart haproxy
fi
}
write_cam_udev() {
#Either Serial number or USB port
#Serial Number
if [ -n "$CAM" ]; then
echo SUBSYSTEM==\"video4linux\", ATTRS{serial}==\"$CAM\", ATTR{index}==\"0\", SYMLINK+=\"cam${INUM}_$INSTANCE\" >> /etc/udev/rules.d/99-octoprint.rules
fi
#USB port camera
if [ -n "$USBCAM" ]; then
echo SUBSYSTEM==\"video4linux\",KERNELS==\"$USBCAM\", SUBSYSTEMS==\"usb\", ATTR{index}==\"0\", DRIVERS==\"uvcvideo\", SYMLINK+=\"cam${INUM}_$INSTANCE\" >> /etc/udev/rules.d/99-octoprint.rules
fi
}
add_camera() {
PI=$1
INUM=''
CAMHAPROX=''
get_settings
if [ "$STREAMER" == none ]; then
echo "No camera streamer service has been installed."
echo "Use the utilities menu to add one."
main_menu
fi
if [ $SUDO_USER ]; then user=$SUDO_USER; fi
echo 'Adding camera' | log
if [ -z "$INSTANCE" ]; then
PS3='Select instance number to add camera to: '
get_instances true
select camopt in "${INSTANCE_ARR[@]}"
do
if [ "$camopt" == Quit ]; then
main_menu
fi
echo "Selected instance for camera: ${cyan}$camopt${white}"
INSTANCE=$camopt
OCTOCONFIG="/home/$user/"
BASE="/home/$user/.$INSTANCE"
OCTOUSER=$user
if grep -q "cam_$INSTANCE" /etc/udev/rules.d/99-octoprint.rules; then
echo "It appears this instance already has at least one camera."
if prompt_confirm "Do you want to add an additional camera for this instance?"; then
echo "Enter a number for this camera."
echo "Ex. entering 2 will setup a service called cam2_$INSTANCE"
echo
read INUM
if [ -z "$INUM" ]; then
echo "No value given, setting as 2"
INUM='2'
fi
else
main_menu
fi
fi
break
done
fi
#for now just set a flag that we are going to write cameras behind haproxy
if [ "$HAPROXY" == true ]; then
if prompt_confirm "Add cameras to haproxy?"; then
CAMHAPROXY=1
fi
fi
if [ -z "$PI" ]; then
detect_camera
if [ -n "$NOSERIAL" ] && [ -n "$CAM" ]; then
unset CAM
fi
#Failed state. Nothing detected
if [ -z "$CAM" ] && [ -z "$TEMPUSBCAM" ] && [ -z "$BYIDCAM" ]; then
echo
echo "${red}No camera was detected during the detection period.${white}"
echo "Try again or try a different camera."
return
fi
#only BYIDCAM
if [ -z "$CAM" ] && [ -z "$TEMPUSBCAM" ] && [ -n "$BYIDCAM" ]; then
echo "Camera was only detected as ${cyan}/dev/v4l/by-id${white} entry."
echo "This will be used as the camera device identifier"
fi
#only USB address
if [ -z "$CAM" ] && [ -n "$TEMPUSBCAM" ]; then
echo "${red}Camera Serial Number not detected${white}"
echo -e "Camera will be setup with physical USB address of ${cyan}$TEMPUSBCAM.${white}"
echo "The camera will have to stay plugged into this location."
USBCAM=$TEMPUSBCAM
fi
#serial number
if [ -n "$CAM" ]; then
echo -e "Camera detected with serial number: ${cyan}$CAM ${white}"
check_sn "$CAM"
fi
else
echo
echo
echo "Setting up a Pi camera service."
echo "Please note that mixing this setup with USB cameras may lead to issues."
echo "Don't expect extensive support for trying to fix these issues."
echo
echo
fi
CAMPORT=$(tail -1 /etc/octoprint_cameras 2>/dev/null | sed -n -e 's/^.*port:\([[:graph:]]*\) \(.*\)/\1/p')
if [ -z "$CAMPORT" ]; then
CAMPORT=8000
fi
CAMPORT=$((CAMPORT+1))
echo "Settings can be modified after initial setup in /etc/systemd/system/cam${INUM}_$INSTANCE.service"
echo
while true; do
echo "Camera Resolution [default: 640x480]:"
read RESOLUTION
if [ -z $RESOLUTION ]
then
RESOLUTION="640x480"
break
elif [[ $RESOLUTION =~ ^[0-9]+x[0-9]+$ ]]
then
break
fi
echo "Invalid resolution"
done
echo "Selected camera resolution: $RESOLUTION" | log
echo "Camera Framerate (use 0 for ustreamer hardware) [default: 5]:"
read FRAMERATE
if [ -z "$FRAMERATE" ]; then
FRAMERATE=5
fi
echo "Selected camera framerate: $FRAMERATE" | log
#Need to check if this is a one-off install
if [ -n "$camopt" ]; then
write_camera
#Pi Cam setup, replace cam_INSTANCE with /dev/video0
if [ -n "$PI" ] && [ "$STREAMER" == ustreamer ]; then
echo SUBSYSTEM==\"video4linux\", ATTRS{name}==\"video0\", SYMLINK+=\"cam${INUM}_$INSTANCE\" >> /etc/udev/rules.d/99-octoprint.rule
fi
systemctl start cam${INUM}_$INSTANCE.service
systemctl enable cam${INUM}_$INSTANCE.service
systemctl daemon-reload
udevadm control --reload-rules
udevadm trigger
main_menu
fi
}