Created
April 15, 2015 14:46
-
-
Save hannes/4482915d7e51709f379f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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