Created
June 2, 2015 04:57
-
-
Save guileen/121ffeb66fad521a851a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @param {Socket} socket auto handle 'data' event, and emit 'packet' event. | |
* @param {Object} options options params | |
* options.headSize the size of header | |
* options.getBodySize function(headBuffer) return bodySize | |
*/ | |
exports.autoParsePacket = function (socket, options) { | |
var headSize = options.headSize; | |
var getBodySize = options.getBodySize; | |
if(!headSize || headSize <= 0) { | |
throw new Error('headSize should be a positive integer'); | |
} | |
if(!getBodySize) { | |
throw new Error('getBodySize function is required'); | |
} | |
var STATE_HEAD = 0; | |
var STATE_BODY = 1; | |
var state = STATE_HEAD; | |
var headOffset = 0; | |
// init headBuffer, we can reuse it cause it is fixed size. | |
var headBuffer = new Buffer(headSize); | |
var packetSize = 0; | |
var packetOffset = 0; | |
var packetBuffer; | |
socket.on('data', function (data) { | |
// data reading offset | |
var offset = 0, end = data.length; | |
// not read to the end | |
while(offset < end) { | |
if(state == STATE_HEAD) { | |
offset = parseHead(data, offset); | |
} else if (state == STATE_BODY) { | |
offset = parseBody(data, offset); | |
} | |
} | |
}); | |
// read headBuffer from data start from offset. | |
// if ready init packetBuffer by headBuffer. | |
function parseHead(data, offset) { | |
var headEnd = Math.min(data.length, offset + headSize - headOffset); | |
data.copy(headBuffer, headOffset, offset, headEnd); | |
headOffset += (headEnd - offset); | |
if(headOffset === headSize) { | |
packetSize = headSize + getBodySize(headBuffer); | |
packetBuffer = new Buffer(packetSize); | |
headBuffer.copy(packetBuffer); | |
packetOffset = headSize; | |
state = STATE_BODY; | |
} | |
return headEnd; | |
} | |
// read packetBuffer from data start from offset | |
// if ready read next packet head. | |
function parseBody(data, offset) { | |
var bodyEnd = Math.min(data.length, offset + packetSize - packetOffset); | |
data.copy(packetBuffer, packetOffset, offset, bodyEnd); | |
packetOffset += (bodyEnd - offset); | |
if(packetOffset == packetSize) { | |
socket.emit('packet', packetBuffer); | |
headOffset = 0; | |
packetOffset = 0; | |
packetSize = 0; | |
packetBuffer = null; | |
state = STATE_HEAD; | |
} | |
return bodyEnd; | |
} | |
} | |
exports.splitReport0x30 = function(packet) { | |
// 0 func_code | |
// 1 packet_length | |
// 2-5 nodeid | |
// 6 status | |
// a. 7-8 volt | |
// b. 7-10 in | |
// c. 11-14 out | |
// -2 -1 count | |
var packets = []; | |
var skip = 0; | |
while(skip < packet.length) { | |
var len = packet[skip + 1]; | |
if(skip + len > packet.length) throw new Error('bad cmd0x30 packet'); | |
packets.push(packet.slice(skip, skip += len)); | |
} | |
return packets; | |
} | |
exports.crc16 = function (buffer, len) { | |
var crc = 0xffff; | |
for (var i = 0; i < len; i++) { | |
crc = ((crc ^ buffer[i]) & 0x00ff) + (crc & 0xff00); | |
for (var bit = 0; bit < 8; bit++) { | |
if ((crc & 0x0001) === 0x0000) { | |
crc >>= 1; | |
} | |
else { | |
crc >>= 1; | |
crc ^= 0xa001; | |
} | |
} | |
} | |
crc = ((crc & 0x00ff) << 8) + ((crc & 0xff00) >> 8); | |
return(crc); | |
} | |
exports.sendPacket = function (sock, packet) { | |
exports.makeCrcPacket(packet); | |
sock.write(packet); | |
} | |
/** | |
* 构造一个合法的数据包 | |
*/ | |
exports.makeCrcPacket = function (packet) { | |
var len = packet.length; | |
packet[0] = 0xaa; | |
packet.writeUInt16BE(packet.length - 4, 2); | |
var crc = exports.crc16(packet, len - 2); | |
packet.writeUInt16BE(crc, len - 2); | |
return packet; | |
} | |
/** | |
* 检验一个包是否合法 | |
*/ | |
exports.isValidPacket = function (packet) { | |
var len = packet.length; | |
return packet[0] == 0xaa && packet.readUInt16BE(len-2)=== exports.crc16(packet,len-2); | |
} | |
exports.replyId = function (sock, funcCode, id) { | |
var packet = new Buffer(10); | |
packet[1] = funcCode; | |
packet.writeUInt32BE(id, 4); | |
exports.sendPacket(sock, packet); | |
} | |
/** | |
* 分隔一个包 | |
* @return {Array[Buffer]} | |
*/ | |
exports.slicePacket = function(packet, sliceSize, offset) { | |
offset = offset || 0; | |
var end, len = packet.length; | |
var slices = []; | |
while(offset < packet.length) { | |
end = offset + sliceSize; | |
if(end > len) break; | |
slices.push(packet.slice(offset, end)); | |
offset = end; | |
} | |
return slices; | |
} | |
exports.readNodeKey = function(buffer, offset) { | |
var key = buffer.readUInt32BE(offset); | |
var type = key % 100; | |
var id = (key - type) / 100; | |
return [key, id, type]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment