start refactoring to seperate dmx api, drivers and webinterface

This commit is contained in:
Sebastian Wiedenroth 2013-11-17 01:41:27 +01:00
parent 7188217bb3
commit bf5cede0ca
6 changed files with 177 additions and 146 deletions

110
anim.js
View file

@ -1,56 +1,62 @@
"use strict"
var ease = require('./easing.js').ease var ease = require('./easing.js').ease
var resolution = 25; var resolution = 25
exports.Anim = function() { function Anim() {
this.fx_stack = []; this.fx_stack = []
this.add = function(to, duration, options) {
var options = options || {};
var duration = duration || resolution;
options['easing'] = options['easing'] || 'linear';
this.fx_stack.push({'to': to, 'duration': duration, 'options': options});
return this;
}
this.delay = function(duration) {
return this.add({}, duration);
}
this.run = function(universe, onFinish) {
var config = {}
, t = 0
, d = 0
, a
;
var fx_stack = this.fx_stack;
var ani_setup = function() {
a = fx_stack.shift();
t = 0;
d = a.duration;
config = {}
for(var k in a.to) {
config[k] = {
'start': universe.get(k),
'end': a.to[k]
}
}
}
var ani_step = function() {
new_vals = {};
for(var k in config) {
new_vals[k] = Math.round(config[k].start + ease['linear'](t, 0, 1, d) * (config[k].end - config[k].start))
}
t = t + resolution;
universe.update(new_vals);
if(t > d) {
if(fx_stack.length > 0) {
ani_setup()
} else {
clearInterval(iid);
if(onFinish) onFinish();
}
}
}
ani_setup();
var iid = setInterval(ani_step, resolution);
}
} }
Anim.prototype.add = function(to, duration, options) {
var options = options || {}
var duration = duration || resolution
options['easing'] = options['easing'] || 'linear'
this.fx_stack.push({'to': to, 'duration': duration, 'options': options})
return this
}
Anim.prototype.delay = function(duration) {
return this.add({}, duration)
}
Anim.prototype.run = function(universe, onFinish) {
var config = {}
var t = 0
var d = 0
var a
var fx_stack = this.fx_stack;
var ani_setup = function() {
a = fx_stack.shift()
t = 0
d = a.duration
config = {}
for(var k in a.to) {
config[k] = {
'start': universe.get(k),
'end': a.to[k]
}
}
}
var ani_step = function() {
new_vals = {}
for(var k in config) {
new_vals[k] = Math.round(config[k].start + ease['linear'](t, 0, 1, d) * (config[k].end - config[k].start))
}
t = t + resolution
universe.update(new_vals)
if(t > d) {
if(fx_stack.length > 0) {
ani_setup()
} else {
clearInterval(iid)
if(onFinish) onFinish()
}
}
}
ani_setup()
var iid = setInterval(ani_step, resolution)
}
module.exports = Anim

41
dmx.js
View file

@ -1,27 +1,28 @@
var events = require('events') "use strict"
, config = require('./config.js')
, web = require('./web.js')
, setup = require('./setup.js').setup
, devices = require('./devices.js').devices
;
var util = require('util')
var EventEmitter = require('events').EventEmitter
var dmx = new events.EventEmitter(); function DMX() {
this.universes = {}
dmx.config = config; this.drivers = {}
dmx.setup = setup; this.registerDriver('null', require('./drivers/null'))
dmx.devices = devices; this.registerDriver('enttec-usb-dmx-pro', require('./drivers/enttec-usb-dmx-pro'))
dmx.drivers = {};
dmx.update = function(universe, update) {
dmx.drivers[universe].update(update);
dmx.emit('update', universe, update);
} }
for(var universe in setup.universes) { util.inherits(DMX, EventEmitter)
dmx.drivers[universe] = require('./drivers/' + setup.universes[universe].output.driver + '.js').init(setup.universes[universe].output.device);
DMX.prototype.registerDriver = function(name, module) {
this.drivers[name] = module
} }
DMX.prototype.addUniverse = function(name, driver, device_id) {
this.universes[name] = new this.drivers[driver](device_id)
}
web.init(dmx); DMX.prototype.update = function(universe, channels) {
this.universes[universe].update(channels)
this.emit('update', universe, channels)
}
module.exports = DMX

View file

@ -1,3 +1,5 @@
"use strict"
var FTDI = require('ftdi') var FTDI = require('ftdi')
var ENTTEC_PRO_DMX_STARTCODE = 0x00 var ENTTEC_PRO_DMX_STARTCODE = 0x00
@ -7,51 +9,52 @@ var ENTTEC_PRO_DMX_STARTCODE = 0x00
, ENTTEC_PRO_RECV_DMX_PKT = 0x05 , ENTTEC_PRO_RECV_DMX_PKT = 0x05
; ;
function EnttecUSBDMXPRO(device_id, cb) {
var self = this
cb = cb || function() {}
this.universe = new Buffer(512)
this.universe.fill(0)
exports.init = function(dev_id) { this.dev = new FTDI.FtdiDevice(device_id)
var send_universe = function(dev, universe) { this.dev.open({
var hdr = Buffer([
ENTTEC_PRO_START_OF_MSG,
ENTTEC_PRO_SEND_DMX_RQ,
(universe.length + 1) & 0xff,
((universe.length + 1) >> 8) & 0xff,
ENTTEC_PRO_DMX_STARTCODE
])
var msg = Buffer.concat([
hdr,
universe,
Buffer([ENTTEC_PRO_END_OF_MSG])
])
dev.write(msg)
}
var universe = new Buffer(512)
universe.fill(0)
var dev = new FTDI.FtdiDevice(dev_id)
dev.open({
'baudrate': 250000, 'baudrate': 250000,
'databits': 8, 'databits': 8,
'stopbits': 2, 'stopbits': 2,
'parity': 'none' 'parity': 'none'
}, function(err) { }, function(err) {
console.log(err) cb(err, device_id)
}) if(!err) {
self.send_universe()
this.update = function(u) {
for(var k in u) {
universe[k] = u[k]
} }
} })
this.get = function(c) {
return universe[c]
}
setInterval(function() {
send_universe(dev, universe);
}, 25)
return this;
} }
EnttecUSBDMXPRO.prototype.send_universe = function() {
var hdr = Buffer([
ENTTEC_PRO_START_OF_MSG,
ENTTEC_PRO_SEND_DMX_RQ,
(this.universe.length + 1) & 0xff,
((this.universe.length + 1) >> 8) & 0xff,
ENTTEC_PRO_DMX_STARTCODE
])
var msg = Buffer.concat([
hdr,
this.universe,
Buffer([ENTTEC_PRO_END_OF_MSG])
])
this.dev.write(msg)
}
EnttecUSBDMXPRO.prototype.update = function(u) {
for(var c in u) {
this.universe[c] = u[c]
}
this.send_universe()
}
EnttecUSBDMXPRO.prototype.get = function(c) {
return this.universe[c]
}
module.exports = EnttecUSBDMXPRO

View file

@ -1,19 +1,21 @@
exports.init = function(dev_id) { "use strict"
var universe = new Buffer(512)
universe.fill(0)
this.update = function(u) { function Null(device_id, cb) {
for(var k in u) { var self = this
universe[k] = u[k] cb = cb || function() {}
} this.universe = new Buffer(512)
} this.universe.fill(0)
this.get = function(k) {
return universe[k];
}
setInterval(function() {
console.log(universe);
}, 1000);
return this;
} }
Null.prototype.update = function(u) {
for(var c in u) {
this.universe[c] = u[c]
}
console.log(this.universe)
}
Null.prototype.get = function(c) {
return this.universe[c]
}
module.exports = Null

View file

@ -19,7 +19,7 @@
margin-bottom: 2em; margin-bottom: 2em;
} }
input[type=range]:after { input[type=range]:before {
content: attr(value); content: attr(value);
color: #eee; color: #eee;
font-family: monospace; font-family: monospace;
@ -27,6 +27,8 @@
width: 60px; width: 60px;
display: block; display: block;
color: #fff; color: #fff;
position: absolute;
margin-bottom: 2em;
} }
.device { .device {
clear: both; clear: both;
@ -125,7 +127,7 @@
<ul class="nav" id="myTab"> <ul class="nav" id="myTab">
<li class="active"><a href="#home" data-toggle="tab">Home</a></li> <li class="active"><a href="#home" data-toggle="tab">Home</a></li>
<li><a href="#sliders" data-toggle="tab">Sliders</a></li> <li><a href="#sliders" data-toggle="tab">Sliders</a></li>
<li><a href="#scripts" data-toggle="tab">Scripts</a></li> <!--<li><a href="#scripts" data-toggle="tab">Scripts</a></li>-->
</ul> </ul>
</div> </div>
</div> </div>

41
web.js
View file

@ -1,11 +1,20 @@
"use strict"
var http = require('http'), var http = require('http'),
path = require('path'), path = require('path'),
io = require('socket.io'), io = require('socket.io'),
fs = require('fs'), fs = require('fs'),
A = require('./anim.js').Anim A = require('./anim.js').Anim
; ;
exports.init = function(dmx) { var DMX = require('./dmx')
var config = require('./config.js')
, web = require('./web.js')
, setup = require('./setup.js').setup
, devices = require('./devices.js').devices
function DMXWeb(dmx) {
function handler (request, response) { function handler (request, response) {
var reqBody = ''; var reqBody = '';
@ -79,10 +88,10 @@ exports.init = function(dmx) {
var app = http.createServer(handler) var app = http.createServer(handler)
app.listen(dmx.config.port, '::', null, function() { app.listen(config.port, '::', null, function() {
try { try {
process.setgid(dmx.config.gid); process.setgid(config.gid);
process.setuid(dmx.config.uid); process.setuid(config.uid);
} catch (err) { } catch (err) {
console.log(err); console.log(err);
process.exit(1); process.exit(1);
@ -90,12 +99,12 @@ exports.init = function(dmx) {
}); });
io.listen(app).sockets.on('connection', function (socket) { io.listen(app).sockets.on('connection', function (socket) {
socket.emit('init', {'devices': dmx.devices, 'setup': dmx.setup}); socket.emit('init', {'devices': devices, 'setup': setup});
socket.on('request_refresh', function() { socket.on('request_refresh', function() {
for(var universe in dmx.setup.universes) { for(var universe in setup.universes) {
u = {} var u = {}
for(var i = 0; i < 256; i++) { for(var i = 0; i < 256; i++) {
u[i] = dmx.drivers[universe].get(i); u[i] = dmx.universes[universe].get(i);
} }
console.log('sending update...') console.log('sending update...')
console.log(u) console.log(u)
@ -113,8 +122,16 @@ exports.init = function(dmx) {
}); });
} }
var dmx = new DMX()
for(var universe in setup.universes) {
dmx.addUniverse(
universe,
setup.universes[universe].output.driver,
setup.universes[universe].output.device
)
}
var web = new DMXWeb(dmx)