'use strict';
var util = require('util');
var events = require('events');
var EventEmitter = events.EventEmitter || events;
var SerialPort = require("serialport");

var EXCEPTION_LENGTH = 5;

/**
 * Simulate a modbus-RTU port using buffered serial connection
 */
var RTUBufferedPort = function(path, options) {
    var self = this;

    // options
    if (typeof(options) == 'undefined') options = {};

    // disable auto open, as we handle the open
    options.autoOpen = false;

    // internal buffer
    this._buffer = new Buffer(0);
    this._id = 0;
    this._cmd = 0;
    this._length = 0;
    this.debug = false;

    // create the SerialPort
    this._client= new SerialPort(path, options);

    // register the port data event
    this._client.on('data', function onData(data) {
        // add data to buffer
        self._buffer = Buffer.concat([self._buffer, data]);

        // check if buffer include a complete modbus answer
        var expectedLength = self._length;
        var bufferLength = self._buffer.length ;

        // check data length
        if (expectedLength < 6 || bufferLength < EXCEPTION_LENGTH) return;

        // loop and check length-sized buffer chunks
        var maxOffset = bufferLength - EXCEPTION_LENGTH;
        for (var i = 0; i <= maxOffset; i++) {
            var unitId = self._buffer[i];
            var functionCode = self._buffer[i+1];

            if ( unitId === self._id) {
                if( functionCode === self._cmd || functionCode === (0x80 | self._cmd)) {
                
                    // a valid modbus frame header has been identified, check for expected buffer length
                    if (functionCode === self._cmd && i + expectedLength <= bufferLength) {
                        self._emitData(i, expectedLength);
                        return;
                        
                    } else {
                        if (functionCode === (0x80 | self._cmd) && i + EXCEPTION_LENGTH <= bufferLength) {
                            self._emitData(i, EXCEPTION_LENGTH);
                            return;
                        }
                    }
                    // frame header matches, but still missing bytes pending ... wait for further bytes
                    break;
                }
            }
        }
        
        // cut off illegal RX chars, else buffer will grow and grow ...
        if( i >= 1 ) {
          self._buffer = self._buffer.slice(i,self._buffer.length);
        }
        
    });

    EventEmitter.call(this);
};
util.inherits(RTUBufferedPort, EventEmitter);

/**
 * Emit the received response, cut the buffer and reset the internal vars.
 * @param {number} start the start index of the response within the buffer
 * @param {number} length the length of the response
 * @private
 */
RTUBufferedPort.prototype._emitData = function(start, length) {
    var buffer = this._buffer.slice(start, start + length);

    // emit debug message
    if (this.debug) { this.emit('debug', {action: 'recive', data: buffer}); }

    this.emit('data', buffer);
    this._buffer = this._buffer.slice(start + length);
};

/**
 * Simulate successful port open
 */
RTUBufferedPort.prototype.open = function (callback) {
    this._client.open(callback);
};

/**
 * Simulate successful close port
 */
RTUBufferedPort.prototype.close = function (callback) {
    this._client.close(callback);
};

/**
 * Check if port is open
 */
RTUBufferedPort.prototype.isOpen = function() {
    return this._client.isOpen();
};

/**
 * Send data to a modbus slave
 */
RTUBufferedPort.prototype.write = function (data) {
    // check data length
    if (data.length < 6) {
        // raise an error ?
        return;
    }

    // remember current unit and command
    this._id = data[0];
    this._cmd = data[1];

    // calculate expected answer length
    switch (this._cmd) {
        case 1:
        case 2:
            var length = data.readUInt16BE(4);
            this._length = 3 + parseInt((length - 1) / 8 + 1) + 2;
            break;
        case 3:
        case 4:
            var length = data.readUInt16BE(4);
            this._length = 3 + 2 * length + 2;
            break;
        case 5:
        case 6:
        case 15:
        case 16:
            this._length = 6 + 2;
            break;
        default:
            // raise and error ?
            this._length = 0;
            break;
    }

    // emit debug message
    if (this.debug) { this.emit('debug', {action: 'send', data: data}); }

    // send buffer to slave
    this._client.write(data);
};

module.exports = RTUBufferedPort;

@@ -183,16 +183,45 @@
 GTH = 5;
+%0Avar MAX_BUFFER_LENGTH = 256;
 %0A%0A/**%0A *
@@ -1052,17 +1052,16 @@
 r.length
- 
 ;%0A%0A     
@@ -1160,16 +1160,191 @@
 eturn;%0A%0A
+        // check buffer size for MAX_BUFFER_SIZE%0A        if (bufferLength %3E MAX_BUFFER_LENGTH) %7B%0A            self._buffer = self._buffer.slice(-MAX_BUFFER_LENGTH);%0A        %7D%0A%0A
         
@@ -1601,25 +1601,24 @@
     if (
- 
 unitId 
-=
+!
 == self.
@@ -1626,229 +1626,19 @@
 id) 
-%7B%0A                if( functionCode === self._cmd %7C%7C functionCode === (0x80 %7C self._cmd)) %7B%0A                %0A                    // a valid modbus frame header has been identified, check for expected buffer length%0A        
+continue;%0A%0A
     
@@ -1729,32 +1729,24 @@
             
-        
 self._emitDa
@@ -1780,32 +1780,24 @@
             
-      
-  
 return;%0A    
@@ -1808,62 +1808,10 @@
     
-            %0A                    %7D else %7B%0A            
+%7D%0A
     
@@ -1913,36 +1913,24 @@
             
-            
 self._emitDa
@@ -1966,36 +1966,24 @@
             
-          
-  
 return;%0A    
@@ -1994,48 +1994,11 @@
     
-        
-    %7D%0A                    %7D%0A    
+%7D%0A%0A
     
@@ -2005,20 +2005,16 @@
         
-    
 // frame
@@ -2065,275 +2065,67 @@
 ding
- ... wait for further bytes%0A                    break;%0A                %7D%0A            %7D%0A        %7D%0A        %0A        // cut off illegal RX chars, else buffer will grow and grow ...%0A        if( i %3E= 1 ) %7B%0A          self._buffer = self._buffer.slice(i,self._buffer.length)
+%0A            if (functionCode === (0x7f & self._cmd)) break
 ;%0A  
@@ -2136,17 +2136,8 @@
   %7D%0A
-        %0A
     

refactor nested if's in code