Skip to content

Add crossfade and update UI #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: lights
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
262 changes: 111 additions & 151 deletions index.html
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,166 +1,126 @@
<!DOCTYPE html>
<html>
<head>
<title>DSL lights</title>
<meta name="mobile-web-app-capable" content="yes" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" sizes="82x99" href="http://www.dimsumlabs.com/wp-content/uploads/2014/08/logo_dsl_text_82x99.png"/>
<link rel="stylesheet" href="gh-fork-ribbon.css" />
</head>
<body style="margin:0">
<canvas id="colorspace" width="1362" height="680"></canvas>
<div style="position:absolute;top:0;left:0">
<select id="host">
<option value="helios.lan">Front (window)</option>
<option value="helios2.lan">Back (screen)</option>
<option value="helios.lan helios2.lan">Both</option>
</select>
<input type="checkbox" id="adc" value="adc"><label for="adc">ADC</label>
<head>
<title>Helios</title>
<link href="https://fonts.googleapis.com/css?family=Teko:300" rel="stylesheet">
<link rel="stylesheet" href="./light.css">
</head>
<body>
<canvas id="colorspace"></canvas>
<div class="toolbar">
<div class="title-section">
<h1>Helios</h1>

<div class="position-select">
<button id="btn-1" onclick="changeHost(0)" disabled>printerside</button>
<button id="btn-2" onclick="changeHost(1)">doorside</button>
</div>
</div>

<div class="slider-section">
<input type="range" value="100" id="slider-brightness" oninput="drawCanvas(this.value)">
</div>
</div>
<a class="github-fork-ribbon right-top" href="https://github.com/dimsumlabs/nodemcu-httpd/tree/lights" title="Fork me on GitHub">Fork me on GitHub</a>
</body>

<script type="text/javascript">
(function (){
var host = location.hostname;
document.getElementById('host').selectedIndex = location.hostname.lastIndexOf("helios2") === 0 ? 1 : 0;
document.getElementById('host').focus();
document.getElementById('host').addEventListener('change', function(event) {
host = event.target.value;
});
document.getElementById('adc').addEventListener('click', function(event) {
event.target.disabled = true;
var ms = event.target.checked ? 5 : 0;
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState == 4) event.target.disabled = false;
}
// Only helios.lan has ADC hooked up
req.open("POST", '//helios.lan/adc.lua?ms=' + ms, true);
req.send();
}, false);

var canvas = document.getElementById('colorspace');
var ctx = canvas.getContext('2d');

function drawCanvas() {
var colours = ctx.createLinearGradient(30, 0, window.innerWidth, 0);
for(var i=0; i <= 360; i+=10) {
colours.addColorStop(i/360, 'hsl(' + i + ', 100%, 50%)');
}

ctx.fillStyle = colours;
ctx.fillRect(30, 0, window.innerWidth, window.innerHeight);

var luminance = ctx.createLinearGradient(0, 0, 0, ctx.canvas.height);
luminance.addColorStop(0, '#ffffff');
luminance.addColorStop(0.05, '#ffffff');
luminance.addColorStop(0.5, 'rgba(255,255,255,0)');
luminance.addColorStop(0.5, 'rgba(0,0,0,0)');
luminance.addColorStop(0.95, '#000000');
luminance.addColorStop(1, '#000000');

ctx.fillStyle = luminance;
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);

var greyscale = ctx.createLinearGradient(0, 30, 0, ctx.canvas.height);
greyscale.addColorStop(0, '#ffffff');
greyscale.addColorStop(1, '#000000');

ctx.fillStyle = greyscale;
ctx.fillRect(0, 0, 30, ctx.canvas.height);
}

var canSend = true;
var pending = false;
var rr=127, gg=127, bb=127;
function sendColour() {
function colourCorrect(v) {
v = Math.max(0, Math.min(255, v));
return Math.round(1023-(v*v)/64);
}

var params = [
'r=' + colourCorrect(rr),
'g=' + colourCorrect(gg),
'b=' + colourCorrect(bb)
].join('&');
canSend = pending = false;
var hosts = host.split(' ');
for (var i=0; i<hosts.length; ++i) {
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState == 4) {
setTimeout(function() { if (pending) sendColour(); else canSend = true; }, 100);
}
}
req.open("POST", '//'+hosts[i]+'/rgb.lua?' + params, true);
req.send();
}
var HOSTS = [
'helios2.lan',
'helios.lan'
];
var host = HOSTS[0];

var canvas = document.getElementById('colorspace');
var btn1 = document.getElementById('btn-1');
var btn2 = document.getElementById('btn-2');
var ctx = canvas.getContext('2d');

drawCanvas();

function changeHost(id) {
this.host = HOSTS[id];
if(id) {
btn1.disabled = false;
btn2.disabled = true;
} else {
btn1.disabled = true;
btn2.disabled = false;
}
}

function sendColour(rgb) {
var params = [
'r=' + rgb[0],
'g=' + rgb[1],
'b=' + rgb[2]
].join('&');

var req = new XMLHttpRequest();
console.log(params);
req.open("POST", 'http://' + host + '/rgb.lua?' + params, true);
req.send();
}

function colourCorrect(v) {
return Math.round(1023-(v*v)/64);
}

function handleEvent(clientX, clientY) {
var data = ctx.getImageData(clientX, clientY, 1, 1).data;
var rgb = [];
for(var i=0; i<3; i++) {
rgb[i] = colourCorrect(data[i]);
}
sendColour(rgb);
}

canvas.addEventListener("touchmove", function(event){
handleEvent(event.touches[0].clientX, event.touches[0].clientY);
}, false);

var mouseDown = false;
document.ontouchmove = function(e) {e.preventDefault()};
canvas.addEventListener('mousedown', function(event) {
if (event.button == 0) {
handleEvent(event.x, event.y);
mouseDown = true;
}
}, false);

function setColour(r, g, b) {
if (r == rr && g == gg && b == bb) {
return;
}
if (r < 0 && g < 0 && b < 0) {
return;
}
if (r > 255 && g > 255 && b > 255) {
return;
}
rr = r;
gg = g;
bb = b;
pending = true;
if (canSend) {
sendColour();
}
document.addEventListener('mouseup', function(event) {
if (event.button == 0) {
mouseDown = false;
}
}, false);

function handleEvent(clientX, clientY) {
var data = ctx.getImageData(clientX, clientY, 1, 1).data;
setColour(data[0], data[1], data[2]);
canvas.addEventListener('mousemove', function(event) {
if (mouseDown) {
handleEvent(event.x, event.y);
}
canvas.addEventListener("touchmove", function(event){
handleEvent(event.touches[0].clientX, event.touches[0].clientY);
}, false);

canvas.addEventListener('mousewheel', function(event) {
var delta = Math.min(1, Math.max(-1, event.wheelDelta || -event.detail));
setColour(rr - delta, gg - delta, bb - delta);
event.preventDefault();
return false;
}, false);

var mouseDown = false;
canvas.addEventListener('mousedown', function(event) {
if (event.button == 0) {
handleEvent(event.clientX, event.clientY);
mouseDown = true;
}
}, false);
document.addEventListener('mouseup', function(event) {
if (event.button == 0) {
mouseDown = false;
}
}, false);
canvas.addEventListener('mousemove', function(event) {
if (mouseDown) {
handleEvent(event.clientX, event.clientY);
}
}, false);

function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
drawCanvas();
}, false);

function drawCanvas(brightness = 100) {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var brt = Math.round((brightness / 100) * 255);
var colours = ctx.createLinearGradient(30, 0, canvas.width, 0);
for(var i=0; i <= 360; i+=10) {
colours.addColorStop(i/360, 'hsl(' + i + ', 100%, '+ brightness/2 + '%)');
}
window.addEventListener('resize', resizeCanvas, false);

resizeCanvas();
drawCanvas();
ctx.fillStyle = colours;
ctx.fillRect(0, 0, canvas.width, canvas.height);

var luminance = ctx.createLinearGradient(0, 0, 0, canvas.height);
luminance.addColorStop(0.0, 'rgba(' + brt + ',' + brt + ',' + brt + ',' + brightness/100 + ')');
luminance.addColorStop(0.5, 'rgba(255,255,255,0)');
luminance.addColorStop(0.5, 'rgba(0,0,0,0)');
luminance.addColorStop(1, '#000000');

ctx.fillStyle = luminance;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}

document.ontouchmove = function(e) {e.preventDefault()};
})();
</script>
</body>
</html>
44 changes: 34 additions & 10 deletions rgb.lua
Original file line number Diff line number Diff line change
@@ -1,19 +1,43 @@
PIN_R = 5
PIN_G = 6
PIN_B = 7

FADE_MS = 8
INTERVAL = 5
getduty = pwm.getduty
setduty = pwm.setduty

function fade(pin, x, tid)
local a = getduty(pin)
local mult = 1
if a>x then mult = -1 end

tmr.alarm(tid, FADE_MS, tmr.ALARM_AUTO, function()
if math.abs(x-a) <= INTERVAL then
setduty(pin, x)
tmr.unregister(tid)
elseif a~=x then
setduty(pin, a)
a = a + (INTERVAL * mult)
end
end)
end

return function (connection, req)
local setduty = pwm.setduty
local r = tonumber(req:match("r=([0-9]+)"))
local g = tonumber(req:match("g=([0-9]+)"))
local b = tonumber(req:match("b=([0-9]+)"))

local arg = tonumber(req:match("r=([0-9]+)"))
if arg then
setduty(5, arg)
if r then
fade(PIN_R, r, 0)
end

arg = tonumber(req:match("g=([0-9]+)"))
if arg then
setduty(6, arg)
if g then
fade(PIN_G, g, 1)
end

arg = tonumber(req:match("b=([0-9]+)"))
if arg then
setduty(7, arg)
if b then
fade(PIN_B, b, 2)
end

-- Send back JSON response.
Expand Down
Loading