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() {
|
||||
new_vals = {}
|
||||
var 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))
|
||||
}
|
||||
|
|
|
@ -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': {
|
||||
channels: ['ctrl', 'dimmer', 'strobe', 'red0', 'green0', 'blue0', 'red1', 'green1', 'blue1', 'red2', 'green2', 'blue2'],
|
||||
ranges: {
|
||||
|
@ -31,9 +37,6 @@ exports.devices = {
|
|||
}
|
||||
}
|
||||
},
|
||||
'showtec-multidim2': {
|
||||
channels: ['1', '2', '3', '4']
|
||||
},
|
||||
'stairville-led-par-56': {
|
||||
channels: ['ctrl', 'red', 'green', 'blue', 'speed'],
|
||||
ranges: {
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
exports.setup = {
|
||||
presets: [
|
||||
module.exports = {
|
||||
"server": {
|
||||
"listen_port": 8080,
|
||||
"listen_host": "::",
|
||||
|
||||
// drop privileges to:
|
||||
// "uid": "www-data",
|
||||
// "gid": "www-data"
|
||||
},
|
||||
"presets": [
|
||||
{
|
||||
label: 'White',
|
||||
label: "White",
|
||||
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 }
|
||||
}
|
||||
|
@ -34,7 +42,8 @@ exports.setup = {
|
|||
universes: {
|
||||
'office': {
|
||||
'output': {
|
||||
'driver': 'enttec-usb-dmx-pro',
|
||||
// 'driver': 'enttec-usb-dmx-pro',
|
||||
'driver': 'null',
|
||||
'device': 0
|
||||
},
|
||||
'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() {
|
||||
this.universes = {}
|
||||
this.drivers = {}
|
||||
|
||||
this.registerDriver('null', require('./drivers/null'))
|
||||
this.registerDriver('enttec-usb-dmx-pro', require('./drivers/enttec-usb-dmx-pro'))
|
||||
}
|
||||
|
||||
util.inherits(DMX, EventEmitter)
|
||||
|
||||
DMX.devices = require('./devices')
|
||||
DMX.Animation = require('./anim')
|
||||
|
||||
DMX.prototype.registerDriver = function(name, module) {
|
||||
this.drivers[name] = module
|
||||
}
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
<title>DMX Lichtschalter</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/static/bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet">
|
||||
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
background: #222;
|
||||
|
@ -45,7 +44,7 @@
|
|||
</style>
|
||||
<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="/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>
|
||||
function get_html_id(universe, channel) {
|
||||
|
|
54
package.json
54
package.json
|
@ -1,26 +1,32 @@
|
|||
{
|
||||
"name": "dmx",
|
||||
"version": "0.0.1",
|
||||
"author": "Sebastian Wiedenroth <wiedi@frubar.net>",
|
||||
"description": "DMX library and webservice",
|
||||
"url": "https://github.com/wiedi/node-dmx",
|
||||
"main": "dmx.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/wiedi/node-dmx.git"
|
||||
},
|
||||
"keywords": [
|
||||
"DMX",
|
||||
"light control"
|
||||
],
|
||||
"dependencies": {
|
||||
"ftdi": "1.0.x",
|
||||
"socket.io": "0.9.x"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"name": "MIT",
|
||||
"url": "http://www.opensource.org/licenses/mit-license.php"
|
||||
}
|
||||
]
|
||||
"name": "dmx",
|
||||
"version": "0.0.1",
|
||||
"author": "Sebastian Wiedenroth <wiedi@frubar.net>",
|
||||
"description": "DMX library and webservice",
|
||||
"url": "https://github.com/wiedi/node-dmx",
|
||||
"main": "dmx.js",
|
||||
"bin": {
|
||||
"dmx-web": "./dmx-web.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/wiedi/node-dmx.git"
|
||||
},
|
||||
"keywords": [
|
||||
"DMX",
|
||||
"light control"
|
||||
],
|
||||
"dependencies": {
|
||||
"ftdi": "1.0.x",
|
||||
"socket.io": "0.9.x",
|
||||
"connect": "2.11.x",
|
||||
"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