233 lines
5.5 KiB
JavaScript
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);
|
||
|
});
|
||
|
}
|
||
|
}
|