multiwii-msp
Version:
NodeJS MultiWii Serial Protocol to send or receive commands from MultiWii via TCP/IP
111 lines (95 loc) • 2.96 kB
JavaScript
/**
*
* Protocol format
* 0 - $
* 1 - M
* 2 - <!>
* 3 - payload length
* 4 - code
* 5-length - payload
* 5+length+1 - crc
*
* @constructor
*/
function MspProtocol() {
this._data = [];
}
/**
*
* @param {int} code - command code
* @param {Buffer|null} [data] - payload
* @return {Buffer}
*/
MspProtocol.prototype.serialize = function (code, data) {
var i, length, crc, buffer;
length = data === undefined || data === null ? 0 : data.length;
buffer = new Buffer(6 + length);
buffer.write('$M<');
buffer.writeUInt8(length, 3);
buffer.writeUInt8(code, 4);
crc = 0x00 ^ code ^ length;
for (i = 0; i < length; i = i + 1) {
crc ^= data.readUInt8(i);
buffer.writeUInt8(data.readUInt8(i), i + 5);
}
buffer.writeUInt8(crc, buffer.length - 1);
return buffer;
};
module.exports = MspProtocol;
/**
* Buffer from attribute is stored in data array
* Method unserialize first valid package from data array
* The valid package bits or invalid bits are removed from data array
*
* @param {Buffer} [data] - input data
* @return {{valid:boolean}|{valid: boolean, code: int, length: int, data: Buffer}}
*/
MspProtocol.prototype.unserialize = function (data) {
var i, length, code, crc, offset, valid, response;
if (data) {
for (i = 0; i < data.length; i = i + 1) {
this._data[this._data.length] = data.readUInt8(i);
}
}
valid = false;
offset = 0;
while (offset < this._data.length) {
if (this._data[offset] !== 36) {
offset = offset + 1;
} else if (this._data[offset + 1] !== 77) {
offset = offset + 2;
} else if (this._data[offset + 2] !== 62) {
offset = offset + 3;
} else if (this._data[offset + 3] <= this._data.length - 6 - offset) {
length = this._data[offset + 3];
code = this._data[offset + 4];
crc = 0x00 ^ code ^ length;
for (i = 0; i < length; i = i + 1) {
crc ^= this._data[offset + 5 + i];
}
if (crc !== this._data[offset + 5 + length]) {
offset = offset + 5 + length;
} else {
data = new Buffer(length);
for (i = 0; i < length; i = i + 1) {
data.writeUInt8(this._data[offset + 5 + i], i);
}
valid = true;
offset = offset + 5 + length + 1;
break;
}
} else {
break;
}
}
this._data = this._data.slice(offset);
response = {
valid: valid
};
if (valid) {
response.code = code;
response.length = length;
response.data = data;
}
return response;
};