Stairs/web/client.js
2017-03-25 16:36:04 +01:00

233 lines
5.5 KiB
JavaScript

var dgram = require('dgram');
var protocol = require('./protocol');
var BufferReader = require('buffer-reader');
var responseHandlers = {};
function registerResponseHandler(command, callback)
{
if (!responseHandlers.hasOwnProperty(command))
responseHandlers[command] = [callback];
else
responseHandlers[command].push(callback);
}
function callResponseHandlers(command, reader, error)
{
if (!responseHandlers.hasOwnProperty(command))
return;
newHandlers = [];
responseHandlers[command].forEach(function(callback)
{
if (!callback(reader, error))
newHandlers.push(callback);
});
responseHandlers[command] = newHandlers;
}
var serverHost = '';
var serverPort = 0;
var client = dgram.createSocket('udp4');
client.on('message', function (message, remote)
{
console.log(message.toString('hex'));
if (message.length < 2)
return;
var reader = new BufferReader(message);
if (reader.nextInt8() !== protocol.Command.Reply)
return;
var command = reader.nextInt8();
if (command === protocol.Command.Error)
callResponseHandlers(reader.nextInt8(), reader, true)
else
callResponseHandlers(command, reader, false);
});
function requestResponse(buffer, callback)
{
if (buffer === null || buffer.length == 0) return;
console.log('> ' + buffer.toString('hex'));
var command = buffer.readInt8(0);
var cancelled = false;
var timeout = setTimeout(function()
{
cancelled = true;
callback(null, true);
clearTimeout(timeout);
}, 2000);
registerResponseHandler(command, function(reader, error)
{
if (cancelled) return;
clearTimeout(timeout);
callback(reader, error);
return true;
});
client.send(buffer, 0, buffer.length, serverPort, serverHost, function(err, bytes)
{
if (err)
onError();
});
}
function readModeData(mode, reader)
{
switch (mode)
{
case protocol.Mode.Static:
return {
brightness: reader.nextInt16LE()
};
case protocol.Mode.Custom:
var values = [];
while (reader.tell() < reader.buf.length)
values.push(reader.nextInt16LE());
return {
brightness: values
};
case protocol.Mode.Alternate:
return {
interval: reader.nextInt16LE(),
brightness: reader.nextInt16LE()
};
case protocol.Mode.Slide:
return {
interval: reader.nextInt16LE(),
brightness: reader.nextInt16LE(),
direction: reader.nextInt8(),
fadeOutTime: reader.nextInt16LE()
};
}
return null;
}
function lsb(value) { return value & 0xFF; }
function msb(value) { return (value >> 8) & 0xFF; }
function writeModeData(mode, data)
{
switch (mode)
{
case protocol.Mode.Static:
if (typeof(data.brightness) == 'undefined') data.brightness = 0;
return new Buffer([protocol.Command.SetMode, mode, lsb(data.brightness), msb(data.brightness)]);
case protocol.Mode.Custom:
var brightness = typeof(data.brightness) !== 'undefined' ? data.brightness.split(',') : [];
var valueCount = Math.min(16, brightness.length);
var buffer = Buffer.alloc(2 + (valueCount * 2));
buffer.writeInt8(protocol.Command.SetMode, 0);
buffer.writeInt8(mode, 1);
for (var index = 0; index < valueCount; index++)
buffer.writeInt16LE(brightness[index], 2 + (index * 2));
return buffer;
case protocol.Mode.Alternate:
if (typeof(data.brightness) == 'undefined') data.brightness = 0;
if (typeof(data.interval) == 'undefined') data.interval = 500;
return new Buffer([protocol.Command.SetMode, mode,
lsb(data.interval), msb(data.interval),
lsb(data.brightness), msb(data.brightness)]);
case protocol.Mode.Slide:
if (typeof(data.brightness) == 'undefined') data.brightness = 0;
if (typeof(data.interval) == 'undefined') data.interval = 500;
if (typeof(data.direction) == 'undefined') data.direction = 0;
if (typeof(data.fadeOutTime) == 'undefined') data.fadeOutTime = 0;
return new Buffer([protocol.Command.SetMode, mode,
lsb(data.interval), msb(data.interval),
lsb(data.brightness), msb(data.brightness),
data.direction,
lsb(data.fadeOutTime), msb(data.fadeOutTime)]);
}
}
module.exports =
{
init: function(host, port)
{
serverHost = host;
serverPort = port;
},
ping: function(callback)
{
requestResponse(new Buffer([protocol.Command.Ping]),
function(reader, error)
{
if (!error)
{
callback(
{
stepCount: reader.nextInt8()
}, false);
}
else
callback(null, true);
});
},
getMode: function(callback)
{
requestResponse(new Buffer([protocol.Command.GetMode]),
function(reader, error)
{
if (!error)
{
var data = { mode: reader.nextInt8() };
data.data = readModeData(data.mode, reader);
callback(data, false);
}
else
callback(null, true);
});
},
setMode: function(mode, data, callback)
{
if (!protocol.Mode.hasOwnProperty(mode))
return;
requestResponse(writeModeData(protocol.Mode[mode], data),
function(reader, error)
{
if (!error)
{
var data = { mode: reader.nextInt8() };
data.data = readModeData(data.mode, reader);
callback(data, false);
}
else
callback(null, true);
});
}
}