1 | (function() |
||
2 | { |
||
3 | const fs = require('fs'); |
||
0 ignored issues
–
show
Backwards Compatibility
introduced
by
![]() |
|||
4 | const respawn = require('respawn'); |
||
0 ignored issues
–
show
|
|||
5 | const util = require('util'); |
||
0 ignored issues
–
show
|
|||
6 | const io = require('socket.io-client'); |
||
0 ignored issues
–
show
|
|||
7 | const assert = require('assert'); |
||
0 ignored issues
–
show
|
|||
8 | const Listener = require( 'Listener' ); |
||
0 ignored issues
–
show
|
|||
9 | |||
10 | var logger; |
||
11 | var defaults = |
||
12 | { |
||
13 | port: 8300, |
||
14 | wspath: '/mjpeg' |
||
15 | }; |
||
16 | |||
17 | class MjpgStreamer |
||
0 ignored issues
–
show
|
|||
18 | { |
||
19 | constructor( name, deps ) |
||
20 | { |
||
21 | logger = deps.logger; |
||
22 | |||
23 | logger.info( "Loaded Cockpit Plugin: MjpgStreamer" ); |
||
24 | |||
25 | this.globalBus = deps.globalEventLoop; |
||
26 | this.cockpitBus = deps.cockpit; |
||
27 | |||
28 | this.settings = {}; |
||
29 | this.camera = null; |
||
30 | |||
31 | this.supervisorLaunchOptions = |
||
32 | [ |
||
33 | "nice", |
||
34 | "-1", |
||
35 | "node", |
||
36 | require.resolve( 'mjpeg-video-server' ), |
||
37 | "-p", |
||
38 | defaults.port, |
||
39 | "-c", |
||
40 | "/etc/openrov/STAR_openrov_net.chained.crt", |
||
41 | "-k", |
||
42 | "/etc/openrov/star_openrov_net.key", |
||
43 | ]; |
||
44 | |||
45 | // Handle mock options |
||
46 | if( process.env.USE_MOCK === 'true' ) |
||
47 | { |
||
48 | if( process.env.MOCK_VIDEO_TYPE === "MJPEG" ) |
||
49 | { |
||
50 | logger.info( "Using MJPEG video format in Mock Mode."); |
||
51 | |||
52 | this.supervisorLaunchOptions.push( '-m' ); |
||
53 | this.supervisorLaunchOptions.push( 'true' ); |
||
54 | |||
55 | if( process.env.MOCK_VIDEO_HARDWARE === 'false' ) |
||
56 | { |
||
57 | logger.info( "Using actual MJPEG video source."); |
||
58 | |||
59 | this.supervisorLaunchOptions.push( '-h' ); |
||
60 | this.supervisorLaunchOptions.push( 'true' ); |
||
61 | } |
||
62 | else |
||
63 | { |
||
64 | logger.info( "Using mocked MJPEG video source."); |
||
65 | } |
||
66 | } |
||
67 | else |
||
68 | { |
||
69 | this.disabled = true; |
||
70 | return; |
||
71 | } |
||
72 | } |
||
73 | |||
74 | this.supervisor = io.connect( 'http://localhost:' + defaults.port, |
||
75 | { |
||
76 | path: defaults.wspath, |
||
77 | reconnection: true, |
||
78 | reconnectionAttempts: Infinity, |
||
79 | reconnectionDelay: 1000 |
||
80 | }); |
||
81 | |||
82 | this.svMonitor = respawn( this.supervisorLaunchOptions, |
||
83 | { |
||
84 | name: 'mjpeg-video-server', |
||
85 | env: |
||
86 | { |
||
87 | 'COCKPIT_PATH': process.env[ "COCKPIT_PATH" ], |
||
0 ignored issues
–
show
|
|||
88 | 'DEBUG': 'app*' |
||
89 | }, |
||
90 | maxRestarts: -1, |
||
91 | sleep: 1000 |
||
92 | }); |
||
93 | |||
94 | this.svMonitor.on( "stdout", (data) => |
||
0 ignored issues
–
show
'arrow function syntax (=>)' is only available in ES6 (use 'esversion: 6').
Generally using ECMAScript 6 specific syntax is fine if you are sure that it is already supported by all engines which are supposed to run this code. Further Reading: ![]() |
|||
95 | { |
||
96 | logger.debug( data.toString() ); |
||
97 | }); |
||
98 | |||
99 | this.svMonitor.on( "stderr", (data) => |
||
0 ignored issues
–
show
'arrow function syntax (=>)' is only available in ES6 (use 'esversion: 6').
Generally using ECMAScript 6 specific syntax is fine if you are sure that it is already supported by all engines which are supposed to run this code. Further Reading: ![]() |
|||
100 | { |
||
101 | logger.debug( data.toString() ); |
||
102 | }); |
||
103 | |||
104 | // Set up listeners |
||
105 | this.listeners = |
||
106 | { |
||
107 | settings: new Listener( this.globalBus, 'settings-change.mjpegVideo', true, (settings) => |
||
0 ignored issues
–
show
'arrow function syntax (=>)' is only available in ES6 (use 'esversion: 6').
Generally using ECMAScript 6 specific syntax is fine if you are sure that it is already supported by all engines which are supposed to run this code. Further Reading: ![]() |
|||
108 | { |
||
109 | try |
||
110 | { |
||
111 | // Check for settings changes |
||
112 | assert.notDeepEqual( settings.mjpegVideo, this.settings ); |
||
113 | |||
114 | // Update settings |
||
115 | this.settings = settings.mjpegVideo; |
||
116 | |||
117 | logger.info( `Updating MJPEG streamer settings to: \n${this.settings}` ); |
||
0 ignored issues
–
show
'template literal syntax' is only available in ES6 (use 'esversion: 6').
Generally using ECMAScript 6 specific syntax is fine if you are sure that it is already supported by all engines which are supposed to run this code. Further Reading: ![]() |
|||
118 | |||
119 | // Send update to supervisor so it restarts the stream |
||
120 | this.supervisor.emit( "updateSettings", this.settings ); |
||
121 | } |
||
122 | catch( err ) |
||
123 | { |
||
124 | // Do nothing |
||
125 | } |
||
126 | }), |
||
127 | |||
128 | scanForCameras: new Listener( this.cockpitBus, "plugin.mjpegVideo.scanForCameras", false, () => |
||
0 ignored issues
–
show
'arrow function syntax (=>)' is only available in ES6 (use 'esversion: 6').
Generally using ECMAScript 6 specific syntax is fine if you are sure that it is already supported by all engines which are supposed to run this code. Further Reading: ![]() |
|||
129 | { |
||
130 | logger.info( "Scanning" ); |
||
131 | this.supervisor.emit( "scan" ); |
||
132 | }), |
||
133 | |||
134 | svConnect: new Listener( this.supervisor, 'connect', false, () => |
||
0 ignored issues
–
show
'arrow function syntax (=>)' is only available in ES6 (use 'esversion: 6').
Generally using ECMAScript 6 specific syntax is fine if you are sure that it is already supported by all engines which are supposed to run this code. Further Reading: ![]() |
|||
135 | { |
||
136 | logger.info( 'Successfully connected to mjpg-streamer supervisor' ); |
||
137 | |||
138 | // Start listening for settings changes (gets the latest settings) |
||
139 | this.listeners.settings.enable(); |
||
140 | }), |
||
141 | |||
142 | svDisconnect: new Listener( this.supervisor, 'disconnect', false, function() |
||
143 | { |
||
144 | logger.info( 'Disconnected from mjpg-streamer supervisor' ); |
||
145 | }), |
||
146 | |||
147 | svError: new Listener( this.supervisor, 'error', false, function(err) |
||
148 | { |
||
149 | logger.error(err, 'Mjpg-streamer supervisor connection error' ); |
||
150 | }), |
||
151 | |||
152 | svReconnect: new Listener( this.supervisor, 'reconnect', false, function() |
||
153 | { |
||
154 | logger.info('Reconnecting to mjpg-streamer supervisor...'); |
||
155 | }), |
||
156 | |||
157 | svStreamRegistration: new Listener( this.supervisor, 'stream.registration', false, ( serial, info ) => |
||
0 ignored issues
–
show
'arrow function syntax (=>)' is only available in ES6 (use 'esversion: 6').
Generally using ECMAScript 6 specific syntax is fine if you are sure that it is already supported by all engines which are supposed to run this code. Further Reading: ![]() |
|||
158 | { |
||
159 | logger.info('Stream Registration: ' + JSON.stringify(info) ); |
||
160 | |||
161 | this.globalBus.emit( 'CameraRegistration', |
||
162 | { |
||
163 | location: "forward", // TODO: Lookup location based on serial ID |
||
164 | videoMimeType: "video/x-motion-jpeg", |
||
165 | resolution: info.resolution, |
||
166 | framerate: info.framerate, |
||
167 | wspath: "", |
||
168 | relativeServiceUrl: `:${info.port}`, |
||
0 ignored issues
–
show
'template literal syntax' is only available in ES6 (use 'esversion: 6').
Generally using ECMAScript 6 specific syntax is fine if you are sure that it is already supported by all engines which are supposed to run this code. Further Reading: ![]() |
|||
169 | sourcePort: info.port, |
||
170 | sourceAddress: "", |
||
171 | connectionType: info.connectionType |
||
172 | }); |
||
173 | }) |
||
174 | } |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
175 | } |
||
176 | |||
177 | start() |
||
178 | { |
||
179 | if( this.disabled ) |
||
180 | { |
||
181 | return; |
||
182 | } |
||
183 | |||
184 | // Enable listeners |
||
185 | this.listeners.svConnect.enable(); |
||
186 | this.listeners.svDisconnect.enable(); |
||
187 | this.listeners.svError.enable(); |
||
188 | this.listeners.svReconnect.enable(); |
||
189 | this.listeners.svStreamRegistration.enable(); |
||
190 | |||
191 | this.listeners.scanForCameras.enable(); |
||
192 | |||
193 | // Start the supervisor process |
||
194 | this.svMonitor.start(); |
||
195 | } |
||
196 | |||
197 | stop() |
||
198 | { |
||
199 | if( this.disabled ) |
||
200 | { |
||
201 | return; |
||
202 | } |
||
203 | |||
204 | // Stop the supervisor process |
||
205 | this.svMonitor.stop(); |
||
206 | |||
207 | // Disable all listeners |
||
208 | for( var listener in this.listeners ) |
||
209 | { |
||
210 | if( this.listeners.hasOwnProperty( listener ) ) |
||
211 | { |
||
212 | listener.disable(); |
||
213 | } |
||
214 | } |
||
215 | } |
||
216 | |||
217 | getSettingSchema() |
||
218 | { |
||
219 | return [ |
||
220 | { |
||
221 | 'title': 'MJPEG Video', |
||
222 | 'type': 'object', |
||
223 | 'id': 'mjpegVideo', |
||
224 | 'category' : 'video', |
||
225 | |||
226 | 'properties': { |
||
227 | 'framerate': |
||
228 | { |
||
229 | 'type': 'string', |
||
230 | 'enum': |
||
231 | [ |
||
232 | '30', |
||
233 | '15', |
||
234 | '10' |
||
235 | ], |
||
236 | 'title': 'Framerate (FPS)', |
||
237 | 'default': '30' |
||
238 | }, |
||
239 | 'resolution': |
||
240 | { |
||
241 | 'type': 'string', |
||
242 | 'enum': |
||
243 | [ |
||
244 | '1920x1080', |
||
245 | '1280x720', |
||
246 | '800x600', |
||
247 | '640x480', |
||
248 | '352x288', |
||
249 | '320x240', |
||
250 | '176x144', |
||
251 | '160x120' |
||
252 | ], |
||
253 | 'title': 'Resolution', |
||
254 | 'default': '800x600' |
||
255 | } |
||
256 | }, |
||
257 | |||
258 | 'required': |
||
259 | [ |
||
260 | 'framerate', // Framerate setting for camera |
||
261 | 'resolution' // Resolution setting for camera |
||
262 | ] |
||
263 | }]; |
||
264 | } |
||
265 | } |
||
266 | |||
267 | module.exports = function( name, deps ) |
||
268 | { |
||
269 | if( process.env.PRODUCTID == "trident" ) |
||
270 | { |
||
271 | deps.logger.debug( "MjpgStreamer Not supported on trident" ); |
||
272 | return {}; |
||
273 | } |
||
274 | |||
275 | return new MjpgStreamer( name, deps ); |
||
276 | }; |
||
277 | }()); |