rewrite webinterface to use express and cdn hosted bootstrap
This commit is contained in:
parent
bf5cede0ca
commit
4003ff812a
17 changed files with 166 additions and 9064 deletions
2
anim.js
2
anim.js
|
@ -39,7 +39,7 @@ Anim.prototype.run = function(universe, onFinish) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var ani_step = function() {
|
var ani_step = function() {
|
||||||
new_vals = {}
|
var new_vals = {}
|
||||||
for(var k in config) {
|
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))
|
new_vals[k] = Math.round(config[k].start + ease['linear'](t, 0, 1, d) * (config[k].end - config[k].start))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
// webserver configuration
|
|
||||||
|
|
||||||
// listen port
|
|
||||||
exports.port = 80;
|
|
||||||
|
|
||||||
// uid and gid to drop root priv.
|
|
||||||
exports.uid = 'light';
|
|
||||||
exports.gid = 'users';
|
|
11
devices.js
11
devices.js
|
@ -1,4 +1,10 @@
|
||||||
exports.devices = {
|
module.exports = {
|
||||||
|
'generic': {
|
||||||
|
channels: ['dimmer']
|
||||||
|
},
|
||||||
|
'showtec-multidim2': {
|
||||||
|
channels: ['1', '2', '3', '4']
|
||||||
|
},
|
||||||
'eurolite-led-bar': {
|
'eurolite-led-bar': {
|
||||||
channels: ['ctrl', 'dimmer', 'strobe', 'red0', 'green0', 'blue0', 'red1', 'green1', 'blue1', 'red2', 'green2', 'blue2'],
|
channels: ['ctrl', 'dimmer', 'strobe', 'red0', 'green0', 'blue0', 'red1', 'green1', 'blue1', 'red2', 'green2', 'blue2'],
|
||||||
ranges: {
|
ranges: {
|
||||||
|
@ -31,9 +37,6 @@ exports.devices = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'showtec-multidim2': {
|
|
||||||
channels: ['1', '2', '3', '4']
|
|
||||||
},
|
|
||||||
'stairville-led-par-56': {
|
'stairville-led-par-56': {
|
||||||
channels: ['ctrl', 'red', 'green', 'blue', 'speed'],
|
channels: ['ctrl', 'red', 'green', 'blue', 'speed'],
|
||||||
ranges: {
|
ranges: {
|
||||||
|
|
|
@ -1,7 +1,15 @@
|
||||||
exports.setup = {
|
module.exports = {
|
||||||
presets: [
|
"server": {
|
||||||
|
"listen_port": 8080,
|
||||||
|
"listen_host": "::",
|
||||||
|
|
||||||
|
// drop privileges to:
|
||||||
|
// "uid": "www-data",
|
||||||
|
// "gid": "www-data"
|
||||||
|
},
|
||||||
|
"presets": [
|
||||||
{
|
{
|
||||||
label: 'White',
|
label: "White",
|
||||||
values: {
|
values: {
|
||||||
'office': { 0:16, 1:255, 2:0, 3:255, 4: 255, 5:255, 15:16, 16:255, 17:0, 18:255, 19: 255, 20:255 }
|
'office': { 0:16, 1:255, 2:0, 3:255, 4: 255, 5:255, 15:16, 16:255, 17:0, 18:255, 19: 255, 20:255 }
|
||||||
}
|
}
|
||||||
|
@ -34,7 +42,8 @@ exports.setup = {
|
||||||
universes: {
|
universes: {
|
||||||
'office': {
|
'office': {
|
||||||
'output': {
|
'output': {
|
||||||
'driver': 'enttec-usb-dmx-pro',
|
// 'driver': 'enttec-usb-dmx-pro',
|
||||||
|
'driver': 'null',
|
||||||
'device': 0
|
'device': 0
|
||||||
},
|
},
|
||||||
'devices': [
|
'devices': [
|
109
dmx-web.js
Executable file
109
dmx-web.js
Executable file
|
@ -0,0 +1,109 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
"use strict"
|
||||||
|
|
||||||
|
var http = require('http')
|
||||||
|
var connect = require('connect')
|
||||||
|
var express = require('express')
|
||||||
|
var socketio = require('socket.io')
|
||||||
|
var program = require('commander')
|
||||||
|
var DMX = require('./dmx')
|
||||||
|
var A = DMX.Animation
|
||||||
|
|
||||||
|
program
|
||||||
|
.version("0.0.1")
|
||||||
|
.option('-c, --config <file>', 'Read config from file [/etc/dmx-web.json]', '/etc/dmx-web.json')
|
||||||
|
.parse(process.argv)
|
||||||
|
|
||||||
|
|
||||||
|
var config = require(program.config)
|
||||||
|
|
||||||
|
function DMXWeb() {
|
||||||
|
var app = express()
|
||||||
|
var server = http.createServer(app)
|
||||||
|
var io = socketio.listen(server)
|
||||||
|
|
||||||
|
var dmx = new DMX()
|
||||||
|
|
||||||
|
for(var universe in config.universes) {
|
||||||
|
dmx.addUniverse(
|
||||||
|
universe,
|
||||||
|
config.universes[universe].output.driver,
|
||||||
|
config.universes[universe].output.device
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var listen_port = config.server.listen_port || 8080
|
||||||
|
var listen_host = config.server.listen_host || '::'
|
||||||
|
|
||||||
|
server.listen(listen_port, listen_host, null, function() {
|
||||||
|
if(config.server.uid && config.server.gid) {
|
||||||
|
try {
|
||||||
|
process.setuid(config.server.uid)
|
||||||
|
process.setgid(config.server.gid)
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
io.set('log level', 1)
|
||||||
|
|
||||||
|
app.configure(function() {
|
||||||
|
app.use(connect.json())
|
||||||
|
})
|
||||||
|
|
||||||
|
app.get('/', function(req, res) {
|
||||||
|
res.sendfile(__dirname + '/index.html')
|
||||||
|
})
|
||||||
|
|
||||||
|
app.post('/animation/:universe', function(req, res) {
|
||||||
|
try {
|
||||||
|
var universe = dmx.universes[req.params.universe]
|
||||||
|
|
||||||
|
// preserve old states
|
||||||
|
var old = {}
|
||||||
|
for(var i = 0; i < 256; i++) {
|
||||||
|
old[i] = universe.get(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
var animation = new A()
|
||||||
|
for(var step in req.body) {
|
||||||
|
animation.add(
|
||||||
|
req.body[step].to,
|
||||||
|
req.body[step].duration || 0,
|
||||||
|
req.body[step].options || {}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
animation.add(old, 0)
|
||||||
|
animation.run(universe)
|
||||||
|
res.json({"success": true})
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e)
|
||||||
|
res.json({"error": String(e)})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
io.sockets.on('connection', function(socket) {
|
||||||
|
socket.emit('init', {'devices': DMX.devices, 'setup': config})
|
||||||
|
|
||||||
|
socket.on('request_refresh', function() {
|
||||||
|
for(var universe in config.universes) {
|
||||||
|
var u = {}
|
||||||
|
for(var i = 0; i < 256; i++) {
|
||||||
|
u[i] = dmx.universes[universe].get(i)
|
||||||
|
}
|
||||||
|
socket.emit('update', universe, u)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
socket.on('update', function(universe, update) {
|
||||||
|
dmx.update(universe, update)
|
||||||
|
})
|
||||||
|
|
||||||
|
dmx.on('update', function(universe, update) {
|
||||||
|
socket.emit('update', universe, update)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
DMXWeb()
|
4
dmx.js
4
dmx.js
|
@ -6,12 +6,16 @@ var EventEmitter = require('events').EventEmitter
|
||||||
function DMX() {
|
function DMX() {
|
||||||
this.universes = {}
|
this.universes = {}
|
||||||
this.drivers = {}
|
this.drivers = {}
|
||||||
|
|
||||||
this.registerDriver('null', require('./drivers/null'))
|
this.registerDriver('null', require('./drivers/null'))
|
||||||
this.registerDriver('enttec-usb-dmx-pro', require('./drivers/enttec-usb-dmx-pro'))
|
this.registerDriver('enttec-usb-dmx-pro', require('./drivers/enttec-usb-dmx-pro'))
|
||||||
}
|
}
|
||||||
|
|
||||||
util.inherits(DMX, EventEmitter)
|
util.inherits(DMX, EventEmitter)
|
||||||
|
|
||||||
|
DMX.devices = require('./devices')
|
||||||
|
DMX.Animation = require('./anim')
|
||||||
|
|
||||||
DMX.prototype.registerDriver = function(name, module) {
|
DMX.prototype.registerDriver = function(name, module) {
|
||||||
this.drivers[name] = module
|
this.drivers[name] = module
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
<title>DMX Lichtschalter</title>
|
<title>DMX Lichtschalter</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet">
|
||||||
<link href="/static/bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet">
|
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
background: #222;
|
background: #222;
|
||||||
|
@ -45,7 +44,7 @@
|
||||||
</style>
|
</style>
|
||||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
|
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
|
||||||
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js"></script>
|
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js"></script>
|
||||||
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
|
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
|
||||||
<script src="/socket.io/socket.io.js"></script>
|
<script src="/socket.io/socket.io.js"></script>
|
||||||
<script>
|
<script>
|
||||||
function get_html_id(universe, channel) {
|
function get_html_id(universe, channel) {
|
||||||
|
|
54
package.json
54
package.json
|
@ -1,26 +1,32 @@
|
||||||
{
|
{
|
||||||
"name": "dmx",
|
"name": "dmx",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"author": "Sebastian Wiedenroth <wiedi@frubar.net>",
|
"author": "Sebastian Wiedenroth <wiedi@frubar.net>",
|
||||||
"description": "DMX library and webservice",
|
"description": "DMX library and webservice",
|
||||||
"url": "https://github.com/wiedi/node-dmx",
|
"url": "https://github.com/wiedi/node-dmx",
|
||||||
"main": "dmx.js",
|
"main": "dmx.js",
|
||||||
"repository": {
|
"bin": {
|
||||||
"type": "git",
|
"dmx-web": "./dmx-web.js"
|
||||||
"url": "https://github.com/wiedi/node-dmx.git"
|
},
|
||||||
},
|
"repository": {
|
||||||
"keywords": [
|
"type": "git",
|
||||||
"DMX",
|
"url": "https://github.com/wiedi/node-dmx.git"
|
||||||
"light control"
|
},
|
||||||
],
|
"keywords": [
|
||||||
"dependencies": {
|
"DMX",
|
||||||
"ftdi": "1.0.x",
|
"light control"
|
||||||
"socket.io": "0.9.x"
|
],
|
||||||
},
|
"dependencies": {
|
||||||
"licenses": [
|
"ftdi": "1.0.x",
|
||||||
{
|
"socket.io": "0.9.x",
|
||||||
"name": "MIT",
|
"connect": "2.11.x",
|
||||||
"url": "http://www.opensource.org/licenses/mit-license.php"
|
"express": "3.4.x",
|
||||||
}
|
"commander": "2.0.x"
|
||||||
]
|
},
|
||||||
|
"licenses": [
|
||||||
|
{
|
||||||
|
"name": "MIT",
|
||||||
|
"url": "http://www.opensource.org/licenses/mit-license.php"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
1058
static/bootstrap/css/bootstrap-responsive.css
vendored
1058
static/bootstrap/css/bootstrap-responsive.css
vendored
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
5774
static/bootstrap/css/bootstrap.css
vendored
5774
static/bootstrap/css/bootstrap.css
vendored
File diff suppressed because it is too large
Load diff
9
static/bootstrap/css/bootstrap.min.css
vendored
9
static/bootstrap/css/bootstrap.min.css
vendored
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 8.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 12 KiB |
2027
static/bootstrap/js/bootstrap.js
vendored
2027
static/bootstrap/js/bootstrap.js
vendored
File diff suppressed because it is too large
Load diff
6
static/bootstrap/js/bootstrap.min.js
vendored
6
static/bootstrap/js/bootstrap.min.js
vendored
File diff suppressed because one or more lines are too long
137
web.js
137
web.js
|
@ -1,137 +0,0 @@
|
||||||
"use strict"
|
|
||||||
|
|
||||||
var http = require('http'),
|
|
||||||
path = require('path'),
|
|
||||||
io = require('socket.io'),
|
|
||||||
fs = require('fs'),
|
|
||||||
A = require('./anim.js').Anim
|
|
||||||
;
|
|
||||||
|
|
||||||
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) {
|
|
||||||
var reqBody = '';
|
|
||||||
|
|
||||||
request.on("data", function (chunk) {
|
|
||||||
reqBody += chunk;
|
|
||||||
});
|
|
||||||
|
|
||||||
request.on("end", function () {
|
|
||||||
var urlData = require('url').parse(request.url),
|
|
||||||
urlPath = urlData.pathname.split('/');
|
|
||||||
|
|
||||||
if(urlPath.length == 3 && urlPath[1] == 'animation') {
|
|
||||||
try {
|
|
||||||
// save old states
|
|
||||||
var universe = dmx.drivers[urlPath[2]], old = {}, black = {};
|
|
||||||
for(var i = 0; i < 256; i++) {
|
|
||||||
old[i] = universe.get(i);
|
|
||||||
black[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var jsonAnim = JSON.parse(reqBody), animation = new A();
|
|
||||||
for(var step in jsonAnim) {
|
|
||||||
animation.add(jsonAnim[step].to, jsonAnim[step].duration || 0, jsonAnim[step].options || {});
|
|
||||||
}
|
|
||||||
|
|
||||||
animation.add(old, 0);
|
|
||||||
animation.run(universe);
|
|
||||||
response.write('{ "success": true }');
|
|
||||||
} catch(e) {
|
|
||||||
response.write('{ "error": "broken json" }');
|
|
||||||
}
|
|
||||||
|
|
||||||
response.end();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var filePath = '.' + urlData.pathname;
|
|
||||||
if (filePath == './')
|
|
||||||
filePath = './index.html';
|
|
||||||
|
|
||||||
var extname = path.extname(filePath);
|
|
||||||
var contentType = 'text/html';
|
|
||||||
switch (extname) {
|
|
||||||
case '.js': contentType = 'text/javascript'; break;
|
|
||||||
case '.css': contentType = 'text/css'; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.exists(filePath, function(exists) {
|
|
||||||
if(!exists) {
|
|
||||||
console.log('404: ' + request.url)
|
|
||||||
response.writeHead(404);
|
|
||||||
response.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.readFile(filePath, function(error, content) {
|
|
||||||
if (error) {
|
|
||||||
console.log('500: ' + request.url)
|
|
||||||
response.writeHead(500);
|
|
||||||
response.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
response.writeHead(200, { 'Content-Type': contentType });
|
|
||||||
response.end(content, 'utf-8');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var app = http.createServer(handler)
|
|
||||||
app.listen(config.port, '::', null, function() {
|
|
||||||
try {
|
|
||||||
process.setgid(config.gid);
|
|
||||||
process.setuid(config.uid);
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
io.listen(app).sockets.on('connection', function (socket) {
|
|
||||||
socket.emit('init', {'devices': devices, 'setup': setup});
|
|
||||||
socket.on('request_refresh', function() {
|
|
||||||
for(var universe in setup.universes) {
|
|
||||||
var u = {}
|
|
||||||
for(var i = 0; i < 256; i++) {
|
|
||||||
u[i] = dmx.universes[universe].get(i);
|
|
||||||
}
|
|
||||||
console.log('sending update...')
|
|
||||||
console.log(u)
|
|
||||||
socket.emit('update', universe, u);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
dmx.on('update', function(universe, update){
|
|
||||||
socket.emit('update', universe, update);
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('update', function(universe, update) {
|
|
||||||
dmx.update(universe, update);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue