-
Notifications
You must be signed in to change notification settings - Fork 240
/
example3.js
224 lines (197 loc) · 6.04 KB
/
example3.js
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
/**
* NodeJS ONVIF PTZ and Presets Test
*
* Created by Roger Hardiman <opensource@rjh.org.uk>
*
* Read the cursor keys and send ONVIF PTZ commands to the camera
*
* There are a few challenges to reading the keyboard
* Firstly there is no 'keyup' event. So we use a Timer to schedule an ONVIF
* Stop Command to be sent after a short delay.
* If we send a new 'move' command (eg change direction or keyboard
* auto-repeat) any pending Stop commands are no longer required and are
* cleared and a new Stop command is scheduled to be sent after a short delay.
*
* Secondly we need to handle auto-repeat if a key is held down so we pause
* and resume stdin.
*
* Finally we need to use the completion callbacks for ONVIF functions
* so that we only send a new ONVIF 'move' command after the previous one has
* finished to prevent overlapping commands.
*
* The program also sends Goto Preset commands.
* The program gets a list of ONVIF presets. Keys 1..9 are used to send
* Goto Preset on the first 9 preset commands.
*
* The GetPresets command is left as an asynchronous command
* and the presets list may come in some time after the StreamURI is displayed
*
*/
var HOSTNAME = '192.168.0.116',
PORT = 2020,
USERNAME = 'username',
PASSWORD = 'password',
STOP_DELAY_MS = 50;
var Cam = require('../lib/onvif').Cam;
var keypress = require('keypress');
new Cam({
hostname: HOSTNAME,
username: USERNAME,
password: PASSWORD,
port: PORT,
timeout: 10000
}, function CamFunc(err) {
if (err) {
console.log(err);
return;
}
var cam_obj = this;
var stop_timer;
var ignore_keypress = false;
var preset_names = [];
var preset_tokens = [];
cam_obj.getStreamUri({
protocol: 'RTSP'
}, // Completion callback function
// This callback is executed once we have a StreamUri
function(err, stream, xml) {
if (err) {
console.log(err);
return;
} else {
console.log('------------------------------');
console.log('Host: ' + HOSTNAME + ' Port: ' + PORT);
console.log('Stream: = ' + stream.uri);
console.log('------------------------------');
// start processing the keyboard
read_and_process_keyboard();
}
}
);
cam_obj.getPresets({}, // use 'default' profileToken
// Completion callback function
// This callback is executed once we have a list of presets
function(err, stream, xml) {
if (err) {
console.log("GetPreset Error " + err);
return;
} else {
// loop over the presets and populate the arrays
// Do this for the first 9 presets
console.log("GetPreset Reply");
var count = 1;
for (var item in stream) {
var name = item; //key
var token = stream[item]; //value
// It is possible to have a preset with a blank name so generate a name
if (name.length == 0) {name = 'no name (' + token + ')';}
preset_names.push(name);
preset_tokens.push(token);
// Show first 9 preset names to user
if (count < 9) {
console.log('Press key ' + count + ' for preset "' + name + '"');
count++;
}
}
}
}
);
function read_and_process_keyboard() {
// listen for the "keypress" events
keypress(process.stdin);
process.stdin.setRawMode(true);
process.stdin.resume();
console.log('');
console.log('Use Cursor Keys to move camera. + and - to zoom. q to quit');
// keypress handler
process.stdin.on('keypress', function(ch, key) {
/* Exit on 'q' or 'Q' or 'CTRL C' */
if ((key && key.ctrl && key.name == 'c')
|| (key && key.name == 'q')) {
process.exit();
}
if (ignore_keypress) {
return;
}
if (key) {
console.log('got "keypress"',key.name);
} else {
if (ch){console.log('got "keypress character"',ch);}
}
// On English keyboards '+' is "Shift and = key"
// Accept the "=" key as zoom in
if (key && key.name == 'up') {
move(0,1,0,'up');
} else if (key && key.name == 'down') {
move(0,-1,0,'down');
} else if (key && key.name == 'left') {
move(-1,0,0,'left');
} else if (key && key.name == 'right') {
move(1,0,0,'right');
} else if (ch && ch == '-') {
move(0,0,-1,'zoom out');
} else if (ch && ch == '+') {
move(0,0,1,'zoom in');
} else if (ch && ch == '=') {
move(0,0,1,'zoom in');
} else if (ch && ch >= '1' && ch <= '9') {
goto_preset(ch);
}
});
}
function move(x_speed, y_speed, zoom_speed, msg) {
// Step 1 - Turn off the keyboard processing (so keypresses do not buffer up)
// Step 2 - Clear any existing 'stop' timeouts. We will re-schedule a new 'stop' command in this function
// Step 3 - Send the Pan/Tilt/Zoom 'move' command.
// Step 4 - In the callback from the PTZ 'move' command we schedule the ONVIF Stop command to be executed after a short delay and re-enable the keyboard
// Pause keyboard processing
ignore_keypress = true;
// Clear any pending 'stop' commands
if (stop_timer) {clearTimeout(stop_timer);}
// Move the camera
console.log('sending move command ' + msg);
cam_obj.continuousMove({x: x_speed,
y: y_speed,
zoom: zoom_speed } ,
// completion callback function
function(err, stream, xml) {
if (err) {
console.log(err);
} else {
console.log('move command sent ' + msg);
// schedule a Stop command to run in the future
stop_timer = setTimeout(stop,STOP_DELAY_MS);
}
// Resume keyboard processing
ignore_keypress = false;
});
}
function stop() {
// send a stop command, stopping Pan/Tilt and stopping zoom
console.log('sending stop command');
cam_obj.stop({panTilt: true, zoom: true},
function(err,stream, xml){
if (err) {
console.log(err);
} else {
console.log('stop command sent');
}
});
}
function goto_preset(number) {
if (number > preset_names.length) {
console.log("No preset " + number);
return;
}
console.log('sending goto preset command ' + preset_names[number - 1]);
cam_obj.gotoPreset({ preset: preset_tokens[number - 1] } ,
// completion callback function
function(err, stream, xml) {
if (err) {
console.log(err);
} else {
console.log('goto preset command sent ');
}
});
}
});