-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontrolCamera.sh
executable file
·225 lines (180 loc) · 10.5 KB
/
controlCamera.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
#!/bin/bash
#===============================================================================
#
# FILE: controlCamera.sh
#
# USAGE: ./controlCamera.sh
#
# DESCRIPTION: This script will use curl to attempt to control an ONVIF camera
#
# REQUIREMENTS: curl, xml2, Linux
# BUGS: Probably
# AUTHOR: Christopher Hubbard (CSH), chubbard@iwillfearnoevil.com
# ORGANIZATION: Home
# CREATED: 01/09/2024 11:07:52 AM
# REVISION: Amanda
#===============================================================================
#set -o nounset # Treat unset variables as an error
#set -o pipefai # Any non-zero exits in pipes fail
#set -e # Any non-zero exit is a failure
#canonicalpath=$(readlink -f $0) # Breaks Mac due to readlink differences
#canonicaldirname=$(dirname ${canonicalpath}/..) # Breaks Mac
#samedirname=$(dirname ${canonicalpath}) # Breaks Mac
usage() {
cat << EOF
This script will attempt to control a generic ONVIF camera. It is assumed the camera
is online, and you know your login information.
Values are set in the settings.cfg file
The script ATTEMPTS to find your profile for ONVIF, however if it is already known, add
it and skip that discovery attempt.
The horizontal and vertical values are default values of 0.1, however if the camera
does not respond to that small of a value, attempt 0.5 for each.
When in doubt, cat your response xml and pipe it through xml2 looking for clues
to what your camera was expecting
Options:
usage | -h show this help screen
left move left
right move right
up move up
down move down
Example:
$0 up
EOF
}
function verifyDeps() {
# Dont even bother running if we do not have the binaries that we need
needed="curl xml2 grep sed"
for i in ${needed} ; do
type $i >/dev/null 2>&1
if [[ $? -eq 1 ]]; then
echo "FATAL - Missing manditory component: $i"
exit1
fi
done
}
function zoomInTemplate() {
DIR="<s:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>${CONTROL}</ProfileToken><Velocity><Zoom x=\"${Z_IN}\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Velocity></ContinuousMove></s:Body></s:Envelope>"
}
function zoomOutTemplate() {
DIR="<s:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>${CONTROL}</ProfileToken><Velocity><Zoom x=\"${Z_OUT}\" xmlns=\"http://www.onvif.org/ver10/schema\"/></Velocity></ContinuousMove></s:Body></s:Envelope>"
}
function stopTemplate() {
#DIR="<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\"><s:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><Stop xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>${CONTROL}</ProfileToken><PanTilt>true</PanTilt><Zoom>false</Zoom></Stop></s:Body></s:Envelope>"
#DIR="<s:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><Stop xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>${CONTROL}</ProfileToken><PanTilt>true</PanTilt><Zoom>false</Zoom></Stop></s:Body></s:Envelope>"
#DIR="<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Stop xmlns="http://www.onvif.org/ver20/ptz/wsdl"><ProfileToken>' . $profileToken . '</ProfileToken><PanTilt>true</PanTilt><Zoom>false</Zoom></Stop></s:Body></s:Envelope>
DIR="<s:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><Stop xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>${CONTROL}</ProfileToken><PanTilt>true</PanTilt><Zoom>false</Zoom></Stop></s:Body></s:Envelope>"
DIR2="<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\"><s:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>${CONTROL}</ProfileToken><Velocity><PanTilt xmlns=\"http://www.onvif.org/ver10/schema\" x=\"0\" y=\"0\"/></Velocity></ContinuousMove></s:Body></s:Envelope>"
}
function capabilitiesTemplate() {
DIR="<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\"> <s:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"> <GetCapabilities xmlns=\"http://www.onvif.org/ver10/device/wsdl\"> <Category>All</Category> </GetCapabilities> </s:Body> </s:Envelope>"
}
function profileTemplate() {
DIR="<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\"> <s:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"> <GetProfiles xmlns=\"http://www.onvif.org/ver10/media/wsdl\"/> </s:Body> </s:Envelope>"
}
function horoTemplate() {
DIR="<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\"><s:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"><ProfileToken>${CONTROL}</ProfileToken><Velocity><PanTilt xmlns=\"http://www.onvif.org/ver10/schema\" x=\"${DIRECTION}${HORO}\" y=\"0\"/></Velocity></ContinuousMove></s:Body></s:Envelope>"
}
function vertTempate() {
DIR="<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\"> <s:Body xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"> <ContinuousMove xmlns=\"http://www.onvif.org/ver20/ptz/wsdl\"> <ProfileToken>${CONTROL}</ProfileToken> <Velocity> <PanTilt xmlns=\"http://www.onvif.org/ver10/schema\" x=\"0\" y=\"${DIRECTION}${VIRT}\"/></Velocity></ContinuousMove></s:Body></s:Envelope>"
}
########### End of templatized XML
function setHoro() {
echo "Missing Left Right move parameters. Setting defaults"
echo "HORO='0.1'" >> ./settings.cfg
}
function setVirt() {
echo "Missing Up Down move parameters. Setting defaults"
echo "VIRT='0.1'" >> ./settings.cfg
}
function findCapabilities() {
capabilitiesTemplate
curl -s -X POST "http://${HOST}:${PORT}/onvif/media_service" -u ${USER}:${PASS} -H "Content-Type: application/soap+xml; charset=utf-8" -H "SOAPAction: http://www.onvif.org/ver10/media/wsdl/GetCapabilities" --data "$(echo ${DIR})" > ./responses/findCapabilities.xml
}
function findProfile() {
profileTemplate
PROFILES=$(curl -s -X POST "http://${HOST}:${PORT}/onvif/media_service" -u ${USER}:${PASS} -H "Content-Type: application/soap+xml; charset=utf-8" -H "SOAPAction: http://www.onvif.org/ver10/media/wsdl/GetProfiles" --data "$(echo ${DIR})" > ./responses/getProfilesResponse.xml)
CONTROL=$(cat ./responses/getProfilesResponse.xml | xml2 | grep 'Profiles\/tt:Name=' | sed 's/.*.=//')
echo -e "Found profiles adding the first one to your settings.cfg:\n${CONTROL}"
CONT_SINGLE=$(echo -e "${CONTROL}" | head -1)
echo -e "CONTROL=${CONT_SINGLE}" >> ./settings.cfg
}
############## end of finding information
function moveLeft() {
DIRECTION='-'
horoTemplate
curl -s -X POST "http://${HOST}:${PORT}/onvif/device_service" -u ${USER}:${PASS} -H "Content-Type: application/soap+xml; charset=utf-8" -H "SOAPAction: http://www.onvif.org/ver10/media/wsdl/ContinuousMove" --data "$(echo ${DIR})" > ./responses/moveLeft.xml
}
function moveRight() {
DIRECTION=''
horoTemplate
curl -s -X POST "http://${HOST}:${PORT}/onvif/device_service" -u ${USER}:${PASS} -H "Content-Type: application/soap+xml; charset=utf-8" -H "SOAPAction: http://www.onvif.org/ver10/media/wsdl/ContinuousMove" --data "$(echo ${DIR})" > ./responses/moveRight.xml
}
function moveUp() {
DIRECTION=''
vertTempate
curl -s -X POST "http://${HOST}:${PORT}/onvif/device_service" -u ${USER}:${PASS} -H "Content-Type: application/soap+xml; charset=utf-8" -H "SOAPAction: http://www.onvif.org/ver10/media/wsdl/ContinuousMove" --data "$(echo ${DIR})" > ./responses/moveUp.xml
}
function moveDown() {
DIRECTION='-'
vertTempate
curl -s -X POST "http://${HOST}:${PORT}/onvif/device_service" -u ${USER}:${PASS} -H "Content-Type: application/soap+xml; charset=utf-8" -H "SOAPAction: http://www.onvif.org/ver10/media/wsdl/ContinuousMove" --data "$(echo ${DIR})" > ./responses/moveDown.xml
}
function stopMove() {
stopTemplate
curl -s -X POST "http://${HOST}:${PORT}/onvif/PTZ" -u ${USER}:${PASS} -H "Content-Type: application/soap+xml; charset=utf-8" -H "SOAPAction: http://www.onvif.org/ver20/media/wsdl/ContinuousMove" --data "$(echo ${DIR})" > ./responses/stopMove.xml
curl -s -X POST "http://${HOST}:${PORT}/onvif/PTZ" -u ${USER}:${PASS} -H "Content-Type: application/soap+xml; charset=utf-8" -H "SOAPAction: http://www.onvif.org/ver20/media/wsdl/ContinuousMove" --data "$(echo ${DIR2})" > ./responses/stopMove2.xml
}
function zoomIn() {
zoomInTemplate
curl -s -X POST "http://${HOST}:${PORT}/onvif/PTZ" -u ${USER}:${PASS} -H "Content-Type: application/soap+xml; charset=utf-8" -H "SOAPAction: http://www.onvif.org/ver20/media/wsdl/ContinuousMove" --data "$(echo ${DIR})" > ./responses/zoomIn.xml
}
function zoomOut() {
zoomOutTemplate
curl -s -X POST "http://${HOST}:${PORT}/onvif/PTZ" -u ${USER}:${PASS} -H "Content-Type: application/soap+xml; charset=utf-8" -H "SOAPAction: http://www.onvif.org/ver20/media/wsdl/ContinuousMove" --data "$(echo ${DIR})" > ./responses/zoomOut.xml
}
# Make sure we have our binaries before attempting work
verifyDeps
# Where we store our XML responses
if [[ ! -e ./responses ]]; then
mkdir responses
fi
if [[ -e settings.cfg ]]; then
. ./settings.cfg
echo "Loaded existing config settings"
else
echo "Cannot find settings file (./settings.cfg)"
exit 1
fi
# Make sure our settings.cfg is complete
if [[ -z ${CONTROL} ]] ; then
findProfile
else
echo "Using Profile control ${CONTROL}"
fi
if [[ -z ${HORO} ]]; then
setHoro
else
echo "Left Right movement set at ${HORO} steps"
fi
if [[ -z ${VIRT} ]]; then
setVirt
else
echo "Up Down movement set at ${VIRT} steps"
fi
if [[ ! -e ./responses/findCapabilities.xml ]]; then
findCapabilities
echo "Grabbing the camera capabilities if possible"
fi
# Reinclude our settings with anything that we have set
. ./settings.cfg
case ${1} in
usage|-h) usage; exit 0 ;;
l*) moveLeft ; sleep ${PAUSE} ; stopMove ;;
r*) moveRight; sleep ${PAUSE} ; stopMove ;;
u*) moveUp ; sleep ${PAUSE} ; stopMove ;;
d*) moveDown ; sleep ${PAUSE} ; stopMove ;;
s*) stopMove ;;
zoomIn) zoomIn;;
zoomOut) zoomOut;;
*) echo "Missing valid command to do" ;;
esac