Skip to content

Instantly share code, notes, and snippets.

@hannes
Created April 15, 2015 14:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hannes/4482915d7e51709f379f to your computer and use it in GitHub Desktop.
Save hannes/4482915d7e51709f379f to your computer and use it in GitHub Desktop.
var https = require('https');
var fs = require('fs');
var net = require('net');
var WebSocketServer = require('websocket').server;
// this works on ubuntu if you set chmod 755 on those files and the private dir
var httpsopts = {
key: fs.readFileSync('/etc/ssl/private/ssl-cert-snakeoil.key'),
cert: fs.readFileSync('/etc/ssl/certs/ssl-cert-snakeoil.pem')
};
var videosock = undefined;
var server = https.createServer(httpsopts, function (req, res) {
// TODO: check video socket
// TODO: map URL and camera
res.setHeader('Content-Type', 'video/mp4');
res.writeHead(200);
videosock.pipe(res);
});
server.listen(7443, function(err){
if (err) console.err(err)
});
wss = new WebSocketServer({
httpServer: server,
autoAcceptConnections: true
});
function hexhex() {
return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
var mid = 42;
function respond(conn, fn, re, pl, irt) {
var resp = {'from': 'UniFiVideo', 'to': 'ubnt_avclient', 'responseExpected': re, 'functionName': fn,
'messageId': mid++, 'inResponseTo': irt, 'payload': pl };
conn.sendBytes(new Buffer(JSON.stringify(resp)));
}
function send_heartbeat(conn) {
respond(conn, '__av_internal____heartbeat__', false, undefined, 0);
}
var serverport = 0;
var server = net.createServer(function (cs) {
videosock = cs;
}).listen(0);
server.on('listening', function() {
serverport = server.address().port;
})
// you can try changing some picture settings here
var camsettings = {'focusPosition': 0, 'aeMode': 'auto', 'saturation': 50, 'wdr': 1,
'zoomPosition': 0, 'brightness': 70, 'denoise': 50, 'sharpness': 50, 'mirror': 0,
'focusMode': 'ztrig', 'contrast': 50, 'flip': 0, 'irLedMode': 'auto', 'hue': 50, 'irLedLevel': 215};
// if you want dates etc on picture
var osdsettings = {'_1': {'enableDate': 0, 'enableLogo': 0, 'tag': ''}, '_2': {'enableDate': 0, 'enableLogo': 0, 'tag': ''}, '_3': {'enableDate': 0, 'enableLogo': 0, 'tag': ''}, '_4': {'enableDate': 0, 'enableLogo': 0, 'tag': ''}};
// these are best left alone
var videosettings = {'video': {'video1': {'bitRateVbrMin': undefined, 'bitRateVbrMax': undefined, 'isCbr': false,
'avSerializer': {'streamName': 'video1', 'type': 'flv', 'destinations': ['###WILLGETOVERWRITTENLATER###']},
'fps': undefined, 'bitRateCbrAvg': undefined}, 'bitrate': undefined, 'video3': undefined, 'fps': undefined, 'video2': undefined}};
wss.on('connect', function(conn) {
var auth = {username: 'ubnt', stage: 0, authId: hexhex(),
challenge: hexhex(), completionCode: 2};
var mac = '';
var serverip = '';
conn.on('message', function(msg) {
var jm = JSON.parse(msg.binaryData.toString('utf8'));
switch (jm.functionName) {
case 'ubnt_avclient_hello':
mac = jm.payload.mac;
console.log(mac, 'hello');
// so we know how the cam reached us...
serverip = jm.payload.connectionHost;
respond(conn, 'ubnt_avclient_hello', false, {protocolVersion: 36, controllerName: 'nodejs'}, jm.messageId);
respond(conn, 'ubnt_avclient_auth', true, auth, undefined);
break;
case 'ubnt_avclient_auth':
auth.commonSecret = jm.payload.commonSecret;
auth.completionCode = 0;
respond(conn, 'ubnt_avclient_auth', false, auth, 0);
console.log(mac, 'authenticated');
// setup heartbeat
setInterval(send_heartbeat, 5000, conn);
// setup camera and stream
respond(conn, 'ChangeIspSettings', true, camsettings, 0);
videosettings.video.video1.avSerializer.destinations[0] =
'tcp://' + serverip + ':' + serverport + '?retryInterval=1&connectTimeout=30';
respond(conn, 'ChangeVideoSettings', true, videosettings, 0);
respond(conn, 'ChangeOsdSettings', true, osdsettings, 0);
respond(conn, 'ChangeDeviceSettings', true, {name: 'nodedrone'}, 0);
case 'ubnt_avclient_timeSync':
var ts = new Date().getTime();
respond(conn, 'ubnt_avclient_timeSync', false, {t1 : ts, t2: ts}, jm.messageId);
break;
case 'ChangeOsdSettings':
case 'EventStreamingStatus':
case 'EventAnalyticsMotion':
case 'ChangeVideoSettings':
case 'ChangeDeviceSettings':
case '__av_internal____heartbeat__':
break;
default:
console.log(mac, 'unknown message ', jm.functionName);
break;
}
});
conn.on('close', function(reasonCode, description) {
console.log('client disconnected.');
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment